Update translations.
[glibc.git] / string / tester.c
blob5a397055b10b6a4132f2b134fb38c1ab17e02b1e
1 /* Tester for string functions.
2 Copyright (C) 1995-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
23 /* Make sure we don't test the optimized inline functions if we want to
24 test the real implementation. */
25 #if !defined DO_STRING_INLINES
26 #undef __USE_STRING_INLINES
27 #endif
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <fcntl.h>
35 #include <libc-diag.h>
37 /* This file tests a range of corner cases of string functions,
38 including cases where truncation occurs or where sizes specified
39 are larger than the actual buffers, which result in various
40 warnings. */
41 DIAG_IGNORE_NEEDS_COMMENT (8, "-Warray-bounds");
42 DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args");
43 #if __GNUC_PREREQ (7, 0)
44 DIAG_IGNORE_NEEDS_COMMENT (9, "-Wrestrict");
45 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
46 #endif
47 #if __GNUC_PREREQ (8, 0)
48 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
49 #endif
50 #if __GNUC_PREREQ (11, 0)
51 DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
52 #endif
55 #define STREQ(a, b) (strcmp((a), (b)) == 0)
57 const char *it = "<UNSET>"; /* Routine name for message routines. */
58 size_t errors = 0;
60 /* Complain if condition is not true. */
61 static void
62 check (int thing, int number)
64 if (!thing)
66 printf ("%s flunked test %d\n", it, number);
67 ++errors;
71 /* Complain if first two args don't strcmp as equal. */
72 static void
73 equal (const char *a, const char *b, int number)
75 check (a != NULL && b != NULL && STREQ (a, b), number);
78 char one[50];
79 char two[50];
80 char *cp;
82 static void
83 test_strcmp (void)
85 it = "strcmp";
86 check (strcmp ("", "") == 0, 1); /* Trivial case. */
87 check (strcmp ("a", "a") == 0, 2); /* Identity. */
88 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
89 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
90 check (strcmp ("abcd", "abc") > 0, 5);
91 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
92 check (strcmp ("abce", "abcd") > 0, 7);
93 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
94 check (strcmp ("a\203", "a\003") > 0, 9);
97 char buf1[0x40], buf2[0x40];
98 int i, j;
99 for (i=0; i < 0x10; i++)
100 for (j = 0; j < 0x10; j++)
102 int k;
103 for (k = 0; k < 0x3f; k++)
105 buf1[k] = '0' ^ (k & 4);
106 buf2[k] = '4' ^ (k & 4);
108 buf1[i] = buf1[0x3f] = 0;
109 buf2[j] = buf2[0x3f] = 0;
110 for (k = 0; k < 0xf; k++)
112 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
113 check (strcmp (buf1+i,buf2+j) == 0, cnum);
114 buf1[i+k] = 'A' + i + k;
115 buf1[i+k+1] = 0;
116 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
117 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
118 buf2[j+k] = 'B' + i + k;
119 buf2[j+k+1] = 0;
120 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
121 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
122 buf2[j+k] = 'A' + i + k;
123 buf1[i] = 'A' + i + 0x80;
124 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
125 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
126 buf1[i] = 'A' + i;
132 #define SIMPLE_COPY(fn, n, str, ntest) \
133 do { \
134 int __n; \
135 char *cp; \
136 for (__n = 0; __n < (int) sizeof (one); ++__n) \
137 one[__n] = 'Z'; \
138 fn (one, str); \
139 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
140 check (*cp == '0' + (n % 10), ntest); \
141 check (*cp == '\0', ntest); \
142 } while (0)
144 static void
145 test_strcpy (void)
147 int i;
148 it = "strcpy";
149 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
150 equal (one, "abcd", 2); /* Basic test. */
152 (void) strcpy (one, "x");
153 equal (one, "x", 3); /* Writeover. */
154 equal (one+2, "cd", 4); /* Wrote too much? */
156 (void) strcpy (two, "hi there");
157 (void) strcpy (one, two);
158 equal (one, "hi there", 5); /* Basic test encore. */
159 equal (two, "hi there", 6); /* Stomped on source? */
161 (void) strcpy (one, "");
162 equal (one, "", 7); /* Boundary condition. */
164 for (i = 0; i < 16; i++)
166 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
167 equal (one + i, "hi there", 8 + (i * 2));
168 (void) strcpy (two, one + i); /* Unaligned source. */
169 equal (two, "hi there", 9 + (i * 2));
172 SIMPLE_COPY(strcpy, 0, "", 41);
173 SIMPLE_COPY(strcpy, 1, "1", 42);
174 SIMPLE_COPY(strcpy, 2, "22", 43);
175 SIMPLE_COPY(strcpy, 3, "333", 44);
176 SIMPLE_COPY(strcpy, 4, "4444", 45);
177 SIMPLE_COPY(strcpy, 5, "55555", 46);
178 SIMPLE_COPY(strcpy, 6, "666666", 47);
179 SIMPLE_COPY(strcpy, 7, "7777777", 48);
180 SIMPLE_COPY(strcpy, 8, "88888888", 49);
181 SIMPLE_COPY(strcpy, 9, "999999999", 50);
182 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
183 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
184 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
185 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
186 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
187 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
188 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
190 /* Simple test using implicitly coerced `void *' arguments. */
191 const void *src = "frobozz";
192 void *dst = one;
193 check (strcpy (dst, src) == dst, 1);
194 equal (dst, "frobozz", 2);
197 static void
198 test_stpcpy (void)
200 it = "stpcpy";
201 check ((stpcpy (one, "a") - one) == 1, 1);
202 equal (one, "a", 2);
204 check ((stpcpy (one, "ab") - one) == 2, 3);
205 equal (one, "ab", 4);
207 check ((stpcpy (one, "abc") - one) == 3, 5);
208 equal (one, "abc", 6);
210 check ((stpcpy (one, "abcd") - one) == 4, 7);
211 equal (one, "abcd", 8);
213 check ((stpcpy (one, "abcde") - one) == 5, 9);
214 equal (one, "abcde", 10);
216 check ((stpcpy (one, "abcdef") - one) == 6, 11);
217 equal (one, "abcdef", 12);
219 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
220 equal (one, "abcdefg", 14);
222 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
223 equal (one, "abcdefgh", 16);
225 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
226 equal (one, "abcdefghi", 18);
228 check ((stpcpy (one, "x") - one) == 1, 19);
229 equal (one, "x", 20); /* Writeover. */
230 equal (one+2, "cdefghi", 21); /* Wrote too much? */
232 check ((stpcpy (one, "xx") - one) == 2, 22);
233 equal (one, "xx", 23); /* Writeover. */
234 equal (one+3, "defghi", 24); /* Wrote too much? */
236 check ((stpcpy (one, "xxx") - one) == 3, 25);
237 equal (one, "xxx", 26); /* Writeover. */
238 equal (one+4, "efghi", 27); /* Wrote too much? */
240 check ((stpcpy (one, "xxxx") - one) == 4, 28);
241 equal (one, "xxxx", 29); /* Writeover. */
242 equal (one+5, "fghi", 30); /* Wrote too much? */
244 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
245 equal (one, "xxxxx", 32); /* Writeover. */
246 equal (one+6, "ghi", 33); /* Wrote too much? */
248 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
249 equal (one, "xxxxxx", 35); /* Writeover. */
250 equal (one+7, "hi", 36); /* Wrote too much? */
252 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
253 equal (one, "xxxxxxx", 38); /* Writeover. */
254 equal (one+8, "i", 39); /* Wrote too much? */
256 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
257 equal (one, "abc", 41);
258 equal (one + 4, "xxx", 42);
260 SIMPLE_COPY(stpcpy, 0, "", 43);
261 SIMPLE_COPY(stpcpy, 1, "1", 44);
262 SIMPLE_COPY(stpcpy, 2, "22", 45);
263 SIMPLE_COPY(stpcpy, 3, "333", 46);
264 SIMPLE_COPY(stpcpy, 4, "4444", 47);
265 SIMPLE_COPY(stpcpy, 5, "55555", 48);
266 SIMPLE_COPY(stpcpy, 6, "666666", 49);
267 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
268 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
269 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
270 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
271 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
272 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
273 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
274 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
275 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
276 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
279 static void
280 test_stpncpy (void)
282 it = "stpncpy";
283 memset (one, 'x', sizeof (one));
284 check (stpncpy (one, "abc", 2) == one + 2, 1);
285 check (stpncpy (one, "abc", 3) == one + 3, 2);
286 check (stpncpy (one, "abc", 4) == one + 3, 3);
287 check (one[3] == '\0' && one[4] == 'x', 4);
288 check (stpncpy (one, "abcd", 5) == one + 4, 5);
289 check (one[4] == '\0' && one[5] == 'x', 6);
290 check (stpncpy (one, "abcd", 6) == one + 4, 7);
291 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
294 static void
295 test_strcat (void)
297 it = "strcat";
298 (void) strcpy (one, "ijk");
299 check (strcat (one, "lmn") == one, 1); /* Returned value. */
300 equal (one, "ijklmn", 2); /* Basic test. */
302 (void) strcpy (one, "x");
303 (void) strcat (one, "yz");
304 equal (one, "xyz", 3); /* Writeover. */
305 equal (one+4, "mn", 4); /* Wrote too much? */
307 (void) strcpy (one, "gh");
308 (void) strcpy (two, "ef");
309 (void) strcat (one, two);
310 equal (one, "ghef", 5); /* Basic test encore. */
311 equal (two, "ef", 6); /* Stomped on source? */
313 (void) strcpy (one, "");
314 (void) strcat (one, "");
315 equal (one, "", 7); /* Boundary conditions. */
316 (void) strcpy (one, "ab");
317 (void) strcat (one, "");
318 equal (one, "ab", 8);
319 (void) strcpy (one, "");
320 (void) strcat (one, "cd");
321 equal (one, "cd", 9);
323 int ntest = 10;
324 char buf1[80] __attribute__ ((aligned (16)));
325 char buf2[32] __attribute__ ((aligned (16)));
326 for (size_t n1 = 0; n1 < 16; ++n1)
327 for (size_t n2 = 0; n2 < 16; ++n2)
328 for (size_t n3 = 0; n3 < 32; ++n3)
330 size_t olderrors = errors;
332 memset (buf1, 'b', sizeof (buf1));
334 memset (buf1 + n2, 'a', n3);
335 buf1[n2 + n3] = '\0';
336 strcpy (buf2 + n1, "123");
338 check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
339 if (errors == olderrors)
340 for (size_t i = 0; i < sizeof (buf1); ++i)
342 if (i < n2)
343 check (buf1[i] == 'b', ntest);
344 else if (i < n2 + n3)
345 check (buf1[i] == 'a', ntest);
346 else if (i < n2 + n3 + 3)
347 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
348 else if (i == n2 + n3 + 3)
349 check (buf1[i] == '\0', ntest);
350 else
351 check (buf1[i] == 'b', ntest);
353 if (errors != olderrors)
355 printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
356 n1, n2, n3, buf1[0]);
357 for (size_t j = 1; j < sizeof (buf1); ++j)
358 printf (",%02hhx", buf1[j]);
359 putchar_unlocked ('\n');
360 break;
366 static void
367 test_strncat (void)
369 /* First test it as strcat, with big counts, then test the count
370 mechanism. */
371 it = "strncat";
372 (void) strcpy (one, "ijk");
373 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
374 equal (one, "ijklmn", 2); /* Basic test. */
376 (void) strcpy (one, "x");
377 (void) strncat (one, "yz", 99);
378 equal (one, "xyz", 3); /* Writeover. */
379 equal (one+4, "mn", 4); /* Wrote too much? */
381 (void) strcpy (one, "gh");
382 (void) strcpy (two, "ef");
383 (void) strncat (one, two, 99);
384 equal (one, "ghef", 5); /* Basic test encore. */
385 equal (two, "ef", 6); /* Stomped on source? */
387 (void) strcpy (one, "");
388 (void) strncat (one, "", 99);
389 equal (one, "", 7); /* Boundary conditions. */
390 (void) strcpy (one, "ab");
391 (void) strncat (one, "", 99);
392 equal (one, "ab", 8);
393 (void) strcpy (one, "");
394 (void) strncat (one, "cd", 99);
395 equal (one, "cd", 9);
397 (void) strcpy (one, "ab");
398 (void) strncat (one, "cdef", 2);
399 equal (one, "abcd", 10); /* Count-limited. */
401 (void) strncat (one, "gh", 0);
402 equal (one, "abcd", 11); /* Zero count. */
404 (void) strncat (one, "gh", 2);
405 equal (one, "abcdgh", 12); /* Count and length equal. */
407 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
408 equal (one, "abcdghij", 13);
410 int ntest = 14;
411 char buf1[80] __attribute__ ((aligned (16)));
412 char buf2[32] __attribute__ ((aligned (16)));
413 for (size_t n1 = 0; n1 < 16; ++n1)
414 for (size_t n2 = 0; n2 < 16; ++n2)
415 for (size_t n3 = 0; n3 < 32; ++n3)
416 for (size_t n4 = 0; n4 < 16; ++n4)
418 size_t olderrors = errors;
420 memset (buf1, 'b', sizeof (buf1));
422 memset (buf1 + n2, 'a', n3);
423 buf1[n2 + n3] = '\0';
424 strcpy (buf2 + n1, "123");
426 check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
427 == buf1 + n2, ntest);
428 if (errors == olderrors)
429 for (size_t i = 0; i < sizeof (buf1); ++i)
431 if (i < n2)
432 check (buf1[i] == 'b', ntest);
433 else if (i < n2 + n3)
434 check (buf1[i] == 'a', ntest);
435 else if (i < n2 + n3 + 3)
436 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
437 else if (i == n2 + n3 + 3)
438 check (buf1[i] == '\0', ntest);
439 else
440 check (buf1[i] == 'b', ntest);
442 if (errors != olderrors)
444 printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
445 n1, n2, n3, n4, buf1[0]);
446 for (size_t j = 1; j < sizeof (buf1); ++j)
447 printf (",%02hhx", buf1[j]);
448 putchar_unlocked ('\n');
449 break;
455 static void
456 test_strncmp (void)
458 /* First test as strcmp with big counts, then test count code. */
459 it = "strncmp";
460 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
461 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
462 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
463 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
464 check (strncmp ("abcd", "abc", 99) > 0, 5);
465 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
466 check (strncmp ("abce", "abcd", 99) > 0, 7);
467 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
468 check (strncmp ("a\203", "a\003", 2) > 0, 9);
469 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
470 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
471 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
472 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
473 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
474 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
477 static void
478 test_strncpy (void)
480 /* Testing is a bit different because of odd semantics. */
481 it = "strncpy";
482 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
483 equal (one, "abc", 2); /* Did the copy go right? */
485 (void) strcpy (one, "abcdefgh");
486 (void) strncpy (one, "xyz", 2);
487 equal (one, "xycdefgh", 3); /* Copy cut by count. */
489 (void) strcpy (one, "abcdefgh");
490 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
491 equal (one, "xyzdefgh", 4);
493 (void) strcpy (one, "abcdefgh");
494 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
495 equal (one, "xyz", 5);
496 equal (one+4, "efgh", 6); /* Wrote too much? */
498 (void) strcpy (one, "abcdefgh");
499 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
500 equal (one, "xyz", 7);
501 equal (one+4, "", 8);
502 equal (one+5, "fgh", 9);
504 (void) strcpy (one, "abc");
505 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
506 equal (one, "abc", 10);
508 (void) strncpy (one, "", 2); /* Zero-length source. */
509 equal (one, "", 11);
510 equal (one+1, "", 12);
511 equal (one+2, "c", 13);
513 (void) strcpy (one, "hi there");
514 (void) strncpy (two, one, 9);
515 equal (two, "hi there", 14); /* Just paranoia. */
516 equal (one, "hi there", 15); /* Stomped on source? */
519 static void
520 test_strlen (void)
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. */
527 char buf[4096];
528 int i;
529 char *p;
530 for (i=0; i < 0x100; i++)
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);
540 static void
541 test_strnlen (void)
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 check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
549 check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
550 check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
551 check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
552 check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
554 char buf[4096];
555 for (int i = 0; i < 0x100; ++i)
557 char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
558 strcpy (p, "OK");
559 strcpy (p + 3, "BAD/WRONG");
560 check (strnlen (p, 100) == 2, 10 + i);
564 static void
565 test_strchr (void)
567 it = "strchr";
568 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
569 (void) strcpy (one, "abcd");
570 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
571 check (strchr (one, 'd') == one+3, 3); /* End of string. */
572 check (strchr (one, 'a') == one, 4); /* Beginning. */
573 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
574 (void) strcpy (one, "ababa");
575 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
576 (void) strcpy (one, "");
577 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
578 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
580 char buf[4096];
581 int i;
582 char *p;
583 for (i=0; i < 0x100; i++)
585 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
586 strcpy (p, "OK");
587 strcpy (p+3, "BAD/WRONG");
588 check (strchr (p, '/') == NULL, 9+i);
593 static void
594 test_strchrnul (void)
596 const char *os;
597 it = "strchrnul";
598 cp = strchrnul ((os = "abcd"), 'z');
599 check (*cp == '\0', 1); /* Not found. */
600 check (cp == os + 4, 2);
601 (void) strcpy (one, "abcd");
602 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
603 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
604 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
605 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
606 (void) strcpy (one, "ababa");
607 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
608 (void) strcpy (one, "");
609 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
610 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
612 char buf[4096];
613 int i;
614 char *p;
615 for (i=0; i < 0x100; i++)
617 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
618 strcpy (p, "OK");
619 strcpy (p+3, "BAD/WRONG");
620 cp = strchrnul (p, '/');
621 check (*cp == '\0', 9+2*i);
622 check (cp == p+2, 10+2*i);
627 static void
628 test_rawmemchr (void)
630 it = "rawmemchr";
631 (void) strcpy (one, "abcd");
632 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
633 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
634 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
635 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
636 (void) strcpy (one, "ababa");
637 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
638 (void) strcpy (one, "");
639 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
641 char buf[4096];
642 int i;
643 char *p;
644 for (i=0; i < 0x100; i++)
646 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
647 strcpy (p, "OK");
648 strcpy (p+3, "BAD/WRONG");
649 check (rawmemchr (p, 'R') == p+8, 6+i);
654 static void
655 test_index (void)
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. */
671 static void
672 test_strrchr (void)
674 it = "strrchr";
675 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
676 (void) strcpy (one, "abcd");
677 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
678 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
679 check (strrchr (one, 'a') == one, 4); /* Beginning. */
680 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
681 (void) strcpy (one, "ababa");
682 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
683 (void) strcpy (one, "");
684 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
685 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
687 char buf[4096];
688 int i;
689 char *p;
690 for (i=0; i < 0x100; i++)
692 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
693 strcpy (p, "OK");
694 strcpy (p+3, "BAD/WRONG");
695 check (strrchr (p, '/') == NULL, 9+i);
700 static void
701 test_memrchr (void)
703 size_t l;
704 it = "memrchr";
705 check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
706 (void) strcpy (one, "abcd");
707 l = strlen (one) + 1;
708 check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
709 check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
710 check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
711 check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
712 (void) strcpy (one, "ababa");
713 l = strlen (one) + 1;
714 check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
715 (void) strcpy (one, "");
716 l = strlen (one) + 1;
717 check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
718 check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
720 /* now test all possible alignment and length combinations to catch
721 bugs due to unrolled loops (assuming unrolling is limited to no
722 more than 128 byte chunks: */
724 char buf[128 + sizeof (long)];
725 long align, len, i, pos, n = 9;
727 for (align = 0; align < (long) sizeof (long); ++align) {
728 for (len = 0; len < (long) (sizeof (buf) - align); ++len) {
729 for (i = 0; i < len; ++i)
730 buf[align + i] = 'x'; /* don't depend on memset... */
732 for (pos = len - 1; pos >= 0; --pos) {
733 #if 0
734 printf("align %d, len %d, pos %d\n", align, len, pos);
735 #endif
736 check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
737 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
738 n++);
739 buf[align + pos] = '-';
746 static void
747 test_rindex (void)
749 it = "rindex";
750 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
751 (void) strcpy (one, "abcd");
752 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
753 check (rindex (one, 'd') == one+3, 3); /* End of string. */
754 check (rindex (one, 'a') == one, 4); /* Beginning. */
755 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
756 (void) strcpy (one, "ababa");
757 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
758 (void) strcpy (one, "");
759 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
760 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
763 static void
764 test_strpbrk (void)
766 it = "strpbrk";
767 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
768 (void) strcpy(one, "abcd");
769 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
770 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
771 check(strpbrk(one, "a") == one, 4); /* Beginning. */
772 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
773 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
774 (void) strcpy(one, "abcabdea");
775 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
776 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
777 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
778 (void) strcpy(one, "");
779 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
780 (void) strcpy(one, "");
781 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
782 (void) strcpy(one, "");
783 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
784 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
785 (void) strcpy(one, "abcabdea");
786 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
787 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
788 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
789 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
792 static void
793 test_strstr (void)
795 it = "strstr";
796 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
797 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
798 (void) strcpy(one, "abcd");
799 check(strstr(one, "c") == one+2, 3); /* Basic test. */
800 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
801 check(strstr(one, "d") == one+3, 5); /* End of string. */
802 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
803 check(strstr(one, "abc") == one, 7); /* Beginning. */
804 check(strstr(one, "abcd") == one, 8); /* Exact match. */
805 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
806 check(strstr(one, "de") == NULL, 10); /* Past end. */
807 check(strstr(one, "") == one, 11); /* Finding empty. */
808 (void) strcpy(one, "ababa");
809 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
810 (void) strcpy(one, "");
811 check(strstr(one, "b") == NULL, 13); /* Empty string. */
812 check(strstr(one, "") == one, 14); /* Empty in empty string. */
813 (void) strcpy(one, "bcbca");
814 check(strstr(one, "bca") == one+2, 15); /* False start. */
815 (void) strcpy(one, "bbbcabbca");
816 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
819 static void
820 test_strspn (void)
822 it = "strspn";
823 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
824 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
825 check(strspn("abc", "qx") == 0, 3); /* None. */
826 check(strspn("", "ab") == 0, 4); /* Null string. */
827 check(strspn("abc", "") == 0, 5); /* Null search list. */
830 static void
831 test_strcspn (void)
833 it = "strcspn";
834 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
835 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
836 check(strcspn("abc", "abc") == 0, 3); /* None. */
837 check(strcspn("", "ab") == 0, 4); /* Null string. */
838 check(strcspn("abc", "") == 3, 5); /* Null search list. */
841 static void
842 test_strtok (void)
844 it = "strtok";
845 (void) strcpy(one, "first, second, third");
846 equal(strtok(one, ", "), "first", 1); /* Basic test. */
847 equal(one, "first", 2);
848 equal(strtok((char *)NULL, ", "), "second", 3);
849 equal(strtok((char *)NULL, ", "), "third", 4);
850 check(strtok((char *)NULL, ", ") == NULL, 5);
851 (void) strcpy(one, ", first, ");
852 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
853 check(strtok((char *)NULL, ", ") == NULL, 7);
854 (void) strcpy(one, "1a, 1b; 2a, 2b");
855 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
856 equal(strtok((char *)NULL, "; "), "1b", 9);
857 equal(strtok((char *)NULL, ", "), "2a", 10);
858 (void) strcpy(two, "x-y");
859 equal(strtok(two, "-"), "x", 11); /* New string before done. */
860 equal(strtok((char *)NULL, "-"), "y", 12);
861 check(strtok((char *)NULL, "-") == NULL, 13);
862 (void) strcpy(one, "a,b, c,, ,d");
863 equal(strtok(one, ", "), "a", 14); /* Different separators. */
864 equal(strtok((char *)NULL, ", "), "b", 15);
865 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
866 equal(strtok((char *)NULL, " ,"), "d", 17);
867 check(strtok((char *)NULL, ", ") == NULL, 18);
868 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
869 (void) strcpy(one, ", ");
870 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
871 (void) strcpy(one, "");
872 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
873 (void) strcpy(one, "abc");
874 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
875 check(strtok((char *)NULL, ", ") == NULL, 23);
876 (void) strcpy(one, "abc");
877 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
878 check(strtok((char *)NULL, "") == NULL, 25);
879 (void) strcpy(one, "abcdefgh");
880 (void) strcpy(one, "a,b,c");
881 equal(strtok(one, ","), "a", 26); /* Basics again... */
882 equal(strtok((char *)NULL, ","), "b", 27);
883 equal(strtok((char *)NULL, ","), "c", 28);
884 check(strtok((char *)NULL, ",") == NULL, 29);
885 equal(one+6, "gh", 30); /* Stomped past end? */
886 equal(one, "a", 31); /* Stomped old tokens? */
887 equal(one+2, "b", 32);
888 equal(one+4, "c", 33);
891 static void
892 test_strtok_r (void)
894 it = "strtok_r";
895 (void) strcpy(one, "first, second, third");
896 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
897 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
898 equal(one, "first", 2);
899 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
900 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
901 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
902 (void) strcpy(one, ", first, ");
903 cp = NULL;
904 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
905 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
906 (void) strcpy(one, "1a, 1b; 2a, 2b");
907 cp = NULL;
908 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
909 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
910 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
911 (void) strcpy(two, "x-y");
912 cp = NULL;
913 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
914 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
915 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
916 (void) strcpy(one, "a,b, c,, ,d");
917 cp = NULL;
918 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
919 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
920 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
921 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
922 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
923 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
924 (void) strcpy(one, ", ");
925 cp = NULL;
926 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
927 (void) strcpy(one, "");
928 cp = NULL;
929 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
930 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
931 (void) strcpy(one, "abc");
932 cp = NULL;
933 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
934 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
935 (void) strcpy(one, "abc");
936 cp = NULL;
937 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
938 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
939 (void) strcpy(one, "abcdefgh");
940 (void) strcpy(one, "a,b,c");
941 cp = NULL;
942 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
943 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
944 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
945 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
946 equal(one+6, "gh", 31); /* Stomped past end? */
947 equal(one, "a", 32); /* Stomped old tokens? */
948 equal(one+2, "b", 33);
949 equal(one+4, "c", 34);
950 strcpy (one, ":::");
951 cp = NULL;
952 check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
953 check (strtok_r (NULL, ":", &cp) == NULL, 36);
956 static void
957 test_strsep (void)
959 char *ptr;
960 it = "strsep";
961 cp = strcpy(one, "first, second, third");
962 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
963 equal(one, "first", 2);
964 equal(strsep(&cp, ", "), "", 3);
965 equal(strsep(&cp, ", "), "second", 4);
966 equal(strsep(&cp, ", "), "", 5);
967 equal(strsep(&cp, ", "), "third", 6);
968 check(strsep(&cp, ", ") == NULL, 7);
969 cp = strcpy(one, ", first, ");
970 equal(strsep(&cp, ", "), "", 8);
971 equal(strsep(&cp, ", "), "", 9);
972 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
973 equal(strsep(&cp, ", "), "", 11);
974 equal(strsep(&cp, ", "), "", 12);
975 check(strsep(&cp, ", ") == NULL, 13);
976 cp = strcpy(one, "1a, 1b; 2a, 2b");
977 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
978 equal(strsep(&cp, ", "), "", 15);
979 equal(strsep(&cp, "; "), "1b", 16);
980 equal(strsep(&cp, ", "), "", 17);
981 equal(strsep(&cp, ", "), "2a", 18);
982 cp = strcpy(two, "x-y");
983 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
984 equal(strsep(&cp, "-"), "y", 20);
985 check(strsep(&cp, "-") == NULL, 21);
986 cp = strcpy(one, "a,b, c,, ,d ");
987 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
988 equal(strsep(&cp, ", "), "b", 23);
989 equal(strsep(&cp, " ,"), "", 24);
990 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
991 equal(strsep(&cp, " ,"), "", 26);
992 equal(strsep(&cp, " ,"), "", 27);
993 equal(strsep(&cp, " ,"), "", 28);
994 equal(strsep(&cp, " ,"), "d", 29);
995 equal(strsep(&cp, " ,"), "", 30);
996 check(strsep(&cp, ", ") == NULL, 31);
997 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
998 cp = strcpy(one, ", ");
999 equal(strsep(&cp, ", "), "", 33);
1000 equal(strsep(&cp, ", "), "", 34);
1001 equal(strsep(&cp, ", "), "", 35);
1002 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
1003 cp = strcpy(one, "");
1004 equal(strsep(&cp, ", "), "", 37);
1005 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
1006 cp = strcpy(one, "abc");
1007 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
1008 check(strsep(&cp, ", ") == NULL, 40);
1009 cp = strcpy(one, "abc");
1010 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
1011 check(strsep(&cp, "") == NULL, 42);
1012 (void) strcpy(one, "abcdefgh");
1013 cp = strcpy(one, "a,b,c");
1014 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
1015 equal(strsep(&cp, ","), "b", 44);
1016 equal(strsep(&cp, ","), "c", 45);
1017 check(strsep(&cp, ",") == NULL, 46);
1018 equal(one+6, "gh", 47); /* Stomped past end? */
1019 equal(one, "a", 48); /* Stomped old tokens? */
1020 equal(one+2, "b", 49);
1021 equal(one+4, "c", 50);
1024 char text[] = "This,is,a,test";
1025 char *list = strdupa (text);
1026 equal (strsep (&list, ","), "This", 51);
1027 equal (strsep (&list, ","), "is", 52);
1028 equal (strsep (&list, ","), "a", 53);
1029 equal (strsep (&list, ","), "test", 54);
1030 check (strsep (&list, ",") == NULL, 55);
1033 cp = strcpy(one, "a,b, c,, ,d,");
1034 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1035 equal(strsep(&cp, ","), "b", 57);
1036 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1037 equal(strsep(&cp, ","), "", 59);
1038 equal(strsep(&cp, ","), " ", 60);
1039 equal(strsep(&cp, ","), "d", 61);
1040 equal(strsep(&cp, ","), "", 62);
1041 check(strsep(&cp, ",") == NULL, 63);
1042 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1044 cp = strcpy(one, "a,b, c,, ,d,");
1045 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1046 equal(strsep(&cp, "x,y"), "b", 66);
1047 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1048 equal(strsep(&cp, "xy,"), "", 68);
1049 equal(strsep(&cp, "x,y"), " ", 69);
1050 equal(strsep(&cp, ",xy"), "d", 70);
1051 equal(strsep(&cp, "xy,"), "", 71);
1052 check(strsep(&cp, "x,y") == NULL, 72);
1053 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1055 cp = strcpy(one, "ABC");
1056 one[4] = ':';
1057 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1058 ptr = strsep(&cp, ":");
1059 equal(ptr, "", 75);
1060 check(ptr == one + 3, 76);
1061 check(cp == NULL, 77);
1063 cp = strcpy(one, "ABC");
1064 one[4] = ':';
1065 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1066 ptr = strsep(&cp, ":.");
1067 equal(ptr, "", 79);
1068 check(ptr == one + 3, 80);
1070 cp = strcpy(one, "ABC"); /* No token in string. */
1071 equal(strsep(&cp, ","), "ABC", 81);
1072 check(cp == NULL, 82);
1074 *one = '\0'; /* Empty string. */
1075 cp = one;
1076 ptr = strsep(&cp, ",");
1077 equal(ptr, "", 83);
1078 check(ptr == one, 84);
1079 check(cp == NULL, 85);
1081 *one = '\0'; /* Empty string and no token. */
1082 cp = one;
1083 ptr = strsep(&cp, "");
1084 equal(ptr, "", 86);
1085 check(ptr == one , 87);
1086 check(cp == NULL, 88);
1089 static void
1090 test_memcmp (void)
1092 int cnt = 1;
1093 char one[21];
1094 char two[21];
1096 it = "memcmp";
1097 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1098 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1099 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1100 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1101 check(memcmp("alph", "cold", 4) < 0, cnt++);
1102 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1103 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1104 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1105 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1106 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1107 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1108 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1109 /* Comparisons with shifting 4-byte boundaries. */
1110 for (int i = 0; i < 4; ++i)
1112 char *a = one + i;
1113 char *b = two + i;
1114 memcpy(a, "--------11112222", 16);
1115 memcpy(b, "--------33334444", 16);
1116 check(memcmp(b, a, 16) > 0, cnt++);
1117 check(memcmp(a, b, 16) < 0, cnt++);
1121 static void
1122 test_memchr (void)
1124 it = "memchr";
1125 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1126 (void) strcpy(one, "abcd");
1127 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1128 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1129 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1130 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1131 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1132 (void) strcpy(one, "ababa");
1133 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1134 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1135 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1136 (void) strcpy(one, "a\203b");
1137 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1139 /* now test all possible alignment and length combinations to catch
1140 bugs due to unrolled loops (assuming unrolling is limited to no
1141 more than 128 byte chunks: */
1143 char buf[128 + sizeof (long)];
1144 long align, len, i, pos;
1146 for (align = 0; align < (long) sizeof (long); ++align) {
1147 for (len = 0; len < (long) (sizeof (buf) - align); ++len) {
1148 for (i = 0; i < len; ++i) {
1149 buf[align + i] = 'x'; /* don't depend on memset... */
1151 for (pos = 0; pos < len; ++pos) {
1152 #if 0
1153 printf("align %d, len %d, pos %d\n", align, len, pos);
1154 #endif
1155 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1156 check(memchr(buf + align, 'x', pos) == NULL, 11);
1157 buf[align + pos] = '-';
1164 static void
1165 test_memcpy (void)
1167 int i;
1168 it = "memcpy";
1169 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1170 equal(one, "abc", 2); /* Did the copy go right? */
1172 (void) strcpy(one, "abcdefgh");
1173 (void) memcpy(one+1, "xyz", 2);
1174 equal(one, "axydefgh", 3); /* Basic test. */
1176 (void) strcpy(one, "abc");
1177 (void) memcpy(one, "xyz", 0);
1178 equal(one, "abc", 4); /* Zero-length copy. */
1180 (void) strcpy(one, "hi there");
1181 (void) strcpy(two, "foo");
1182 (void) memcpy(two, one, 9);
1183 equal(two, "hi there", 5); /* Just paranoia. */
1184 equal(one, "hi there", 6); /* Stomped on source? */
1186 for (i = 0; i < 16; i++)
1188 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1189 strcpy (one, x);
1190 check (memcpy (one + i, "hi there", 9) == one + i,
1191 7 + (i * 6)); /* Unaligned destination. */
1192 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1193 equal (one + i, "hi there", 9 + (i * 6));
1194 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1195 check (memcpy (two, one + i, 9) == two,
1196 11 + (i * 6)); /* Unaligned source. */
1197 equal (two, "hi there", 12 + (i * 6));
1201 static void
1202 test_mempcpy (void)
1204 int i;
1205 it = "mempcpy";
1206 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1207 equal(one, "abc", 2); /* Did the copy go right? */
1209 (void) strcpy(one, "abcdefgh");
1210 (void) mempcpy(one+1, "xyz", 2);
1211 equal(one, "axydefgh", 3); /* Basic test. */
1213 (void) strcpy(one, "abc");
1214 (void) mempcpy(one, "xyz", 0);
1215 equal(one, "abc", 4); /* Zero-length copy. */
1217 (void) strcpy(one, "hi there");
1218 (void) strcpy(two, "foo");
1219 (void) mempcpy(two, one, 9);
1220 equal(two, "hi there", 5); /* Just paranoia. */
1221 equal(one, "hi there", 6); /* Stomped on source? */
1223 for (i = 0; i < 16; i++)
1225 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1226 strcpy (one, x);
1227 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1228 7 + (i * 6)); /* Unaligned destination. */
1229 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1230 equal (one + i, "hi there", 9 + (i * 6));
1231 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1232 check (mempcpy (two, one + i, 9) == two + 9,
1233 11 + (i * 6)); /* Unaligned source. */
1234 equal (two, "hi there", 12 + (i * 6));
1238 static void
1239 test_memmove (void)
1241 it = "memmove";
1242 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1243 equal(one, "abc", 2); /* Did the copy go right? */
1245 (void) strcpy(one, "abcdefgh");
1246 (void) memmove(one+1, "xyz", 2);
1247 equal(one, "axydefgh", 3); /* Basic test. */
1249 (void) strcpy(one, "abc");
1250 (void) memmove(one, "xyz", 0);
1251 equal(one, "abc", 4); /* Zero-length copy. */
1253 (void) strcpy(one, "hi there");
1254 (void) strcpy(two, "foo");
1255 (void) memmove(two, one, 9);
1256 equal(two, "hi there", 5); /* Just paranoia. */
1257 equal(one, "hi there", 6); /* Stomped on source? */
1259 (void) strcpy(one, "abcdefgh");
1260 (void) memmove(one+1, one, 9);
1261 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1263 (void) strcpy(one, "abcdefgh");
1264 (void) memmove(one+1, one+2, 7);
1265 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1267 (void) strcpy(one, "abcdefgh");
1268 (void) memmove(one, one, 9);
1269 equal(one, "abcdefgh", 9); /* 100% overlap. */
1272 static void
1273 test_memccpy (void)
1275 /* First test like memcpy, then the search part The SVID, the only
1276 place where memccpy is mentioned, says overlap might fail, so we
1277 don't try it. Besides, it's hard to see the rationale for a
1278 non-left-to-right memccpy. */
1279 it = "memccpy";
1280 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1281 equal(one, "abc", 2); /* Did the copy go right? */
1283 (void) strcpy(one, "abcdefgh");
1284 (void) memccpy(one+1, "xyz", 'q', 2);
1285 equal(one, "axydefgh", 3); /* Basic test. */
1287 (void) strcpy(one, "abc");
1288 (void) memccpy(one, "xyz", 'q', 0);
1289 equal(one, "abc", 4); /* Zero-length copy. */
1291 (void) strcpy(one, "hi there");
1292 (void) strcpy(two, "foo");
1293 (void) memccpy(two, one, 'q', 9);
1294 equal(two, "hi there", 5); /* Just paranoia. */
1295 equal(one, "hi there", 6); /* Stomped on source? */
1297 (void) strcpy(one, "abcdefgh");
1298 (void) strcpy(two, "horsefeathers");
1299 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1300 equal(one, "abcdefgh", 8); /* Source intact? */
1301 equal(two, "abcdefeathers", 9); /* Copy correct? */
1303 (void) strcpy(one, "abcd");
1304 (void) strcpy(two, "bumblebee");
1305 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1306 equal(two, "aumblebee", 11);
1307 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1308 equal(two, "abcdlebee", 13);
1309 (void) strcpy(one, "xyz");
1310 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1311 equal(two, "xbcdlebee", 15);
1314 static void
1315 test_memset (void)
1317 int i;
1319 it = "memset";
1320 (void) strcpy(one, "abcdefgh");
1321 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1322 equal(one, "axxxefgh", 2); /* Basic test. */
1324 (void) memset(one+2, 'y', 0);
1325 equal(one, "axxxefgh", 3); /* Zero-length set. */
1327 (void) memset(one+5, 0, 1);
1328 equal(one, "axxxe", 4); /* Zero fill. */
1329 equal(one+6, "gh", 5); /* And the leftover. */
1331 (void) memset(one+2, 010045, 1);
1332 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1334 /* Non-8bit fill character. */
1335 memset (one, 0x101, sizeof (one));
1336 for (i = 0; i < (int) sizeof (one); ++i)
1337 check (one[i] == '\01', 7);
1339 /* Test for more complex versions of memset, for all alignments and
1340 lengths up to 256. This test takes a little while, perhaps it should
1341 be made weaker? */
1343 char data[512];
1344 int j;
1345 int k;
1346 int c;
1348 for (i = 0; i < 512; i++)
1349 data[i] = 'x';
1350 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1351 memset(,'y',) */
1352 for (j = 0; j < 256; j++)
1353 for (i = 0; i < 256; i++)
1355 memset (data + i, c, j);
1356 for (k = 0; k < i; k++)
1357 if (data[k] != 'x')
1358 goto fail;
1359 for (k = i; k < i+j; k++)
1361 if (data[k] != c)
1362 goto fail;
1363 data[k] = 'x';
1365 for (k = i+j; k < 512; k++)
1366 if (data[k] != 'x')
1367 goto fail;
1368 continue;
1370 fail:
1371 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1376 static void
1377 test_bcopy (void)
1379 /* Much like memcpy. Berklix manual is silent about overlap, so
1380 don't test it. */
1381 it = "bcopy";
1382 (void) bcopy("abc", one, 4);
1383 equal(one, "abc", 1); /* Simple copy. */
1385 (void) strcpy(one, "abcdefgh");
1386 (void) bcopy("xyz", one+1, 2);
1387 equal(one, "axydefgh", 2); /* Basic test. */
1389 (void) strcpy(one, "abc");
1390 (void) bcopy("xyz", one, 0);
1391 equal(one, "abc", 3); /* Zero-length copy. */
1393 (void) strcpy(one, "hi there");
1394 (void) strcpy(two, "foo");
1395 (void) bcopy(one, two, 9);
1396 equal(two, "hi there", 4); /* Just paranoia. */
1397 equal(one, "hi there", 5); /* Stomped on source? */
1400 static void
1401 test_bzero (void)
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);
1410 (void) strcpy(one, "abcdef");
1411 bzero(one+2, 0);
1412 equal(one, "abcdef", 4); /* Zero-length copy. */
1415 static void
1416 test_strndup (void)
1418 char *p, *q;
1419 it = "strndup";
1420 p = strndup("abcdef", 12);
1421 check(p != NULL, 1);
1422 if (p != NULL)
1424 equal(p, "abcdef", 2);
1425 q = strndup(p + 1, 2);
1426 check(q != NULL, 3);
1427 if (q != NULL)
1428 equal(q, "bc", 4);
1429 free (q);
1431 free (p);
1432 p = strndup("abc def", 3);
1433 check(p != NULL, 5);
1434 if (p != NULL)
1435 equal(p, "abc", 6);
1436 free (p);
1439 static void
1440 test_bcmp (void)
1442 it = "bcmp";
1443 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1444 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1445 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1446 check(bcmp("abce", "abcd", 4) != 0, 4);
1447 check(bcmp("alph", "beta", 4) != 0, 5);
1448 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1449 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1452 static void
1453 test_memcmpeq (void)
1455 it = "__memcmpeq";
1456 check (__memcmpeq ("a", "a", 1) == 0, 1); /* Identity. */
1457 check (__memcmpeq ("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1458 check (__memcmpeq ("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1459 check (__memcmpeq ("abce", "abcd", 4) != 0, 4);
1460 check (__memcmpeq ("alph", "beta", 4) != 0, 5);
1461 check (__memcmpeq ("abce", "abcd", 3) == 0, 6); /* Count limited. */
1462 check (__memcmpeq ("abc", "def", 0) == 0, 8); /* Zero count. */
1465 static void
1466 test_strerror (void)
1468 it = "strerror";
1469 check(strerror(EDOM) != 0, 1);
1470 check(strerror(ERANGE) != 0, 2);
1471 check(strerror(ENOENT) != 0, 3);
1474 static void
1475 test_strcasecmp (void)
1477 it = "strcasecmp";
1478 /* Note that the locale is "C". */
1479 check(strcasecmp("a", "a") == 0, 1);
1480 check(strcasecmp("a", "A") == 0, 2);
1481 check(strcasecmp("A", "a") == 0, 3);
1482 check(strcasecmp("a", "b") < 0, 4);
1483 check(strcasecmp("c", "b") > 0, 5);
1484 check(strcasecmp("abc", "AbC") == 0, 6);
1485 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1486 check(strcasecmp("", "0123456789") < 0, 8);
1487 check(strcasecmp("AbC", "") > 0, 9);
1488 check(strcasecmp("AbC", "A") > 0, 10);
1489 check(strcasecmp("AbC", "Ab") > 0, 11);
1490 check(strcasecmp("AbC", "ab") > 0, 12);
1493 static void
1494 test_strncasecmp (void)
1496 it = "strncasecmp";
1497 /* Note that the locale is "C". */
1498 check(strncasecmp("a", "a", 5) == 0, 1);
1499 check(strncasecmp("a", "A", 5) == 0, 2);
1500 check(strncasecmp("A", "a", 5) == 0, 3);
1501 check(strncasecmp("a", "b", 5) < 0, 4);
1502 check(strncasecmp("c", "b", 5) > 0, 5);
1503 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1504 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1505 check(strncasecmp("", "0123456789", 10) < 0, 8);
1506 check(strncasecmp("AbC", "", 5) > 0, 9);
1507 check(strncasecmp("AbC", "A", 5) > 0, 10);
1508 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1509 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1510 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1511 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1512 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1513 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1514 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1515 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1516 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1517 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1521 main (void)
1523 int status;
1525 /* Test strcmp first because we use it to test other things. */
1526 test_strcmp ();
1528 /* Test strcpy next because we need it to set up other tests. */
1529 test_strcpy ();
1531 /* A closely related function is stpcpy. */
1532 test_stpcpy ();
1534 /* stpncpy. */
1535 test_stpncpy ();
1537 /* strcat. */
1538 test_strcat ();
1540 /* strncat. */
1541 test_strncat ();
1543 /* strncmp. */
1544 test_strncmp ();
1546 /* strncpy. */
1547 test_strncpy ();
1549 /* strlen. */
1550 test_strlen ();
1552 /* strnlen. */
1553 test_strnlen ();
1555 /* strchr. */
1556 test_strchr ();
1558 /* strchrnul. */
1559 test_strchrnul ();
1561 /* rawmemchr. */
1562 test_rawmemchr ();
1564 /* index - just like strchr. */
1565 test_index ();
1567 /* strrchr. */
1568 test_strrchr ();
1570 /* memrchr. */
1571 test_memrchr ();
1573 /* rindex - just like strrchr. */
1574 test_rindex ();
1576 /* strpbrk - somewhat like strchr. */
1577 test_strpbrk ();
1579 /* strstr - somewhat like strchr. */
1580 test_strstr ();
1582 /* strspn. */
1583 test_strspn ();
1585 /* strcspn. */
1586 test_strcspn ();
1588 /* strtok - the hard one. */
1589 test_strtok ();
1591 /* strtok_r. */
1592 test_strtok_r ();
1594 /* strsep. */
1595 test_strsep ();
1597 /* memcmp. */
1598 test_memcmp ();
1600 /* memchr. */
1601 test_memchr ();
1603 /* memcpy - need not work for overlap. */
1604 test_memcpy ();
1606 /* memmove - must work on overlap. */
1607 test_memmove ();
1609 /* mempcpy */
1610 test_mempcpy ();
1612 /* memccpy. */
1613 test_memccpy ();
1615 /* memset. */
1616 test_memset ();
1618 /* bcopy. */
1619 test_bcopy ();
1621 /* bzero. */
1622 test_bzero ();
1624 /* bcmp - somewhat like memcmp. */
1625 test_bcmp ();
1627 /* __memcmpeq - somewhat like memcmp. */
1628 test_memcmpeq ();
1630 /* strndup. */
1631 test_strndup ();
1633 /* strerror - VERY system-dependent. */
1634 test_strerror ();
1636 /* strcasecmp. Without locale dependencies. */
1637 test_strcasecmp ();
1639 /* strncasecmp. Without locale dependencies. */
1640 test_strncasecmp ();
1642 if (errors == 0)
1644 status = EXIT_SUCCESS;
1645 puts("No errors.");
1647 else
1649 status = EXIT_FAILURE;
1650 printf("%Zd errors.\n", errors);
1653 return status;