Update install.texi, and regenerate INSTALL.
[glibc.git] / string / tester.c
blob8de70ad3ce9ae7319ea6672b61295c09b4c81cac
1 /* Tester for string functions.
2 Copyright (C) 1995-2023 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 <stdint.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <fcntl.h>
36 #include <libc-diag.h>
38 /* This file tests a range of corner cases of string functions,
39 including cases where truncation occurs or where sizes specified
40 are larger than the actual buffers, which result in various
41 warnings. */
42 DIAG_IGNORE_NEEDS_COMMENT (8, "-Warray-bounds");
43 DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args");
44 #if __GNUC_PREREQ (7, 0)
45 DIAG_IGNORE_NEEDS_COMMENT (9, "-Wrestrict");
46 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
47 #endif
48 #if __GNUC_PREREQ (8, 0)
49 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
50 #endif
51 #if __GNUC_PREREQ (11, 0)
52 DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
53 #endif
56 #define STREQ(a, b) (strcmp((a), (b)) == 0)
58 const char *it = "<UNSET>"; /* Routine name for message routines. */
59 size_t errors = 0;
61 /* Complain if condition is not true. */
62 static void
63 check (int thing, int number)
65 if (!thing)
67 printf ("%s flunked test %d\n", it, number);
68 ++errors;
72 /* Complain if first two args don't strcmp as equal. */
73 static void
74 equal (const char *a, const char *b, int number)
76 check (a != NULL && b != NULL && STREQ (a, b), number);
79 char one[50];
80 char two[50];
81 char *cp;
83 static void
84 test_strcmp (void)
86 it = "strcmp";
87 check (strcmp ("", "") == 0, 1); /* Trivial case. */
88 check (strcmp ("a", "a") == 0, 2); /* Identity. */
89 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
90 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
91 check (strcmp ("abcd", "abc") > 0, 5);
92 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
93 check (strcmp ("abce", "abcd") > 0, 7);
94 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
95 check (strcmp ("a\203", "a\003") > 0, 9);
98 char buf1[0x40], buf2[0x40];
99 int i, j;
100 for (i=0; i < 0x10; i++)
101 for (j = 0; j < 0x10; j++)
103 int k;
104 for (k = 0; k < 0x3f; k++)
106 buf1[k] = '0' ^ (k & 4);
107 buf2[k] = '4' ^ (k & 4);
109 buf1[i] = buf1[0x3f] = 0;
110 buf2[j] = buf2[0x3f] = 0;
111 for (k = 0; k < 0xf; k++)
113 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
114 check (strcmp (buf1+i,buf2+j) == 0, cnum);
115 buf1[i+k] = 'A' + i + k;
116 buf1[i+k+1] = 0;
117 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
118 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
119 buf2[j+k] = 'B' + i + k;
120 buf2[j+k+1] = 0;
121 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
122 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
123 buf2[j+k] = 'A' + i + k;
124 buf1[i] = 'A' + i + 0x80;
125 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
126 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
127 buf1[i] = 'A' + i;
133 #define SIMPLE_COPY(fn, n, str, ntest) \
134 do { \
135 int __n; \
136 char *cp; \
137 for (__n = 0; __n < (int) sizeof (one); ++__n) \
138 one[__n] = 'Z'; \
139 fn (one, str); \
140 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
141 check (*cp == '0' + (n % 10), ntest); \
142 check (*cp == '\0', ntest); \
143 } while (0)
145 static void
146 test_strcpy (void)
148 int i;
149 it = "strcpy";
150 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
151 equal (one, "abcd", 2); /* Basic test. */
153 (void) strcpy (one, "x");
154 equal (one, "x", 3); /* Writeover. */
155 equal (one+2, "cd", 4); /* Wrote too much? */
157 (void) strcpy (two, "hi there");
158 (void) strcpy (one, two);
159 equal (one, "hi there", 5); /* Basic test encore. */
160 equal (two, "hi there", 6); /* Stomped on source? */
162 (void) strcpy (one, "");
163 equal (one, "", 7); /* Boundary condition. */
165 for (i = 0; i < 16; i++)
167 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
168 equal (one + i, "hi there", 8 + (i * 2));
169 (void) strcpy (two, one + i); /* Unaligned source. */
170 equal (two, "hi there", 9 + (i * 2));
173 SIMPLE_COPY(strcpy, 0, "", 41);
174 SIMPLE_COPY(strcpy, 1, "1", 42);
175 SIMPLE_COPY(strcpy, 2, "22", 43);
176 SIMPLE_COPY(strcpy, 3, "333", 44);
177 SIMPLE_COPY(strcpy, 4, "4444", 45);
178 SIMPLE_COPY(strcpy, 5, "55555", 46);
179 SIMPLE_COPY(strcpy, 6, "666666", 47);
180 SIMPLE_COPY(strcpy, 7, "7777777", 48);
181 SIMPLE_COPY(strcpy, 8, "88888888", 49);
182 SIMPLE_COPY(strcpy, 9, "999999999", 50);
183 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
184 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
185 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
186 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
187 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
188 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
189 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
191 /* Simple test using implicitly coerced `void *' arguments. */
192 const void *src = "frobozz";
193 void *dst = one;
194 check (strcpy (dst, src) == dst, 1);
195 equal (dst, "frobozz", 2);
198 static void
199 test_stpcpy (void)
201 it = "stpcpy";
202 check ((stpcpy (one, "a") - one) == 1, 1);
203 equal (one, "a", 2);
205 check ((stpcpy (one, "ab") - one) == 2, 3);
206 equal (one, "ab", 4);
208 check ((stpcpy (one, "abc") - one) == 3, 5);
209 equal (one, "abc", 6);
211 check ((stpcpy (one, "abcd") - one) == 4, 7);
212 equal (one, "abcd", 8);
214 check ((stpcpy (one, "abcde") - one) == 5, 9);
215 equal (one, "abcde", 10);
217 check ((stpcpy (one, "abcdef") - one) == 6, 11);
218 equal (one, "abcdef", 12);
220 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
221 equal (one, "abcdefg", 14);
223 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
224 equal (one, "abcdefgh", 16);
226 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
227 equal (one, "abcdefghi", 18);
229 check ((stpcpy (one, "x") - one) == 1, 19);
230 equal (one, "x", 20); /* Writeover. */
231 equal (one+2, "cdefghi", 21); /* Wrote too much? */
233 check ((stpcpy (one, "xx") - one) == 2, 22);
234 equal (one, "xx", 23); /* Writeover. */
235 equal (one+3, "defghi", 24); /* Wrote too much? */
237 check ((stpcpy (one, "xxx") - one) == 3, 25);
238 equal (one, "xxx", 26); /* Writeover. */
239 equal (one+4, "efghi", 27); /* Wrote too much? */
241 check ((stpcpy (one, "xxxx") - one) == 4, 28);
242 equal (one, "xxxx", 29); /* Writeover. */
243 equal (one+5, "fghi", 30); /* Wrote too much? */
245 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
246 equal (one, "xxxxx", 32); /* Writeover. */
247 equal (one+6, "ghi", 33); /* Wrote too much? */
249 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
250 equal (one, "xxxxxx", 35); /* Writeover. */
251 equal (one+7, "hi", 36); /* Wrote too much? */
253 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
254 equal (one, "xxxxxxx", 38); /* Writeover. */
255 equal (one+8, "i", 39); /* Wrote too much? */
257 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
258 equal (one, "abc", 41);
259 equal (one + 4, "xxx", 42);
261 SIMPLE_COPY(stpcpy, 0, "", 43);
262 SIMPLE_COPY(stpcpy, 1, "1", 44);
263 SIMPLE_COPY(stpcpy, 2, "22", 45);
264 SIMPLE_COPY(stpcpy, 3, "333", 46);
265 SIMPLE_COPY(stpcpy, 4, "4444", 47);
266 SIMPLE_COPY(stpcpy, 5, "55555", 48);
267 SIMPLE_COPY(stpcpy, 6, "666666", 49);
268 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
269 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
270 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
271 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
272 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
273 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
274 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
275 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
276 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
277 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
280 static void
281 test_stpncpy (void)
283 it = "stpncpy";
284 memset (one, 'x', sizeof (one));
285 check (stpncpy (one, "abc", 2) == one + 2, 1);
286 check (stpncpy (one, "abc", 3) == one + 3, 2);
287 check (stpncpy (one, "abc", 4) == one + 3, 3);
288 check (one[3] == '\0' && one[4] == 'x', 4);
289 check (stpncpy (one, "abcd", 5) == one + 4, 5);
290 check (one[4] == '\0' && one[5] == 'x', 6);
291 check (stpncpy (one, "abcd", 6) == one + 4, 7);
292 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
295 static void
296 test_strcat (void)
298 it = "strcat";
299 (void) strcpy (one, "ijk");
300 check (strcat (one, "lmn") == one, 1); /* Returned value. */
301 equal (one, "ijklmn", 2); /* Basic test. */
303 (void) strcpy (one, "x");
304 (void) strcat (one, "yz");
305 equal (one, "xyz", 3); /* Writeover. */
306 equal (one+4, "mn", 4); /* Wrote too much? */
308 (void) strcpy (one, "gh");
309 (void) strcpy (two, "ef");
310 (void) strcat (one, two);
311 equal (one, "ghef", 5); /* Basic test encore. */
312 equal (two, "ef", 6); /* Stomped on source? */
314 (void) strcpy (one, "");
315 (void) strcat (one, "");
316 equal (one, "", 7); /* Boundary conditions. */
317 (void) strcpy (one, "ab");
318 (void) strcat (one, "");
319 equal (one, "ab", 8);
320 (void) strcpy (one, "");
321 (void) strcat (one, "cd");
322 equal (one, "cd", 9);
324 int ntest = 10;
325 char buf1[80] __attribute__ ((aligned (16)));
326 char buf2[32] __attribute__ ((aligned (16)));
327 for (size_t n1 = 0; n1 < 16; ++n1)
328 for (size_t n2 = 0; n2 < 16; ++n2)
329 for (size_t n3 = 0; n3 < 32; ++n3)
331 size_t olderrors = errors;
333 memset (buf1, 'b', sizeof (buf1));
335 memset (buf1 + n2, 'a', n3);
336 buf1[n2 + n3] = '\0';
337 strcpy (buf2 + n1, "123");
339 check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
340 if (errors == olderrors)
341 for (size_t i = 0; i < sizeof (buf1); ++i)
343 if (i < n2)
344 check (buf1[i] == 'b', ntest);
345 else if (i < n2 + n3)
346 check (buf1[i] == 'a', ntest);
347 else if (i < n2 + n3 + 3)
348 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
349 else if (i == n2 + n3 + 3)
350 check (buf1[i] == '\0', ntest);
351 else
352 check (buf1[i] == 'b', ntest);
354 if (errors != olderrors)
356 printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
357 n1, n2, n3, buf1[0]);
358 for (size_t j = 1; j < sizeof (buf1); ++j)
359 printf (",%02hhx", buf1[j]);
360 putchar_unlocked ('\n');
361 break;
367 static void
368 test_strncat (void)
370 /* First test it as strcat, with big counts, then test the count
371 mechanism. */
372 it = "strncat";
373 (void) strcpy (one, "ijk");
374 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
375 equal (one, "ijklmn", 2); /* Basic test. */
377 (void) strcpy (one, "x");
378 (void) strncat (one, "yz", 99);
379 equal (one, "xyz", 3); /* Writeover. */
380 equal (one+4, "mn", 4); /* Wrote too much? */
382 (void) strcpy (one, "gh");
383 (void) strcpy (two, "ef");
384 (void) strncat (one, two, 99);
385 equal (one, "ghef", 5); /* Basic test encore. */
386 equal (two, "ef", 6); /* Stomped on source? */
388 (void) strcpy (one, "");
389 (void) strncat (one, "", 99);
390 equal (one, "", 7); /* Boundary conditions. */
391 (void) strcpy (one, "ab");
392 (void) strncat (one, "", 99);
393 equal (one, "ab", 8);
394 (void) strcpy (one, "");
395 (void) strncat (one, "cd", 99);
396 equal (one, "cd", 9);
398 (void) strcpy (one, "ab");
399 (void) strncat (one, "cdef", 2);
400 equal (one, "abcd", 10); /* Count-limited. */
402 (void) strncat (one, "gh", 0);
403 equal (one, "abcd", 11); /* Zero count. */
405 (void) strncat (one, "gh", 2);
406 equal (one, "abcdgh", 12); /* Count and length equal. */
408 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
409 equal (one, "abcdghij", 13);
411 int ntest = 14;
412 char buf1[80] __attribute__ ((aligned (16)));
413 char buf2[32] __attribute__ ((aligned (16)));
414 for (size_t n1 = 0; n1 < 16; ++n1)
415 for (size_t n2 = 0; n2 < 16; ++n2)
416 for (size_t n3 = 0; n3 < 32; ++n3)
417 for (size_t n4 = 0; n4 < 16; ++n4)
419 size_t olderrors = errors;
421 memset (buf1, 'b', sizeof (buf1));
423 memset (buf1 + n2, 'a', n3);
424 buf1[n2 + n3] = '\0';
425 strcpy (buf2 + n1, "123");
427 check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
428 == buf1 + n2, ntest);
429 if (errors == olderrors)
430 for (size_t i = 0; i < sizeof (buf1); ++i)
432 if (i < n2)
433 check (buf1[i] == 'b', ntest);
434 else if (i < n2 + n3)
435 check (buf1[i] == 'a', ntest);
436 else if (i < n2 + n3 + 3)
437 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
438 else if (i == n2 + n3 + 3)
439 check (buf1[i] == '\0', ntest);
440 else
441 check (buf1[i] == 'b', ntest);
443 if (errors != olderrors)
445 printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
446 n1, n2, n3, n4, buf1[0]);
447 for (size_t j = 1; j < sizeof (buf1); ++j)
448 printf (",%02hhx", buf1[j]);
449 putchar_unlocked ('\n');
450 break;
456 static void
457 test_strncmp (void)
459 /* First test as strcmp with big counts, then test count code. */
460 it = "strncmp";
461 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
462 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
463 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
464 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
465 check (strncmp ("abcd", "abc", 99) > 0, 5);
466 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
467 check (strncmp ("abce", "abcd", 99) > 0, 7);
468 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
469 check (strncmp ("a\203", "a\003", 2) > 0, 9);
470 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
471 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
472 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
473 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
474 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
475 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
478 static void
479 test_strncpy (void)
481 /* Testing is a bit different because of odd semantics. */
482 it = "strncpy";
483 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
484 equal (one, "abc", 2); /* Did the copy go right? */
486 (void) strcpy (one, "abcdefgh");
487 (void) strncpy (one, "xyz", 2);
488 equal (one, "xycdefgh", 3); /* Copy cut by count. */
490 (void) strcpy (one, "abcdefgh");
491 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
492 equal (one, "xyzdefgh", 4);
494 (void) strcpy (one, "abcdefgh");
495 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
496 equal (one, "xyz", 5);
497 equal (one+4, "efgh", 6); /* Wrote too much? */
499 (void) strcpy (one, "abcdefgh");
500 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
501 equal (one, "xyz", 7);
502 equal (one+4, "", 8);
503 equal (one+5, "fgh", 9);
505 (void) strcpy (one, "abc");
506 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
507 equal (one, "abc", 10);
509 (void) strncpy (one, "", 2); /* Zero-length source. */
510 equal (one, "", 11);
511 equal (one+1, "", 12);
512 equal (one+2, "c", 13);
514 (void) strcpy (one, "hi there");
515 (void) strncpy (two, one, 9);
516 equal (two, "hi there", 14); /* Just paranoia. */
517 equal (one, "hi there", 15); /* Stomped on source? */
520 static void
521 test_strlen (void)
523 it = "strlen";
524 check (strlen ("") == 0, 1); /* Empty. */
525 check (strlen ("a") == 1, 2); /* Single char. */
526 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
528 char buf[4096];
529 int i;
530 char *p;
531 for (i=0; i < 0x100; i++)
533 p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
534 strcpy (p, "OK");
535 strcpy (p+3, "BAD/WRONG");
536 check (strlen (p) == 2, 4+i);
541 static void
542 test_strnlen (void)
544 it = "strnlen";
545 check (strnlen ("", 10) == 0, 1); /* Empty. */
546 check (strnlen ("a", 10) == 1, 2); /* Single char. */
547 check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
548 check (strnlen ("foo", (size_t) -1) == 3, 4); /* limits of n. */
549 check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
550 check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
551 check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
552 check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
553 check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
555 char buf[4096];
556 for (int i = 0; i < 0x100; ++i)
558 char *p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
559 strcpy (p, "OK");
560 strcpy (p + 3, "BAD/WRONG");
561 check (strnlen (p, 100) == 2, 10 + i);
565 static void
566 test_strchr (void)
568 it = "strchr";
569 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
570 (void) strcpy (one, "abcd");
571 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
572 check (strchr (one, 'd') == one+3, 3); /* End of string. */
573 check (strchr (one, 'a') == one, 4); /* Beginning. */
574 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
575 (void) strcpy (one, "ababa");
576 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
577 (void) strcpy (one, "");
578 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
579 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
581 char buf[4096];
582 int i;
583 char *p;
584 for (i=0; i < 0x100; i++)
586 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
587 strcpy (p, "OK");
588 strcpy (p+3, "BAD/WRONG");
589 check (strchr (p, '/') == NULL, 9+i);
594 static void
595 test_strchrnul (void)
597 const char *os;
598 it = "strchrnul";
599 cp = strchrnul ((os = "abcd"), 'z');
600 check (*cp == '\0', 1); /* Not found. */
601 check (cp == os + 4, 2);
602 (void) strcpy (one, "abcd");
603 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
604 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
605 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
606 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
607 (void) strcpy (one, "ababa");
608 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
609 (void) strcpy (one, "");
610 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
611 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
613 char buf[4096];
614 int i;
615 char *p;
616 for (i=0; i < 0x100; i++)
618 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
619 strcpy (p, "OK");
620 strcpy (p+3, "BAD/WRONG");
621 cp = strchrnul (p, '/');
622 check (*cp == '\0', 9+2*i);
623 check (cp == p+2, 10+2*i);
628 static void
629 test_rawmemchr (void)
631 it = "rawmemchr";
632 (void) strcpy (one, "abcd");
633 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
634 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
635 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
636 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
637 (void) strcpy (one, "ababa");
638 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
639 (void) strcpy (one, "");
640 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
642 char buf[4096];
643 int i;
644 char *p;
645 for (i=0; i < 0x100; i++)
647 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
648 strcpy (p, "OK");
649 strcpy (p+3, "BAD/WRONG");
650 check (rawmemchr (p, 'R') == p+8, 6+i);
655 static void
656 test_index (void)
658 it = "index";
659 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
660 (void) strcpy (one, "abcd");
661 check (index (one, 'c') == one+2, 2); /* Basic test. */
662 check (index (one, 'd') == one+3, 3); /* End of string. */
663 check (index (one, 'a') == one, 4); /* Beginning. */
664 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
665 (void) strcpy (one, "ababa");
666 check (index (one, 'b') == one+1, 6); /* Finding first. */
667 (void) strcpy (one, "");
668 check (index (one, 'b') == NULL, 7); /* Empty string. */
669 check (index (one, '\0') == one, 8); /* NUL in empty string. */
672 static void
673 test_strrchr (void)
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. */
688 char buf[4096];
689 int i;
690 char *p;
691 for (i=0; i < 0x100; i++)
693 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
694 strcpy (p, "OK");
695 strcpy (p+3, "BAD/WRONG");
696 check (strrchr (p, '/') == NULL, 9+i);
701 static void
702 test_memrchr (void)
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. */
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: */
725 char buf[128 + sizeof (long)];
726 long align, len, i, pos, n = 9;
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... */
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, n++);
738 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
739 n++);
740 buf[align + pos] = '-';
747 static void
748 test_rindex (void)
750 it = "rindex";
751 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
752 (void) strcpy (one, "abcd");
753 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
754 check (rindex (one, 'd') == one+3, 3); /* End of string. */
755 check (rindex (one, 'a') == one, 4); /* Beginning. */
756 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
757 (void) strcpy (one, "ababa");
758 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
759 (void) strcpy (one, "");
760 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
761 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
764 static void
765 test_strpbrk (void)
767 it = "strpbrk";
768 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
769 (void) strcpy(one, "abcd");
770 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
771 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
772 check(strpbrk(one, "a") == one, 4); /* Beginning. */
773 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
774 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
775 (void) strcpy(one, "abcabdea");
776 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
777 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
778 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
779 (void) strcpy(one, "");
780 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
781 (void) strcpy(one, "");
782 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
783 (void) strcpy(one, "");
784 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
785 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
786 (void) strcpy(one, "abcabdea");
787 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
788 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
789 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
790 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
793 static void
794 test_strstr (void)
796 it = "strstr";
797 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
798 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
799 (void) strcpy(one, "abcd");
800 check(strstr(one, "c") == one+2, 3); /* Basic test. */
801 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
802 check(strstr(one, "d") == one+3, 5); /* End of string. */
803 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
804 check(strstr(one, "abc") == one, 7); /* Beginning. */
805 check(strstr(one, "abcd") == one, 8); /* Exact match. */
806 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
807 check(strstr(one, "de") == NULL, 10); /* Past end. */
808 check(strstr(one, "") == one, 11); /* Finding empty. */
809 (void) strcpy(one, "ababa");
810 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
811 (void) strcpy(one, "");
812 check(strstr(one, "b") == NULL, 13); /* Empty string. */
813 check(strstr(one, "") == one, 14); /* Empty in empty string. */
814 (void) strcpy(one, "bcbca");
815 check(strstr(one, "bca") == one+2, 15); /* False start. */
816 (void) strcpy(one, "bbbcabbca");
817 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
820 static void
821 test_strspn (void)
823 it = "strspn";
824 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
825 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
826 check(strspn("abc", "qx") == 0, 3); /* None. */
827 check(strspn("", "ab") == 0, 4); /* Null string. */
828 check(strspn("abc", "") == 0, 5); /* Null search list. */
831 static void
832 test_strcspn (void)
834 it = "strcspn";
835 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
836 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
837 check(strcspn("abc", "abc") == 0, 3); /* None. */
838 check(strcspn("", "ab") == 0, 4); /* Null string. */
839 check(strcspn("abc", "") == 3, 5); /* Null search list. */
842 static void
843 test_strtok (void)
845 it = "strtok";
846 (void) strcpy(one, "first, second, third");
847 equal(strtok(one, ", "), "first", 1); /* Basic test. */
848 equal(one, "first", 2);
849 equal(strtok((char *)NULL, ", "), "second", 3);
850 equal(strtok((char *)NULL, ", "), "third", 4);
851 check(strtok((char *)NULL, ", ") == NULL, 5);
852 (void) strcpy(one, ", first, ");
853 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
854 check(strtok((char *)NULL, ", ") == NULL, 7);
855 (void) strcpy(one, "1a, 1b; 2a, 2b");
856 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
857 equal(strtok((char *)NULL, "; "), "1b", 9);
858 equal(strtok((char *)NULL, ", "), "2a", 10);
859 (void) strcpy(two, "x-y");
860 equal(strtok(two, "-"), "x", 11); /* New string before done. */
861 equal(strtok((char *)NULL, "-"), "y", 12);
862 check(strtok((char *)NULL, "-") == NULL, 13);
863 (void) strcpy(one, "a,b, c,, ,d");
864 equal(strtok(one, ", "), "a", 14); /* Different separators. */
865 equal(strtok((char *)NULL, ", "), "b", 15);
866 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
867 equal(strtok((char *)NULL, " ,"), "d", 17);
868 check(strtok((char *)NULL, ", ") == NULL, 18);
869 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
870 (void) strcpy(one, ", ");
871 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
872 (void) strcpy(one, "");
873 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
874 (void) strcpy(one, "abc");
875 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
876 check(strtok((char *)NULL, ", ") == NULL, 23);
877 (void) strcpy(one, "abc");
878 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
879 check(strtok((char *)NULL, "") == NULL, 25);
880 (void) strcpy(one, "abcdefgh");
881 (void) strcpy(one, "a,b,c");
882 equal(strtok(one, ","), "a", 26); /* Basics again... */
883 equal(strtok((char *)NULL, ","), "b", 27);
884 equal(strtok((char *)NULL, ","), "c", 28);
885 check(strtok((char *)NULL, ",") == NULL, 29);
886 equal(one+6, "gh", 30); /* Stomped past end? */
887 equal(one, "a", 31); /* Stomped old tokens? */
888 equal(one+2, "b", 32);
889 equal(one+4, "c", 33);
892 static void
893 test_strtok_r (void)
895 it = "strtok_r";
896 (void) strcpy(one, "first, second, third");
897 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
898 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
899 equal(one, "first", 2);
900 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
901 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
902 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
903 (void) strcpy(one, ", first, ");
904 cp = NULL;
905 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
906 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
907 (void) strcpy(one, "1a, 1b; 2a, 2b");
908 cp = NULL;
909 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
910 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
911 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
912 (void) strcpy(two, "x-y");
913 cp = NULL;
914 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
915 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
916 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
917 (void) strcpy(one, "a,b, c,, ,d");
918 cp = NULL;
919 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
920 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
921 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
922 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
923 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
924 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
925 (void) strcpy(one, ", ");
926 cp = NULL;
927 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
928 (void) strcpy(one, "");
929 cp = NULL;
930 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
931 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
932 (void) strcpy(one, "abc");
933 cp = NULL;
934 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
935 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
936 (void) strcpy(one, "abc");
937 cp = NULL;
938 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
939 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
940 (void) strcpy(one, "abcdefgh");
941 (void) strcpy(one, "a,b,c");
942 cp = NULL;
943 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
944 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
945 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
946 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
947 equal(one+6, "gh", 31); /* Stomped past end? */
948 equal(one, "a", 32); /* Stomped old tokens? */
949 equal(one+2, "b", 33);
950 equal(one+4, "c", 34);
951 strcpy (one, ":::");
952 cp = NULL;
953 check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
954 check (strtok_r (NULL, ":", &cp) == NULL, 36);
957 static void
958 test_strsep (void)
960 char *ptr;
961 it = "strsep";
962 cp = strcpy(one, "first, second, third");
963 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
964 equal(one, "first", 2);
965 equal(strsep(&cp, ", "), "", 3);
966 equal(strsep(&cp, ", "), "second", 4);
967 equal(strsep(&cp, ", "), "", 5);
968 equal(strsep(&cp, ", "), "third", 6);
969 check(strsep(&cp, ", ") == NULL, 7);
970 cp = strcpy(one, ", first, ");
971 equal(strsep(&cp, ", "), "", 8);
972 equal(strsep(&cp, ", "), "", 9);
973 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
974 equal(strsep(&cp, ", "), "", 11);
975 equal(strsep(&cp, ", "), "", 12);
976 check(strsep(&cp, ", ") == NULL, 13);
977 cp = strcpy(one, "1a, 1b; 2a, 2b");
978 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
979 equal(strsep(&cp, ", "), "", 15);
980 equal(strsep(&cp, "; "), "1b", 16);
981 equal(strsep(&cp, ", "), "", 17);
982 equal(strsep(&cp, ", "), "2a", 18);
983 cp = strcpy(two, "x-y");
984 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
985 equal(strsep(&cp, "-"), "y", 20);
986 check(strsep(&cp, "-") == NULL, 21);
987 cp = strcpy(one, "a,b, c,, ,d ");
988 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
989 equal(strsep(&cp, ", "), "b", 23);
990 equal(strsep(&cp, " ,"), "", 24);
991 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
992 equal(strsep(&cp, " ,"), "", 26);
993 equal(strsep(&cp, " ,"), "", 27);
994 equal(strsep(&cp, " ,"), "", 28);
995 equal(strsep(&cp, " ,"), "d", 29);
996 equal(strsep(&cp, " ,"), "", 30);
997 check(strsep(&cp, ", ") == NULL, 31);
998 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
999 cp = strcpy(one, ", ");
1000 equal(strsep(&cp, ", "), "", 33);
1001 equal(strsep(&cp, ", "), "", 34);
1002 equal(strsep(&cp, ", "), "", 35);
1003 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
1004 cp = strcpy(one, "");
1005 equal(strsep(&cp, ", "), "", 37);
1006 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
1007 cp = strcpy(one, "abc");
1008 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
1009 check(strsep(&cp, ", ") == NULL, 40);
1010 cp = strcpy(one, "abc");
1011 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
1012 check(strsep(&cp, "") == NULL, 42);
1013 (void) strcpy(one, "abcdefgh");
1014 cp = strcpy(one, "a,b,c");
1015 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
1016 equal(strsep(&cp, ","), "b", 44);
1017 equal(strsep(&cp, ","), "c", 45);
1018 check(strsep(&cp, ",") == NULL, 46);
1019 equal(one+6, "gh", 47); /* Stomped past end? */
1020 equal(one, "a", 48); /* Stomped old tokens? */
1021 equal(one+2, "b", 49);
1022 equal(one+4, "c", 50);
1025 char text[] = "This,is,a,test";
1026 char *list = strdupa (text);
1027 equal (strsep (&list, ","), "This", 51);
1028 equal (strsep (&list, ","), "is", 52);
1029 equal (strsep (&list, ","), "a", 53);
1030 equal (strsep (&list, ","), "test", 54);
1031 check (strsep (&list, ",") == NULL, 55);
1034 cp = strcpy(one, "a,b, c,, ,d,");
1035 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1036 equal(strsep(&cp, ","), "b", 57);
1037 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1038 equal(strsep(&cp, ","), "", 59);
1039 equal(strsep(&cp, ","), " ", 60);
1040 equal(strsep(&cp, ","), "d", 61);
1041 equal(strsep(&cp, ","), "", 62);
1042 check(strsep(&cp, ",") == NULL, 63);
1043 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1045 cp = strcpy(one, "a,b, c,, ,d,");
1046 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1047 equal(strsep(&cp, "x,y"), "b", 66);
1048 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1049 equal(strsep(&cp, "xy,"), "", 68);
1050 equal(strsep(&cp, "x,y"), " ", 69);
1051 equal(strsep(&cp, ",xy"), "d", 70);
1052 equal(strsep(&cp, "xy,"), "", 71);
1053 check(strsep(&cp, "x,y") == NULL, 72);
1054 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1056 cp = strcpy(one, "ABC");
1057 one[4] = ':';
1058 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1059 ptr = strsep(&cp, ":");
1060 equal(ptr, "", 75);
1061 check(ptr == one + 3, 76);
1062 check(cp == NULL, 77);
1064 cp = strcpy(one, "ABC");
1065 one[4] = ':';
1066 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1067 ptr = strsep(&cp, ":.");
1068 equal(ptr, "", 79);
1069 check(ptr == one + 3, 80);
1071 cp = strcpy(one, "ABC"); /* No token in string. */
1072 equal(strsep(&cp, ","), "ABC", 81);
1073 check(cp == NULL, 82);
1075 *one = '\0'; /* Empty string. */
1076 cp = one;
1077 ptr = strsep(&cp, ",");
1078 equal(ptr, "", 83);
1079 check(ptr == one, 84);
1080 check(cp == NULL, 85);
1082 *one = '\0'; /* Empty string and no token. */
1083 cp = one;
1084 ptr = strsep(&cp, "");
1085 equal(ptr, "", 86);
1086 check(ptr == one , 87);
1087 check(cp == NULL, 88);
1090 static void
1091 test_memcmp (void)
1093 int cnt = 1;
1094 char one[21];
1095 char two[21];
1097 it = "memcmp";
1098 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1099 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1100 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1101 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1102 check(memcmp("alph", "cold", 4) < 0, cnt++);
1103 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1104 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1105 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1106 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1107 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1108 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1109 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1110 /* Comparisons with shifting 4-byte boundaries. */
1111 for (int i = 0; i < 4; ++i)
1113 char *a = one + i;
1114 char *b = two + i;
1115 memcpy(a, "--------11112222", 16);
1116 memcpy(b, "--------33334444", 16);
1117 check(memcmp(b, a, 16) > 0, cnt++);
1118 check(memcmp(a, b, 16) < 0, cnt++);
1122 static void
1123 test_memchr (void)
1125 it = "memchr";
1126 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1127 (void) strcpy(one, "abcd");
1128 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1129 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1130 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1131 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1132 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1133 (void) strcpy(one, "ababa");
1134 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1135 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1136 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1137 (void) strcpy(one, "a\203b");
1138 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1140 /* now test all possible alignment and length combinations to catch
1141 bugs due to unrolled loops (assuming unrolling is limited to no
1142 more than 128 byte chunks: */
1144 char buf[128 + sizeof (long)];
1145 long align, len, i, pos;
1147 for (align = 0; align < (long) sizeof (long); ++align) {
1148 for (len = 0; len < (long) (sizeof (buf) - align); ++len) {
1149 for (i = 0; i < len; ++i) {
1150 buf[align + i] = 'x'; /* don't depend on memset... */
1152 for (pos = 0; pos < len; ++pos) {
1153 #if 0
1154 printf("align %d, len %d, pos %d\n", align, len, pos);
1155 #endif
1156 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1157 check(memchr(buf + align, 'x', pos) == NULL, 11);
1158 buf[align + pos] = '-';
1165 static void
1166 test_memcpy (void)
1168 int i;
1169 it = "memcpy";
1170 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1171 equal(one, "abc", 2); /* Did the copy go right? */
1173 (void) strcpy(one, "abcdefgh");
1174 (void) memcpy(one+1, "xyz", 2);
1175 equal(one, "axydefgh", 3); /* Basic test. */
1177 (void) strcpy(one, "abc");
1178 (void) memcpy(one, "xyz", 0);
1179 equal(one, "abc", 4); /* Zero-length copy. */
1181 (void) strcpy(one, "hi there");
1182 (void) strcpy(two, "foo");
1183 (void) memcpy(two, one, 9);
1184 equal(two, "hi there", 5); /* Just paranoia. */
1185 equal(one, "hi there", 6); /* Stomped on source? */
1187 for (i = 0; i < 16; i++)
1189 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1190 strcpy (one, x);
1191 check (memcpy (one + i, "hi there", 9) == one + i,
1192 7 + (i * 6)); /* Unaligned destination. */
1193 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1194 equal (one + i, "hi there", 9 + (i * 6));
1195 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1196 check (memcpy (two, one + i, 9) == two,
1197 11 + (i * 6)); /* Unaligned source. */
1198 equal (two, "hi there", 12 + (i * 6));
1202 static void
1203 test_mempcpy (void)
1205 int i;
1206 it = "mempcpy";
1207 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1208 equal(one, "abc", 2); /* Did the copy go right? */
1210 (void) strcpy(one, "abcdefgh");
1211 (void) mempcpy(one+1, "xyz", 2);
1212 equal(one, "axydefgh", 3); /* Basic test. */
1214 (void) strcpy(one, "abc");
1215 (void) mempcpy(one, "xyz", 0);
1216 equal(one, "abc", 4); /* Zero-length copy. */
1218 (void) strcpy(one, "hi there");
1219 (void) strcpy(two, "foo");
1220 (void) mempcpy(two, one, 9);
1221 equal(two, "hi there", 5); /* Just paranoia. */
1222 equal(one, "hi there", 6); /* Stomped on source? */
1224 for (i = 0; i < 16; i++)
1226 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1227 strcpy (one, x);
1228 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1229 7 + (i * 6)); /* Unaligned destination. */
1230 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1231 equal (one + i, "hi there", 9 + (i * 6));
1232 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1233 check (mempcpy (two, one + i, 9) == two + 9,
1234 11 + (i * 6)); /* Unaligned source. */
1235 equal (two, "hi there", 12 + (i * 6));
1239 static void
1240 test_memmove (void)
1242 it = "memmove";
1243 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1244 equal(one, "abc", 2); /* Did the copy go right? */
1246 (void) strcpy(one, "abcdefgh");
1247 (void) memmove(one+1, "xyz", 2);
1248 equal(one, "axydefgh", 3); /* Basic test. */
1250 (void) strcpy(one, "abc");
1251 (void) memmove(one, "xyz", 0);
1252 equal(one, "abc", 4); /* Zero-length copy. */
1254 (void) strcpy(one, "hi there");
1255 (void) strcpy(two, "foo");
1256 (void) memmove(two, one, 9);
1257 equal(two, "hi there", 5); /* Just paranoia. */
1258 equal(one, "hi there", 6); /* Stomped on source? */
1260 (void) strcpy(one, "abcdefgh");
1261 (void) memmove(one+1, one, 9);
1262 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1264 (void) strcpy(one, "abcdefgh");
1265 (void) memmove(one+1, one+2, 7);
1266 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1268 (void) strcpy(one, "abcdefgh");
1269 (void) memmove(one, one, 9);
1270 equal(one, "abcdefgh", 9); /* 100% overlap. */
1273 static void
1274 test_memccpy (void)
1276 /* First test like memcpy, then the search part The SVID, the only
1277 place where memccpy is mentioned, says overlap might fail, so we
1278 don't try it. Besides, it's hard to see the rationale for a
1279 non-left-to-right memccpy. */
1280 it = "memccpy";
1281 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1282 equal(one, "abc", 2); /* Did the copy go right? */
1284 (void) strcpy(one, "abcdefgh");
1285 (void) memccpy(one+1, "xyz", 'q', 2);
1286 equal(one, "axydefgh", 3); /* Basic test. */
1288 (void) strcpy(one, "abc");
1289 (void) memccpy(one, "xyz", 'q', 0);
1290 equal(one, "abc", 4); /* Zero-length copy. */
1292 (void) strcpy(one, "hi there");
1293 (void) strcpy(two, "foo");
1294 (void) memccpy(two, one, 'q', 9);
1295 equal(two, "hi there", 5); /* Just paranoia. */
1296 equal(one, "hi there", 6); /* Stomped on source? */
1298 (void) strcpy(one, "abcdefgh");
1299 (void) strcpy(two, "horsefeathers");
1300 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1301 equal(one, "abcdefgh", 8); /* Source intact? */
1302 equal(two, "abcdefeathers", 9); /* Copy correct? */
1304 (void) strcpy(one, "abcd");
1305 (void) strcpy(two, "bumblebee");
1306 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1307 equal(two, "aumblebee", 11);
1308 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1309 equal(two, "abcdlebee", 13);
1310 (void) strcpy(one, "xyz");
1311 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1312 equal(two, "xbcdlebee", 15);
1315 static void
1316 test_memset (void)
1318 int i;
1320 it = "memset";
1321 (void) strcpy(one, "abcdefgh");
1322 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1323 equal(one, "axxxefgh", 2); /* Basic test. */
1325 (void) memset(one+2, 'y', 0);
1326 equal(one, "axxxefgh", 3); /* Zero-length set. */
1328 (void) memset(one+5, 0, 1);
1329 equal(one, "axxxe", 4); /* Zero fill. */
1330 equal(one+6, "gh", 5); /* And the leftover. */
1332 (void) memset(one+2, 010045, 1);
1333 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1335 /* Non-8bit fill character. */
1336 memset (one, 0x101, sizeof (one));
1337 for (i = 0; i < (int) sizeof (one); ++i)
1338 check (one[i] == '\01', 7);
1340 /* Test for more complex versions of memset, for all alignments and
1341 lengths up to 256. This test takes a little while, perhaps it should
1342 be made weaker? */
1344 char data[512];
1345 int j;
1346 int k;
1347 int c;
1349 for (i = 0; i < 512; i++)
1350 data[i] = 'x';
1351 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1352 memset(,'y',) */
1353 for (j = 0; j < 256; j++)
1354 for (i = 0; i < 256; i++)
1356 memset (data + i, c, j);
1357 for (k = 0; k < i; k++)
1358 if (data[k] != 'x')
1359 goto fail;
1360 for (k = i; k < i+j; k++)
1362 if (data[k] != c)
1363 goto fail;
1364 data[k] = 'x';
1366 for (k = i+j; k < 512; k++)
1367 if (data[k] != 'x')
1368 goto fail;
1369 continue;
1371 fail:
1372 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1377 static void
1378 test_bcopy (void)
1380 /* Much like memcpy. Berklix manual is silent about overlap, so
1381 don't test it. */
1382 it = "bcopy";
1383 (void) bcopy("abc", one, 4);
1384 equal(one, "abc", 1); /* Simple copy. */
1386 (void) strcpy(one, "abcdefgh");
1387 (void) bcopy("xyz", one+1, 2);
1388 equal(one, "axydefgh", 2); /* Basic test. */
1390 (void) strcpy(one, "abc");
1391 (void) bcopy("xyz", one, 0);
1392 equal(one, "abc", 3); /* Zero-length copy. */
1394 (void) strcpy(one, "hi there");
1395 (void) strcpy(two, "foo");
1396 (void) bcopy(one, two, 9);
1397 equal(two, "hi there", 4); /* Just paranoia. */
1398 equal(one, "hi there", 5); /* Stomped on source? */
1401 static void
1402 test_bzero (void)
1404 it = "bzero";
1405 (void) strcpy(one, "abcdef");
1406 bzero(one+2, 2);
1407 equal(one, "ab", 1); /* Basic test. */
1408 equal(one+3, "", 2);
1409 equal(one+4, "ef", 3);
1411 (void) strcpy(one, "abcdef");
1412 bzero(one+2, 0);
1413 equal(one, "abcdef", 4); /* Zero-length copy. */
1416 static void
1417 test_strndup (void)
1419 char *p, *q;
1420 it = "strndup";
1421 p = strndup("abcdef", 12);
1422 check(p != NULL, 1);
1423 if (p != NULL)
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);
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);
1440 static void
1441 test_bcmp (void)
1443 it = "bcmp";
1444 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1445 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1446 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1447 check(bcmp("abce", "abcd", 4) != 0, 4);
1448 check(bcmp("alph", "beta", 4) != 0, 5);
1449 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1450 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1453 static void
1454 test_memcmpeq (void)
1456 it = "__memcmpeq";
1457 check (__memcmpeq ("a", "a", 1) == 0, 1); /* Identity. */
1458 check (__memcmpeq ("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1459 check (__memcmpeq ("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1460 check (__memcmpeq ("abce", "abcd", 4) != 0, 4);
1461 check (__memcmpeq ("alph", "beta", 4) != 0, 5);
1462 check (__memcmpeq ("abce", "abcd", 3) == 0, 6); /* Count limited. */
1463 check (__memcmpeq ("abc", "def", 0) == 0, 8); /* Zero count. */
1466 static void
1467 test_strerror (void)
1469 it = "strerror";
1470 check(strerror(EDOM) != 0, 1);
1471 check(strerror(ERANGE) != 0, 2);
1472 check(strerror(ENOENT) != 0, 3);
1475 static void
1476 test_strcasecmp (void)
1478 it = "strcasecmp";
1479 /* Note that the locale is "C". */
1480 check(strcasecmp("a", "a") == 0, 1);
1481 check(strcasecmp("a", "A") == 0, 2);
1482 check(strcasecmp("A", "a") == 0, 3);
1483 check(strcasecmp("a", "b") < 0, 4);
1484 check(strcasecmp("c", "b") > 0, 5);
1485 check(strcasecmp("abc", "AbC") == 0, 6);
1486 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1487 check(strcasecmp("", "0123456789") < 0, 8);
1488 check(strcasecmp("AbC", "") > 0, 9);
1489 check(strcasecmp("AbC", "A") > 0, 10);
1490 check(strcasecmp("AbC", "Ab") > 0, 11);
1491 check(strcasecmp("AbC", "ab") > 0, 12);
1494 static void
1495 test_strncasecmp (void)
1497 it = "strncasecmp";
1498 /* Note that the locale is "C". */
1499 check(strncasecmp("a", "a", 5) == 0, 1);
1500 check(strncasecmp("a", "A", 5) == 0, 2);
1501 check(strncasecmp("A", "a", 5) == 0, 3);
1502 check(strncasecmp("a", "b", 5) < 0, 4);
1503 check(strncasecmp("c", "b", 5) > 0, 5);
1504 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1505 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1506 check(strncasecmp("", "0123456789", 10) < 0, 8);
1507 check(strncasecmp("AbC", "", 5) > 0, 9);
1508 check(strncasecmp("AbC", "A", 5) > 0, 10);
1509 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1510 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1511 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1512 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1513 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1514 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1515 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1516 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1517 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1518 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1522 main (void)
1524 int status;
1526 /* Test strcmp first because we use it to test other things. */
1527 test_strcmp ();
1529 /* Test strcpy next because we need it to set up other tests. */
1530 test_strcpy ();
1532 /* A closely related function is stpcpy. */
1533 test_stpcpy ();
1535 /* stpncpy. */
1536 test_stpncpy ();
1538 /* strcat. */
1539 test_strcat ();
1541 /* strncat. */
1542 test_strncat ();
1544 /* strncmp. */
1545 test_strncmp ();
1547 /* strncpy. */
1548 test_strncpy ();
1550 /* strlen. */
1551 test_strlen ();
1553 /* strnlen. */
1554 test_strnlen ();
1556 /* strchr. */
1557 test_strchr ();
1559 /* strchrnul. */
1560 test_strchrnul ();
1562 /* rawmemchr. */
1563 test_rawmemchr ();
1565 /* index - just like strchr. */
1566 test_index ();
1568 /* strrchr. */
1569 test_strrchr ();
1571 /* memrchr. */
1572 test_memrchr ();
1574 /* rindex - just like strrchr. */
1575 test_rindex ();
1577 /* strpbrk - somewhat like strchr. */
1578 test_strpbrk ();
1580 /* strstr - somewhat like strchr. */
1581 test_strstr ();
1583 /* strspn. */
1584 test_strspn ();
1586 /* strcspn. */
1587 test_strcspn ();
1589 /* strtok - the hard one. */
1590 test_strtok ();
1592 /* strtok_r. */
1593 test_strtok_r ();
1595 /* strsep. */
1596 test_strsep ();
1598 /* memcmp. */
1599 test_memcmp ();
1601 /* memchr. */
1602 test_memchr ();
1604 /* memcpy - need not work for overlap. */
1605 test_memcpy ();
1607 /* memmove - must work on overlap. */
1608 test_memmove ();
1610 /* mempcpy */
1611 test_mempcpy ();
1613 /* memccpy. */
1614 test_memccpy ();
1616 /* memset. */
1617 test_memset ();
1619 /* bcopy. */
1620 test_bcopy ();
1622 /* bzero. */
1623 test_bzero ();
1625 /* bcmp - somewhat like memcmp. */
1626 test_bcmp ();
1628 /* __memcmpeq - somewhat like memcmp. */
1629 test_memcmpeq ();
1631 /* strndup. */
1632 test_strndup ();
1634 /* strerror - VERY system-dependent. */
1635 test_strerror ();
1637 /* strcasecmp. Without locale dependencies. */
1638 test_strcasecmp ();
1640 /* strncasecmp. Without locale dependencies. */
1641 test_strncasecmp ();
1643 if (errors == 0)
1645 status = EXIT_SUCCESS;
1646 puts("No errors.");
1648 else
1650 status = EXIT_FAILURE;
1651 printf("%zd errors.\n", errors);
1654 return status;