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