blob: 7c8d314dc528f238c219671b171e7a290025beb2 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* Tester for string functions.
2 Copyright (C) 1995-2001, 2003, 2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20#ifndef _GNU_SOURCE
21#define _GNU_SOURCE
22#endif
23
24/* Make sure we don't test the optimized inline functions if we want to
25 test the real implementation. */
26#if !defined DO_STRING_INLINES
27#undef __USE_STRING_INLINES
28#endif
29
30#include <errno.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <strings.h>
35#include <fcntl.h>
36
37#ifdef __UCLIBC__
38# define __TEST_BSD_FUNCS__
39#else
40# undef __TEST_BSD_FUNCS__
41#endif
42
43#if defined(__UCLIBC_SUSV3_LEGACY__) || defined(__UCLIBC_SUSV3_LEGACY_MACROS__)
44# define __TEST_SUSV3_LEGACY__
45#else
46# undef __TEST_SUSV3_LEGACY__
47#endif
48
49#define STREQ(a, b) (strcmp((a), (b)) == 0)
50
51const char *it = "<UNSET>"; /* Routine name for message routines. */
52size_t errors = 0;
53
54/* Complain if condition is not true. */
55static void
56check (int thing, int number)
57{
58 if (!thing)
59 {
60 printf("%s flunked test %d\n", it, number);
61 ++errors;
62 }
63}
64
65/* Complain if first two args don't strcmp as equal. */
66static void
67equal (const char *a, const char *b, int number)
68{
69 check(a != NULL && b != NULL && STREQ (a, b), number);
70}
71
72char one[50];
73char two[50];
74char *cp;
75
76static void
77test_strcmp (void)
78{
79 it = "strcmp";
80 check (strcmp ("", "") == 0, 1); /* Trivial case. */
81 check (strcmp ("a", "a") == 0, 2); /* Identity. */
82 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
83 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
84 check (strcmp ("abcd", "abc") > 0, 5);
85 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
86 check (strcmp ("abce", "abcd") > 0, 7);
87 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
88 check (strcmp ("a\203", "a\003") > 0, 9);
89
90 {
91 char buf1[0x40], buf2[0x40];
92 int i, j;
93 for (i=0; i < 0x10; i++)
94 for (j = 0; j < 0x10; j++)
95 {
96 int k;
97 for (k = 0; k < 0x3f; k++)
98 {
99 buf1[k] = '0' ^ (k & 4);
100 buf2[k] = '4' ^ (k & 4);
101 }
102 buf1[i] = buf1[0x3f] = 0;
103 buf2[j] = buf2[0x3f] = 0;
104 for (k = 0; k < 0xf; k++)
105 {
106 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
107 check (strcmp (buf1+i,buf2+j) == 0, cnum);
108 buf1[i+k] = 'A' + i + k;
109 buf1[i+k+1] = 0;
110 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
111 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
112 buf2[j+k] = 'B' + i + k;
113 buf2[j+k+1] = 0;
114 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
115 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
116 buf2[j+k] = 'A' + i + k;
117 buf1[i] = 'A' + i + 0x80;
118 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
119 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
120 buf1[i] = 'A' + i;
121 }
122 }
123 }
124}
125
126#define SIMPLE_COPY(fn, n, str, ntest) \
127 do { \
128 int __n; \
129 char *cp; \
130 for (__n = 0; __n < (int) sizeof (one); ++__n) \
131 one[__n] = 'Z'; \
132 fn (one, str); \
133 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
134 check (*cp == '0' + (n % 10), ntest); \
135 check (*cp == '\0', ntest); \
136 } while (0)
137
138static void
139test_strcpy (void)
140{
141 int i;
142 it = "strcpy";
143 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
144 equal (one, "abcd", 2); /* Basic test. */
145
146 (void) strcpy (one, "x");
147 equal (one, "x", 3); /* Writeover. */
148 equal (one+2, "cd", 4); /* Wrote too much? */
149
150 (void) strcpy (two, "hi there");
151 (void) strcpy (one, two);
152 equal (one, "hi there", 5); /* Basic test encore. */
153 equal (two, "hi there", 6); /* Stomped on source? */
154
155 (void) strcpy (one, "");
156 equal (one, "", 7); /* Boundary condition. */
157
158 for (i = 0; i < 16; i++)
159 {
160 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
161 equal (one + i, "hi there", 8 + (i * 2));
162 (void) strcpy (two, one + i); /* Unaligned source. */
163 equal (two, "hi there", 9 + (i * 2));
164 }
165
166 SIMPLE_COPY(strcpy, 0, "", 41);
167 SIMPLE_COPY(strcpy, 1, "1", 42);
168 SIMPLE_COPY(strcpy, 2, "22", 43);
169 SIMPLE_COPY(strcpy, 3, "333", 44);
170 SIMPLE_COPY(strcpy, 4, "4444", 45);
171 SIMPLE_COPY(strcpy, 5, "55555", 46);
172 SIMPLE_COPY(strcpy, 6, "666666", 47);
173 SIMPLE_COPY(strcpy, 7, "7777777", 48);
174 SIMPLE_COPY(strcpy, 8, "88888888", 49);
175 SIMPLE_COPY(strcpy, 9, "999999999", 50);
176 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
177 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
178 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
179 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
180 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
181 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
182 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
183
184 /* Simple test using implicitly coerced `void *' arguments. */
185 const void *src = "frobozz";
186 void *dst = one;
187 check (strcpy (dst, src) == dst, 1);
188 equal (dst, "frobozz", 2);
189}
190
191static void
192test_stpcpy (void)
193{
194 it = "stpcpy";
195 check ((stpcpy (one, "a") - one) == 1, 1);
196 equal (one, "a", 2);
197
198 check ((stpcpy (one, "ab") - one) == 2, 3);
199 equal (one, "ab", 4);
200
201 check ((stpcpy (one, "abc") - one) == 3, 5);
202 equal (one, "abc", 6);
203
204 check ((stpcpy (one, "abcd") - one) == 4, 7);
205 equal (one, "abcd", 8);
206
207 check ((stpcpy (one, "abcde") - one) == 5, 9);
208 equal (one, "abcde", 10);
209
210 check ((stpcpy (one, "abcdef") - one) == 6, 11);
211 equal (one, "abcdef", 12);
212
213 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
214 equal (one, "abcdefg", 14);
215
216 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
217 equal (one, "abcdefgh", 16);
218
219 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
220 equal (one, "abcdefghi", 18);
221
222 check ((stpcpy (one, "x") - one) == 1, 19);
223 equal (one, "x", 20); /* Writeover. */
224 equal (one+2, "cdefghi", 21); /* Wrote too much? */
225
226 check ((stpcpy (one, "xx") - one) == 2, 22);
227 equal (one, "xx", 23); /* Writeover. */
228 equal (one+3, "defghi", 24); /* Wrote too much? */
229
230 check ((stpcpy (one, "xxx") - one) == 3, 25);
231 equal (one, "xxx", 26); /* Writeover. */
232 equal (one+4, "efghi", 27); /* Wrote too much? */
233
234 check ((stpcpy (one, "xxxx") - one) == 4, 28);
235 equal (one, "xxxx", 29); /* Writeover. */
236 equal (one+5, "fghi", 30); /* Wrote too much? */
237
238 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
239 equal (one, "xxxxx", 32); /* Writeover. */
240 equal (one+6, "ghi", 33); /* Wrote too much? */
241
242 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
243 equal (one, "xxxxxx", 35); /* Writeover. */
244 equal (one+7, "hi", 36); /* Wrote too much? */
245
246 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
247 equal (one, "xxxxxxx", 38); /* Writeover. */
248 equal (one+8, "i", 39); /* Wrote too much? */
249
250 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
251 equal (one, "abc", 41);
252 equal (one + 4, "xxx", 42);
253
254 SIMPLE_COPY(stpcpy, 0, "", 43);
255 SIMPLE_COPY(stpcpy, 1, "1", 44);
256 SIMPLE_COPY(stpcpy, 2, "22", 45);
257 SIMPLE_COPY(stpcpy, 3, "333", 46);
258 SIMPLE_COPY(stpcpy, 4, "4444", 47);
259 SIMPLE_COPY(stpcpy, 5, "55555", 48);
260 SIMPLE_COPY(stpcpy, 6, "666666", 49);
261 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
262 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
263 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
264 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
265 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
266 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
267 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
268 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
269 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
270 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
271}
272
273static void
274test_stpncpy (void)
275{
276 it = "stpncpy";
277 memset (one, 'x', sizeof (one));
278 check (stpncpy (one, "abc", 2) == one + 2, 1);
279 check (stpncpy (one, "abc", 3) == one + 3, 2);
280 check (stpncpy (one, "abc", 4) == one + 3, 3);
281 check (one[3] == '\0' && one[4] == 'x', 4);
282 check (stpncpy (one, "abcd", 5) == one + 4, 5);
283 check (one[4] == '\0' && one[5] == 'x', 6);
284 check (stpncpy (one, "abcd", 6) == one + 4, 7);
285 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
286}
287
288static void
289test_strcat (void)
290{
291 it = "strcat";
292 (void) strcpy (one, "ijk");
293 check (strcat (one, "lmn") == one, 1); /* Returned value. */
294 equal (one, "ijklmn", 2); /* Basic test. */
295
296 (void) strcpy (one, "x");
297 (void) strcat (one, "yz");
298 equal (one, "xyz", 3); /* Writeover. */
299 equal (one+4, "mn", 4); /* Wrote too much? */
300
301 (void) strcpy (one, "gh");
302 (void) strcpy (two, "ef");
303 (void) strcat (one, two);
304 equal (one, "ghef", 5); /* Basic test encore. */
305 equal (two, "ef", 6); /* Stomped on source? */
306
307 (void) strcpy (one, "");
308 (void) strcat (one, "");
309 equal (one, "", 7); /* Boundary conditions. */
310 (void) strcpy (one, "ab");
311 (void) strcat (one, "");
312 equal (one, "ab", 8);
313 (void) strcpy (one, "");
314 (void) strcat (one, "cd");
315 equal (one, "cd", 9);
316}
317
318static void
319test_strncat (void)
320{
321 /* First test it as strcat, with big counts, then test the count
322 mechanism. */
323 it = "strncat";
324 (void) strcpy (one, "ijk");
325 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
326 equal (one, "ijklmn", 2); /* Basic test. */
327
328 (void) strcpy (one, "x");
329 (void) strncat (one, "yz", 99);
330 equal (one, "xyz", 3); /* Writeover. */
331 equal (one+4, "mn", 4); /* Wrote too much? */
332
333 (void) strcpy (one, "gh");
334 (void) strcpy (two, "ef");
335 (void) strncat (one, two, 99);
336 equal (one, "ghef", 5); /* Basic test encore. */
337 equal (two, "ef", 6); /* Stomped on source? */
338
339 (void) strcpy (one, "");
340 (void) strncat (one, "", 99);
341 equal (one, "", 7); /* Boundary conditions. */
342 (void) strcpy (one, "ab");
343 (void) strncat (one, "", 99);
344 equal (one, "ab", 8);
345 (void) strcpy (one, "");
346 (void) strncat (one, "cd", 99);
347 equal (one, "cd", 9);
348
349 (void) strcpy (one, "ab");
350 (void) strncat (one, "cdef", 2);
351 equal (one, "abcd", 10); /* Count-limited. */
352
353 (void) strncat (one, "gh", 0);
354 equal (one, "abcd", 11); /* Zero count. */
355
356 (void) strncat (one, "gh", 2);
357 equal (one, "abcdgh", 12); /* Count and length equal. */
358
359 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
360 equal (one, "abcdghij", 13);
361}
362
363static void
364test_strlcat (void)
365{
366#ifdef __TEST_BSD_FUNCS__
367 /* First test it as strcat, with big counts, then test the count
368 mechanism. */
369 it = "strlcat";
370 (void) strcpy (one, "ijk");
371 check (strlcat (one, "lmn", 99) == 6, 1); /* Returned value. */
372 equal (one, "ijklmn", 2); /* Basic test. */
373
374 (void) strcpy (one, "x");
375 (void) strlcat (one, "yz", 99);
376 equal (one, "xyz", 3); /* Writeover. */
377 equal (one+4, "mn", 4); /* Wrote too much? */
378
379 (void) strcpy (one, "gh");
380 (void) strcpy (two, "ef");
381 (void) strlcat (one, two, 99);
382 equal (one, "ghef", 5); /* Basic test encore. */
383 equal (two, "ef", 6); /* Stomped on source? */
384
385 (void) strcpy (one, "");
386 (void) strlcat (one, "", 99);
387 equal (one, "", 7); /* Boundary conditions. */
388 (void) strcpy (one, "ab");
389 (void) strlcat (one, "", 99);
390 equal (one, "ab", 8);
391 (void) strcpy (one, "");
392 (void) strlcat (one, "cd", 99);
393 equal (one, "cd", 9);
394
395 (void) strcpy (one, "ab");
396 (void) strlcat (one, "cdef", 2);
397 equal (one, "ab", 10); /* Count-limited. */
398
399 (void) strlcat (one, "gh", 0);
400 equal (one, "ab", 11); /* Zero count. */
401
402 (void) strlcat (one, "gh", 4);
403 equal (one, "abg", 12); /* Count and length equal. */
404
405 (void) strlcat (one, "ij", (size_t)-1); /* set sign bit in count */
406 equal (one, "abgij", 13);
407#endif
408}
409
410static void
411test_strncmp (void)
412{
413 /* First test as strcmp with big counts, then test count code. */
414 it = "strncmp";
415 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
416 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
417 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
418 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
419 check (strncmp ("abcd", "abc", 99) > 0, 5);
420 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
421 check (strncmp ("abce", "abcd", 99) > 0, 7);
422 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
423 check (strncmp ("a\203", "a\003", 2) > 0, 9);
424 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
425 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
426 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
427 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
428 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
429 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
430 check (strncmp ("aa", "ab", (size_t)-1) < 0, 16);
431}
432
433static void
434test_strncpy (void)
435{
436 /* Testing is a bit different because of odd semantics. */
437 it = "strncpy";
438 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
439 equal (one, "abc", 2); /* Did the copy go right? */
440
441 (void) strcpy (one, "abcdefgh");
442 (void) strncpy (one, "xyz", 2);
443 equal (one, "xycdefgh", 3); /* Copy cut by count. */
444
445 (void) strcpy (one, "abcdefgh");
446 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
447 equal (one, "xyzdefgh", 4);
448
449 (void) strcpy (one, "abcdefgh");
450 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
451 equal (one, "xyz", 5);
452 equal (one+4, "efgh", 6); /* Wrote too much? */
453
454 (void) strcpy (one, "abcdefgh");
455 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
456 equal (one, "xyz", 7);
457 equal (one+4, "", 8);
458 equal (one+5, "fgh", 9);
459
460 (void) strcpy (one, "abc");
461 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
462 equal (one, "abc", 10);
463
464 (void) strncpy (one, "", 2); /* Zero-length source. */
465 equal (one, "", 11);
466 equal (one+1, "", 12);
467 equal (one+2, "c", 13);
468
469 (void) strcpy (one, "hi there");
470 (void) strncpy (two, one, 9);
471 equal (two, "hi there", 14); /* Just paranoia. */
472 equal (one, "hi there", 15); /* Stomped on source? */
473}
474
475static void
476test_strlcpy (void)
477{
478#ifdef __TEST_BSD_FUNCS__
479 /* Testing is a bit different because of odd semantics. */
480 it = "strlcpy";
481 check (strlcpy (one, "abc", sizeof(one)) == 3, 1); /* Returned value. */
482 equal (one, "abc", 2); /* Did the copy go right? */
483
484 (void) strcpy (one, "abcdefgh");
485 (void) strlcpy (one, "xyz", 2);
486 equal (one, "x\0cdefgh", 3); /* Copy cut by count. */
487
488 (void) strcpy (one, "abcdefgh");
489 (void) strlcpy (one, "xyz", 3); /* Copy cut just before NUL. */
490 equal (one, "xy\0defgh", 4);
491
492 (void) strcpy (one, "abcdefgh");
493 (void) strlcpy (one, "xyz", 4); /* Copy just includes NUL. */
494 equal (one, "xyz", 5);
495 equal (one+4, "efgh", 6); /* Wrote too much? */
496
497 (void) strcpy (one, "abcdefgh");
498 (void) strlcpy (one, "xyz", 5); /* Copy includes padding. */
499 equal (one, "xyz", 7);
500 equal (one+3, "", 8);
501 equal (one+4, "efgh", 9);
502
503 (void) strcpy (one, "abc");
504 (void) strlcpy (one, "xyz", 0); /* Zero-length copy. */
505 equal (one, "abc", 10);
506
507 (void) strlcpy (one, "", 2); /* Zero-length source. */
508 equal (one, "", 11);
509 equal (one+1, "bc", 12);
510 equal (one+2, "c", 13);
511
512 (void) strcpy (one, "hi there");
513 (void) strlcpy (two, one, 9);
514 equal (two, "hi there", 14); /* Just paranoia. */
515 equal (one, "hi there", 15); /* Stomped on source? */
516#endif
517}
518
519static void
520test_strlen (void)
521{
522 it = "strlen";
523 check (strlen ("") == 0, 1); /* Empty. */
524 check (strlen ("a") == 1, 2); /* Single char. */
525 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
526 {
527 char buf[4096];
528 int i;
529 char *p;
530 for (i=0; i < 0x100; i++)
531 {
532 p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
533 strcpy (p, "OK");
534 strcpy (p+3, "BAD/WRONG");
535 check (strlen (p) == 2, 4+i);
536 }
537 }
538}
539
540static void
541test_strnlen (void)
542{
543 it = "strnlen";
544 check (strnlen ("", 10) == 0, 1); /* Empty. */
545 check (strnlen ("a", 10) == 1, 2); /* Single char. */
546 check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
547 check (strnlen ("foo", (size_t)-1) == 3, 4); /* limits of n. */
548
549 {
550 char buf[4096];
551 int i;
552 char *p;
553 for (i=0; i < 0x100; i++)
554 {
555 p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
556 strcpy (p, "OK");
557 strcpy (p+3, "BAD/WRONG");
558 check (strnlen (p, 100) == 2, 5+i);
559 }
560 }
561}
562
563static void
564test_strchr (void)
565{
566 it = "strchr";
567 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
568 (void) strcpy (one, "abcd");
569 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
570 check (strchr (one, 'd') == one+3, 3); /* End of string. */
571 check (strchr (one, 'a') == one, 4); /* Beginning. */
572 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
573 (void) strcpy (one, "ababa");
574 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
575 (void) strcpy (one, "");
576 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
577 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
578 {
579 char buf[4096];
580 int i;
581 char *p;
582 for (i=0; i < 0x100; i++)
583 {
584 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
585 strcpy (p, "OK");
586 strcpy (p+3, "BAD/WRONG");
587 check (strchr (p, '/') == NULL, 9+i);
588 }
589 }
590}
591
592static void
593test_strchrnul (void)
594{
595 const char *os;
596 it = "strchrnul";
597 cp = strchrnul ((os = "abcd"), 'z');
598 check (*cp == '\0', 1); /* Not found. */
599 check (cp == os + 4, 2);
600 (void) strcpy (one, "abcd");
601 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
602 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
603 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
604 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
605 (void) strcpy (one, "ababa");
606 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
607 (void) strcpy (one, "");
608 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
609 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
610 {
611 char buf[4096];
612 int i;
613 char *p;
614 for (i=0; i < 0x100; i++)
615 {
616 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
617 strcpy (p, "OK");
618 strcpy (p+3, "BAD/WRONG");
619 cp = strchrnul (p, '/');
620 check (*cp == '\0', 9+2*i);
621 check (cp == p+2, 10+2*i);
622 }
623 }
624}
625
626static void
627test_rawmemchr (void)
628{
629 it = "rawmemchr";
630 (void) strcpy (one, "abcd");
631 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
632 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
633 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
634 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
635 (void) strcpy (one, "ababa");
636 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
637 (void) strcpy (one, "");
638 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
639 {
640 char buf[4096];
641 int i;
642 char *p;
643 for (i=0; i < 0x100; i++)
644 {
645 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
646 strcpy (p, "OK");
647 strcpy (p+3, "BAD/WRONG");
648 check (rawmemchr (p, 'R') == p+8, 6+i);
649 }
650 }
651}
652
653static void
654test_index (void)
655{
656#ifdef __TEST_SUSV3_LEGACY__
657 it = "index";
658 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
659 (void) strcpy (one, "abcd");
660 check (index (one, 'c') == one+2, 2); /* Basic test. */
661 check (index (one, 'd') == one+3, 3); /* End of string. */
662 check (index (one, 'a') == one, 4); /* Beginning. */
663 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
664 (void) strcpy (one, "ababa");
665 check (index (one, 'b') == one+1, 6); /* Finding first. */
666 (void) strcpy (one, "");
667 check (index (one, 'b') == NULL, 7); /* Empty string. */
668 check (index (one, '\0') == one, 8); /* NUL in empty string. */
669#endif
670}
671
672static void
673test_strrchr (void)
674{
675 it = "strrchr";
676 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
677 (void) strcpy (one, "abcd");
678 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
679 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
680 check (strrchr (one, 'a') == one, 4); /* Beginning. */
681 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
682 (void) strcpy (one, "ababa");
683 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
684 (void) strcpy (one, "");
685 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
686 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
687 {
688 char buf[4096];
689 int i;
690 char *p;
691 for (i=0; i < 0x100; i++)
692 {
693 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
694 strcpy (p, "OK");
695 strcpy (p+3, "BAD/WRONG");
696 check (strrchr (p, '/') == NULL, 9+i);
697 }
698 }
699}
700
701static void
702test_memrchr (void)
703{
704 size_t l;
705 it = "memrchr";
706 check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
707 (void) strcpy (one, "abcd");
708 l = strlen (one) + 1;
709 check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
710 check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
711 check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
712 check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
713 (void) strcpy (one, "ababa");
714 l = strlen (one) + 1;
715 check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
716 (void) strcpy (one, "");
717 l = strlen (one) + 1;
718 check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
719 check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
720
721 /* now test all possible alignment and length combinations to catch
722 bugs due to unrolled loops (assuming unrolling is limited to no
723 more than 128 byte chunks: */
724 {
725 char buf[128 + sizeof(long)];
726 long align, len, i, pos;
727
728 for (align = 0; align < (long) sizeof(long); ++align) {
729 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
730 for (i = 0; i < len; ++i)
731 buf[align + i] = 'x'; /* don't depend on memset... */
732
733 for (pos = len - 1; pos >= 0; --pos) {
734#if 0
735 printf("align %d, len %d, pos %d\n", align, len, pos);
736#endif
737 check(memrchr(buf + align, 'x', len) == buf + align + pos, 9);
738 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
739 10);
740 buf[align + pos] = '-';
741 }
742 }
743 }
744 }
745}
746
747static void
748test_rindex (void)
749{
750#ifdef __TEST_SUSV3_LEGACY__
751 it = "rindex";
752 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
753 (void) strcpy (one, "abcd");
754 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
755 check (rindex (one, 'd') == one+3, 3); /* End of string. */
756 check (rindex (one, 'a') == one, 4); /* Beginning. */
757 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
758 (void) strcpy (one, "ababa");
759 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
760 (void) strcpy (one, "");
761 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
762 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
763#endif
764}
765
766static void
767test_strpbrk (void)
768{
769 it = "strpbrk";
770 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
771 (void) strcpy(one, "abcd");
772 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
773 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
774 check(strpbrk(one, "a") == one, 4); /* Beginning. */
775 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
776 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
777 (void) strcpy(one, "abcabdea");
778 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
779 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
780 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
781 (void) strcpy(one, "");
782 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
783 (void) strcpy(one, "");
784 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
785 (void) strcpy(one, "");
786 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
787 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
788 (void) strcpy(one, "abcabdea");
789 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
790 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
791 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
792 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
793}
794
795static void
796test_strstr (void)
797{
798 it = "strstr";
799 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
800 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
801 (void) strcpy(one, "abcd");
802 check(strstr(one, "c") == one+2, 3); /* Basic test. */
803 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
804 check(strstr(one, "d") == one+3, 5); /* End of string. */
805 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
806 check(strstr(one, "abc") == one, 7); /* Beginning. */
807 check(strstr(one, "abcd") == one, 8); /* Exact match. */
808 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
809 check(strstr(one, "de") == NULL, 10); /* Past end. */
810 check(strstr(one, "") == one, 11); /* Finding empty. */
811 (void) strcpy(one, "ababa");
812 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
813 (void) strcpy(one, "");
814 check(strstr(one, "b") == NULL, 13); /* Empty string. */
815 check(strstr(one, "") == one, 14); /* Empty in empty string. */
816 (void) strcpy(one, "bcbca");
817 check(strstr(one, "bca") == one+2, 15); /* False start. */
818 (void) strcpy(one, "bbbcabbca");
819 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
820}
821
822static void
823test_strspn (void)
824{
825 it = "strspn";
826 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
827 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
828 check(strspn("abc", "qx") == 0, 3); /* None. */
829 check(strspn("", "ab") == 0, 4); /* Null string. */
830 check(strspn("abc", "") == 0, 5); /* Null search list. */
831}
832
833static void
834test_strcspn (void)
835{
836 it = "strcspn";
837 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
838 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
839 check(strcspn("abc", "abc") == 0, 3); /* None. */
840 check(strcspn("", "ab") == 0, 4); /* Null string. */
841 check(strcspn("abc", "") == 3, 5); /* Null search list. */
842}
843
844static void
845test_strtok (void)
846{
847 it = "strtok";
848 (void) strcpy(one, "first, second, third");
849 equal(strtok(one, ", "), "first", 1); /* Basic test. */
850 equal(one, "first", 2);
851 equal(strtok((char *)NULL, ", "), "second", 3);
852 equal(strtok((char *)NULL, ", "), "third", 4);
853 check(strtok((char *)NULL, ", ") == NULL, 5);
854 (void) strcpy(one, ", first, ");
855 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
856 check(strtok((char *)NULL, ", ") == NULL, 7);
857 (void) strcpy(one, "1a, 1b; 2a, 2b");
858 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
859 equal(strtok((char *)NULL, "; "), "1b", 9);
860 equal(strtok((char *)NULL, ", "), "2a", 10);
861 (void) strcpy(two, "x-y");
862 equal(strtok(two, "-"), "x", 11); /* New string before done. */
863 equal(strtok((char *)NULL, "-"), "y", 12);
864 check(strtok((char *)NULL, "-") == NULL, 13);
865 (void) strcpy(one, "a,b, c,, ,d");
866 equal(strtok(one, ", "), "a", 14); /* Different separators. */
867 equal(strtok((char *)NULL, ", "), "b", 15);
868 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
869 equal(strtok((char *)NULL, " ,"), "d", 17);
870 check(strtok((char *)NULL, ", ") == NULL, 18);
871 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
872 (void) strcpy(one, ", ");
873 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
874 (void) strcpy(one, "");
875 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
876 (void) strcpy(one, "abc");
877 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
878 check(strtok((char *)NULL, ", ") == NULL, 23);
879 (void) strcpy(one, "abc");
880 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
881 check(strtok((char *)NULL, "") == NULL, 25);
882 (void) strcpy(one, "abcdefgh");
883 (void) strcpy(one, "a,b,c");
884 equal(strtok(one, ","), "a", 26); /* Basics again... */
885 equal(strtok((char *)NULL, ","), "b", 27);
886 equal(strtok((char *)NULL, ","), "c", 28);
887 check(strtok((char *)NULL, ",") == NULL, 29);
888 equal(one+6, "gh", 30); /* Stomped past end? */
889 equal(one, "a", 31); /* Stomped old tokens? */
890 equal(one+2, "b", 32);
891 equal(one+4, "c", 33);
892}
893
894static void
895test_strtok_r (void)
896{
897 it = "strtok_r";
898 (void) strcpy(one, "first, second, third");
899 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
900 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
901 equal(one, "first", 2);
902 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
903 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
904 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
905 (void) strcpy(one, ", first, ");
906 cp = NULL;
907 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
908 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
909 (void) strcpy(one, "1a, 1b; 2a, 2b");
910 cp = NULL;
911 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
912 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
913 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
914 (void) strcpy(two, "x-y");
915 cp = NULL;
916 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
917 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
918 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
919 (void) strcpy(one, "a,b, c,, ,d");
920 cp = NULL;
921 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
922 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
923 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
924 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
925 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
926 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
927 (void) strcpy(one, ", ");
928 cp = NULL;
929 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
930 (void) strcpy(one, "");
931 cp = NULL;
932 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
933 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
934 (void) strcpy(one, "abc");
935 cp = NULL;
936 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
937 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
938 (void) strcpy(one, "abc");
939 cp = NULL;
940 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
941 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
942 (void) strcpy(one, "abcdefgh");
943 (void) strcpy(one, "a,b,c");
944 cp = NULL;
945 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
946 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
947 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
948 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
949 equal(one+6, "gh", 31); /* Stomped past end? */
950 equal(one, "a", 32); /* Stomped old tokens? */
951 equal(one+2, "b", 33);
952 equal(one+4, "c", 34);
953}
954
955static void
956test_strsep (void)
957{
958 char *ptr;
959 it = "strsep";
960 cp = strcpy(one, "first, second, third");
961 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
962 equal(one, "first", 2);
963 equal(strsep(&cp, ", "), "", 3);
964 equal(strsep(&cp, ", "), "second", 4);
965 equal(strsep(&cp, ", "), "", 5);
966 equal(strsep(&cp, ", "), "third", 6);
967 check(strsep(&cp, ", ") == NULL, 7);
968 cp = strcpy(one, ", first, ");
969 equal(strsep(&cp, ", "), "", 8);
970 equal(strsep(&cp, ", "), "", 9);
971 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
972 equal(strsep(&cp, ", "), "", 11);
973 equal(strsep(&cp, ", "), "", 12);
974 check(strsep(&cp, ", ") == NULL, 13);
975 cp = strcpy(one, "1a, 1b; 2a, 2b");
976 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
977 equal(strsep(&cp, ", "), "", 15);
978 equal(strsep(&cp, "; "), "1b", 16);
979 equal(strsep(&cp, ", "), "", 17);
980 equal(strsep(&cp, ", "), "2a", 18);
981 cp = strcpy(two, "x-y");
982 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
983 equal(strsep(&cp, "-"), "y", 20);
984 check(strsep(&cp, "-") == NULL, 21);
985 cp = strcpy(one, "a,b, c,, ,d ");
986 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
987 equal(strsep(&cp, ", "), "b", 23);
988 equal(strsep(&cp, " ,"), "", 24);
989 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
990 equal(strsep(&cp, " ,"), "", 26);
991 equal(strsep(&cp, " ,"), "", 27);
992 equal(strsep(&cp, " ,"), "", 28);
993 equal(strsep(&cp, " ,"), "d", 29);
994 equal(strsep(&cp, " ,"), "", 30);
995 check(strsep(&cp, ", ") == NULL, 31);
996 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
997 cp = strcpy(one, ", ");
998 equal(strsep(&cp, ", "), "", 33);
999 equal(strsep(&cp, ", "), "", 34);
1000 equal(strsep(&cp, ", "), "", 35);
1001 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
1002 cp = strcpy(one, "");
1003 equal(strsep(&cp, ", "), "", 37);
1004 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
1005 cp = strcpy(one, "abc");
1006 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
1007 check(strsep(&cp, ", ") == NULL, 40);
1008 cp = strcpy(one, "abc");
1009 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
1010 check(strsep(&cp, "") == NULL, 42);
1011 (void) strcpy(one, "abcdefgh");
1012 cp = strcpy(one, "a,b,c");
1013 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
1014 equal(strsep(&cp, ","), "b", 44);
1015 equal(strsep(&cp, ","), "c", 45);
1016 check(strsep(&cp, ",") == NULL, 46);
1017 equal(one+6, "gh", 47); /* Stomped past end? */
1018 equal(one, "a", 48); /* Stomped old tokens? */
1019 equal(one+2, "b", 49);
1020 equal(one+4, "c", 50);
1021
1022 {
1023 char text[] = "This,is,a,test";
1024 char *list = strdupa (text);
1025 equal (strsep (&list, ","), "This", 51);
1026 equal (strsep (&list, ","), "is", 52);
1027 equal (strsep (&list, ","), "a", 53);
1028 equal (strsep (&list, ","), "test", 54);
1029 check (strsep (&list, ",") == NULL, 55);
1030 }
1031
1032 cp = strcpy(one, "a,b, c,, ,d,");
1033 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1034 equal(strsep(&cp, ","), "b", 57);
1035 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1036 equal(strsep(&cp, ","), "", 59);
1037 equal(strsep(&cp, ","), " ", 60);
1038 equal(strsep(&cp, ","), "d", 61);
1039 equal(strsep(&cp, ","), "", 62);
1040 check(strsep(&cp, ",") == NULL, 63);
1041 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1042
1043 cp = strcpy(one, "a,b, c,, ,d,");
1044 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1045 equal(strsep(&cp, "x,y"), "b", 66);
1046 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1047 equal(strsep(&cp, "xy,"), "", 68);
1048 equal(strsep(&cp, "x,y"), " ", 69);
1049 equal(strsep(&cp, ",xy"), "d", 70);
1050 equal(strsep(&cp, "xy,"), "", 71);
1051 check(strsep(&cp, "x,y") == NULL, 72);
1052 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1053
1054 cp = strcpy(one, "ABC");
1055 one[4] = ':';
1056 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1057 ptr = strsep(&cp, ":");
1058 equal(ptr, "", 75);
1059 check(ptr == one + 3, 76);
1060 check(cp == NULL, 77);
1061
1062 cp = strcpy(one, "ABC");
1063 one[4] = ':';
1064 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1065 ptr = strsep(&cp, ":.");
1066 equal(ptr, "", 79);
1067 check(ptr == one + 3, 80);
1068
1069 cp = strcpy(one, "ABC"); /* No token in string. */
1070 equal(strsep(&cp, ","), "ABC", 81);
1071 check(cp == NULL, 82);
1072
1073 *one = '\0'; /* Empty string. */
1074 cp = one;
1075 ptr = strsep(&cp, ",");
1076 equal(ptr, "", 83);
1077 check(ptr == one, 84);
1078 check(cp == NULL, 85);
1079
1080 *one = '\0'; /* Empty string and no token. */
1081 cp = one;
1082 ptr = strsep(&cp, "");
1083 equal(ptr, "", 86);
1084 check(ptr == one , 87);
1085 check(cp == NULL, 88);
1086}
1087
1088static void
1089test_memcmp (void)
1090{
1091 int i, cnt = 1;
1092 char one[21], two[21];
1093
1094 it = "memcmp";
1095 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1096 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1097 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1098 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1099 check(memcmp("alph", "cold", 4) < 0, cnt++);
1100 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1101 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1102 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1103 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1104 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1105 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1106 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1107 /* Comparisons with shifting 4-byte boundaries. */
1108 for (i=0; i<4; i++)
1109 {
1110 char *a = one + i, *b = two + i;
1111 strncpy( a, "--------11112222", 16);
1112 strncpy( b, "--------33334444", 16);
1113 check( memcmp(b, a, 16) > 0, cnt++);
1114 check( memcmp(a, b, 16) < 0, cnt++);
1115 }
1116}
1117
1118static void
1119test_memchr (void)
1120{
1121 it = "memchr";
1122 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1123 (void) strcpy(one, "abcd");
1124 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1125 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1126 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1127 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1128 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1129 (void) strcpy(one, "ababa");
1130 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1131 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1132 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1133 (void) strcpy(one, "a\203b");
1134 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1135
1136 /* now test all possible alignment and length combinations to catch
1137 bugs due to unrolled loops (assuming unrolling is limited to no
1138 more than 128 byte chunks: */
1139 {
1140 char buf[128 + sizeof(long)];
1141 long align, len, i, pos;
1142
1143 for (align = 0; align < (long) sizeof(long); ++align) {
1144 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
1145 for (i = 0; i < len; ++i) {
1146 buf[align + i] = 'x'; /* don't depend on memset... */
1147 }
1148 for (pos = 0; pos < len; ++pos) {
1149#if 0
1150 printf("align %d, len %d, pos %d\n", align, len, pos);
1151#endif
1152 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1153 check(memchr(buf + align, 'x', pos) == NULL, 11);
1154 buf[align + pos] = '-';
1155 }
1156 }
1157 }
1158 }
1159}
1160
1161static void
1162test_memcpy (void)
1163{
1164 int i;
1165 it = "memcpy";
1166 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1167 equal(one, "abc", 2); /* Did the copy go right? */
1168
1169 (void) strcpy(one, "abcdefgh");
1170 (void) memcpy(one+1, "xyz", 2);
1171 equal(one, "axydefgh", 3); /* Basic test. */
1172
1173 (void) strcpy(one, "abc");
1174 (void) memcpy(one, "xyz", 0);
1175 equal(one, "abc", 4); /* Zero-length copy. */
1176
1177 (void) strcpy(one, "hi there");
1178 (void) strcpy(two, "foo");
1179 (void) memcpy(two, one, 9);
1180 equal(two, "hi there", 5); /* Just paranoia. */
1181 equal(one, "hi there", 6); /* Stomped on source? */
1182
1183 for (i = 0; i < 16; i++)
1184 {
1185 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1186 strcpy (one, x);
1187 check (memcpy (one + i, "hi there", 9) == one + i,
1188 7 + (i * 6)); /* Unaligned destination. */
1189 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1190 equal (one + i, "hi there", 9 + (i * 6));
1191 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1192 check (memcpy (two, one + i, 9) == two,
1193 11 + (i * 6)); /* Unaligned source. */
1194 equal (two, "hi there", 12 + (i * 6));
1195 }
1196}
1197
1198static void
1199test_mempcpy (void)
1200{
1201 int i;
1202 it = "mempcpy";
1203 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1204 equal(one, "abc", 2); /* Did the copy go right? */
1205
1206 (void) strcpy(one, "abcdefgh");
1207 (void) mempcpy(one+1, "xyz", 2);
1208 equal(one, "axydefgh", 3); /* Basic test. */
1209
1210 (void) strcpy(one, "abc");
1211 (void) mempcpy(one, "xyz", 0);
1212 equal(one, "abc", 4); /* Zero-length copy. */
1213
1214 (void) strcpy(one, "hi there");
1215 (void) strcpy(two, "foo");
1216 (void) mempcpy(two, one, 9);
1217 equal(two, "hi there", 5); /* Just paranoia. */
1218 equal(one, "hi there", 6); /* Stomped on source? */
1219
1220 for (i = 0; i < 16; i++)
1221 {
1222 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1223 strcpy (one, x);
1224 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1225 7 + (i * 6)); /* Unaligned destination. */
1226 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1227 equal (one + i, "hi there", 9 + (i * 6));
1228 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1229 check (mempcpy (two, one + i, 9) == two + 9,
1230 11 + (i * 6)); /* Unaligned source. */
1231 equal (two, "hi there", 12 + (i * 6));
1232 }
1233}
1234
1235static void
1236test_memmove (void)
1237{
1238 it = "memmove";
1239 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1240 equal(one, "abc", 2); /* Did the copy go right? */
1241
1242 (void) strcpy(one, "abcdefgh");
1243 (void) memmove(one+1, "xyz", 2);
1244 equal(one, "axydefgh", 3); /* Basic test. */
1245
1246 (void) strcpy(one, "abc");
1247 (void) memmove(one, "xyz", 0);
1248 equal(one, "abc", 4); /* Zero-length copy. */
1249
1250 (void) strcpy(one, "hi there");
1251 (void) strcpy(two, "foo");
1252 (void) memmove(two, one, 9);
1253 equal(two, "hi there", 5); /* Just paranoia. */
1254 equal(one, "hi there", 6); /* Stomped on source? */
1255
1256 (void) strcpy(one, "abcdefgh");
1257 (void) memmove(one+1, one, 9);
1258 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1259
1260 (void) strcpy(one, "abcdefgh");
1261 (void) memmove(one+1, one+2, 7);
1262 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1263
1264 (void) strcpy(one, "abcdefgh");
1265 (void) memmove(one, one, 9);
1266 equal(one, "abcdefgh", 9); /* 100% overlap. */
1267}
1268
1269static void
1270test_memccpy (void)
1271{
1272 /* First test like memcpy, then the search part The SVID, the only
1273 place where memccpy is mentioned, says overlap might fail, so we
1274 don't try it. Besides, it's hard to see the rationale for a
1275 non-left-to-right memccpy. */
1276 it = "memccpy";
1277 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1278 equal(one, "abc", 2); /* Did the copy go right? */
1279
1280 (void) strcpy(one, "abcdefgh");
1281 (void) memccpy(one+1, "xyz", 'q', 2);
1282 equal(one, "axydefgh", 3); /* Basic test. */
1283
1284 (void) strcpy(one, "abc");
1285 (void) memccpy(one, "xyz", 'q', 0);
1286 equal(one, "abc", 4); /* Zero-length copy. */
1287
1288 (void) strcpy(one, "hi there");
1289 (void) strcpy(two, "foo");
1290 (void) memccpy(two, one, 'q', 9);
1291 equal(two, "hi there", 5); /* Just paranoia. */
1292 equal(one, "hi there", 6); /* Stomped on source? */
1293
1294 (void) strcpy(one, "abcdefgh");
1295 (void) strcpy(two, "horsefeathers");
1296 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1297 equal(one, "abcdefgh", 8); /* Source intact? */
1298 equal(two, "abcdefeathers", 9); /* Copy correct? */
1299
1300 (void) strcpy(one, "abcd");
1301 (void) strcpy(two, "bumblebee");
1302 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1303 equal(two, "aumblebee", 11);
1304 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1305 equal(two, "abcdlebee", 13);
1306 (void) strcpy(one, "xyz");
1307 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1308 equal(two, "xbcdlebee", 15);
1309}
1310
1311static void
1312test_memset (void)
1313{
1314 int i;
1315
1316 it = "memset";
1317 (void) strcpy(one, "abcdefgh");
1318 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1319 equal(one, "axxxefgh", 2); /* Basic test. */
1320
1321 (void) memset(one+2, 'y', 0);
1322 equal(one, "axxxefgh", 3); /* Zero-length set. */
1323
1324 (void) memset(one+5, 0, 1);
1325 equal(one, "axxxe", 4); /* Zero fill. */
1326 equal(one+6, "gh", 5); /* And the leftover. */
1327
1328 (void) memset(one+2, 010045, 1);
1329 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1330
1331 /* Non-8bit fill character. */
1332 memset (one, 0x101, sizeof (one));
1333 for (i = 0; i < (int) sizeof (one); ++i)
1334 check (one[i] == '\01', 7);
1335
1336 /* Test for more complex versions of memset, for all alignments and
1337 lengths up to 256. This test takes a little while, perhaps it should
1338 be made weaker? */
1339 {
1340 char data[512];
1341 int j;
1342 int k;
1343 int c;
1344
1345 for (i = 0; i < 512; i++)
1346 data[i] = 'x';
1347 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1348 memset(,'y',) */
1349 for (j = 0; j < 256; j++)
1350 for (i = 0; i < 256; i++)
1351 {
1352 memset (data + i, c, j);
1353 for (k = 0; k < i; k++)
1354 if (data[k] != 'x')
1355 goto fail;
1356 for (k = i; k < i+j; k++)
1357 {
1358 if (data[k] != c)
1359 goto fail;
1360 data[k] = 'x';
1361 }
1362 for (k = i+j; k < 512; k++)
1363 if (data[k] != 'x')
1364 goto fail;
1365 continue;
1366
1367 fail:
1368 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1369 }
1370 }
1371}
1372
1373static void
1374test_bcopy (void)
1375{
1376#ifdef __TEST_SUSV3_LEGACY__
1377 /* Much like memcpy. Berklix manual is silent about overlap, so
1378 don't test it. */
1379 it = "bcopy";
1380 (void) bcopy("abc", one, 4);
1381 equal(one, "abc", 1); /* Simple copy. */
1382
1383 (void) strcpy(one, "abcdefgh");
1384 (void) bcopy("xyz", one+1, 2);
1385 equal(one, "axydefgh", 2); /* Basic test. */
1386
1387 (void) strcpy(one, "abc");
1388 (void) bcopy("xyz", one, 0);
1389 equal(one, "abc", 3); /* Zero-length copy. */
1390
1391 (void) strcpy(one, "hi there");
1392 (void) strcpy(two, "foo");
1393 (void) bcopy(one, two, 9);
1394 equal(two, "hi there", 4); /* Just paranoia. */
1395 equal(one, "hi there", 5); /* Stomped on source? */
1396#endif
1397}
1398
1399static void
1400test_bzero (void)
1401{
1402#ifdef __TEST_SUSV3_LEGACY__
1403 it = "bzero";
1404 (void) strcpy(one, "abcdef");
1405 bzero(one+2, 2);
1406 equal(one, "ab", 1); /* Basic test. */
1407 equal(one+3, "", 2);
1408 equal(one+4, "ef", 3);
1409
1410 (void) strcpy(one, "abcdef");
1411 bzero(one+2, 0);
1412 equal(one, "abcdef", 4); /* Zero-length copy. */
1413#endif
1414}
1415
1416static void
1417test_strndup (void)
1418{
1419 char *p, *q;
1420 it = "strndup";
1421 p = strndup("abcdef", 12);
1422 check(p != NULL, 1);
1423 if (p != NULL)
1424 {
1425 equal(p, "abcdef", 2);
1426 q = strndup(p + 1, 2);
1427 check(q != NULL, 3);
1428 if (q != NULL)
1429 equal(q, "bc", 4);
1430 free (q);
1431 }
1432 free (p);
1433 p = strndup("abc def", 3);
1434 check(p != NULL, 5);
1435 if (p != NULL)
1436 equal(p, "abc", 6);
1437 free (p);
1438}
1439
1440static void
1441test_bcmp (void)
1442{
1443#ifdef __TEST_SUSV3_LEGACY__
1444 it = "bcmp";
1445 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1446 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1447 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1448 check(bcmp("abce", "abcd", 4) != 0, 4);
1449 check(bcmp("alph", "beta", 4) != 0, 5);
1450 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1451 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1452#endif
1453}
1454
1455static void
1456test_strerror (void)
1457{
1458 it = "strerror";
1459 check(strerror(EDOM) != 0, 1);
1460 check(strerror(ERANGE) != 0, 2);
1461 check(strerror(ENOENT) != 0, 3);
1462}
1463
1464static void
1465test_strcasecmp (void)
1466{
1467 it = "strcasecmp";
1468 /* Note that the locale is "C". */
1469 check(strcasecmp("a", "a") == 0, 1);
1470 check(strcasecmp("a", "A") == 0, 2);
1471 check(strcasecmp("A", "a") == 0, 3);
1472 check(strcasecmp("a", "b") < 0, 4);
1473 check(strcasecmp("c", "b") > 0, 5);
1474 check(strcasecmp("abc", "AbC") == 0, 6);
1475 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1476 check(strcasecmp("", "0123456789") < 0, 8);
1477 check(strcasecmp("AbC", "") > 0, 9);
1478 check(strcasecmp("AbC", "A") > 0, 10);
1479 check(strcasecmp("AbC", "Ab") > 0, 11);
1480 check(strcasecmp("AbC", "ab") > 0, 12);
1481}
1482
1483static void
1484test_strncasecmp (void)
1485{
1486 it = "strncasecmp";
1487 /* Note that the locale is "C". */
1488 check(strncasecmp("a", "a", 5) == 0, 1);
1489 check(strncasecmp("a", "A", 5) == 0, 2);
1490 check(strncasecmp("A", "a", 5) == 0, 3);
1491 check(strncasecmp("a", "b", 5) < 0, 4);
1492 check(strncasecmp("c", "b", 5) > 0, 5);
1493 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1494 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1495 check(strncasecmp("", "0123456789", 10) < 0, 8);
1496 check(strncasecmp("AbC", "", 5) > 0, 9);
1497 check(strncasecmp("AbC", "A", 5) > 0, 10);
1498 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1499 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1500 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1501 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1502 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1503 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1504 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1505 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1506 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1507 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1508}
1509
1510int
1511main (void)
1512{
1513 int status;
1514
1515 /* Test strcmp first because we use it to test other things. */
1516 test_strcmp ();
1517
1518 /* Test strcpy next because we need it to set up other tests. */
1519 test_strcpy ();
1520
1521 /* A closely related function is stpcpy. */
1522 test_stpcpy ();
1523
1524 /* stpncpy. */
1525 test_stpncpy ();
1526
1527 /* strcat. */
1528 test_strcat ();
1529
1530 /* strncat. */
1531 test_strncat ();
1532
1533 /* strlcat. */
1534 test_strlcat ();
1535
1536 /* strncmp. */
1537 test_strncmp ();
1538
1539 /* strncpy. */
1540 test_strncpy ();
1541
1542 /* strlcpy. */
1543 test_strlcpy ();
1544
1545 /* strlen. */
1546 test_strlen ();
1547
1548 /* strnlen. */
1549 test_strnlen ();
1550
1551 /* strchr. */
1552 test_strchr ();
1553
1554 /* strchrnul. */
1555 test_strchrnul ();
1556
1557 /* rawmemchr. */
1558 test_rawmemchr ();
1559
1560 /* index - just like strchr. */
1561 test_index ();
1562
1563 /* strrchr. */
1564 test_strrchr ();
1565
1566 /* memrchr. */
1567 test_memrchr ();
1568
1569 /* rindex - just like strrchr. */
1570 test_rindex ();
1571
1572 /* strpbrk - somewhat like strchr. */
1573 test_strpbrk ();
1574
1575 /* strstr - somewhat like strchr. */
1576 test_strstr ();
1577
1578 /* strspn. */
1579 test_strspn ();
1580
1581 /* strcspn. */
1582 test_strcspn ();
1583
1584 /* strtok - the hard one. */
1585 test_strtok ();
1586
1587 /* strtok_r. */
1588 test_strtok_r ();
1589
1590 /* strsep. */
1591 test_strsep ();
1592
1593 /* memcmp. */
1594 test_memcmp ();
1595
1596 /* memchr. */
1597 test_memchr ();
1598
1599 /* memcpy - need not work for overlap. */
1600 test_memcpy ();
1601
1602 /* memmove - must work on overlap. */
1603 test_memmove ();
1604
1605 /* mempcpy */
1606 test_mempcpy ();
1607
1608 /* memccpy. */
1609 test_memccpy ();
1610
1611 /* memset. */
1612 test_memset ();
1613
1614 /* bcopy. */
1615 test_bcopy ();
1616
1617 /* bzero. */
1618 test_bzero ();
1619
1620 /* bcmp - somewhat like memcmp. */
1621 test_bcmp ();
1622
1623 /* strndup. */
1624 test_strndup ();
1625
1626 /* strerror - VERY system-dependent. */
1627 test_strerror ();
1628
1629 /* strcasecmp. Without locale dependencies. */
1630 test_strcasecmp ();
1631
1632 /* strncasecmp. Without locale dependencies. */
1633 test_strncasecmp ();
1634
1635 if (errors == 0)
1636 {
1637 status = EXIT_SUCCESS;
1638 puts("No errors.");
1639 }
1640 else
1641 {
1642 status = EXIT_FAILURE;
1643 printf("%Zd errors.\n", errors);
1644 }
1645
1646 return status;
1647}