Update copyright notices with scripts/update-copyrights
[glibc.git] / string / tester.c
blob62905a7d2466ef5e28fa3ccf16c1fec046071e51
1 /* Tester for string functions.
2 Copyright (C) 1995-2014 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 <http://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>
37 #define STREQ(a, b) (strcmp((a), (b)) == 0)
39 const char *it = "<UNSET>"; /* Routine name for message routines. */
40 size_t errors = 0;
42 /* Complain if condition is not true. */
43 static void
44 check (int thing, int number)
46 if (!thing)
48 printf ("%s flunked test %d\n", it, number);
49 ++errors;
53 /* Complain if first two args don't strcmp as equal. */
54 static void
55 equal (const char *a, const char *b, int number)
57 check (a != NULL && b != NULL && STREQ (a, b), number);
60 char one[50];
61 char two[50];
62 char *cp;
64 static void
65 test_strcmp (void)
67 it = "strcmp";
68 check (strcmp ("", "") == 0, 1); /* Trivial case. */
69 check (strcmp ("a", "a") == 0, 2); /* Identity. */
70 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
71 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
72 check (strcmp ("abcd", "abc") > 0, 5);
73 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
74 check (strcmp ("abce", "abcd") > 0, 7);
75 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
76 check (strcmp ("a\203", "a\003") > 0, 9);
79 char buf1[0x40], buf2[0x40];
80 int i, j;
81 for (i=0; i < 0x10; i++)
82 for (j = 0; j < 0x10; j++)
84 int k;
85 for (k = 0; k < 0x3f; k++)
87 buf1[k] = '0' ^ (k & 4);
88 buf2[k] = '4' ^ (k & 4);
90 buf1[i] = buf1[0x3f] = 0;
91 buf2[j] = buf2[0x3f] = 0;
92 for (k = 0; k < 0xf; k++)
94 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
95 check (strcmp (buf1+i,buf2+j) == 0, cnum);
96 buf1[i+k] = 'A' + i + k;
97 buf1[i+k+1] = 0;
98 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
99 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
100 buf2[j+k] = 'B' + i + k;
101 buf2[j+k+1] = 0;
102 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
103 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
104 buf2[j+k] = 'A' + i + k;
105 buf1[i] = 'A' + i + 0x80;
106 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
107 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
108 buf1[i] = 'A' + i;
114 #define SIMPLE_COPY(fn, n, str, ntest) \
115 do { \
116 int __n; \
117 char *cp; \
118 for (__n = 0; __n < (int) sizeof (one); ++__n) \
119 one[__n] = 'Z'; \
120 fn (one, str); \
121 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
122 check (*cp == '0' + (n % 10), ntest); \
123 check (*cp == '\0', ntest); \
124 } while (0)
126 static void
127 test_strcpy (void)
129 int i;
130 it = "strcpy";
131 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
132 equal (one, "abcd", 2); /* Basic test. */
134 (void) strcpy (one, "x");
135 equal (one, "x", 3); /* Writeover. */
136 equal (one+2, "cd", 4); /* Wrote too much? */
138 (void) strcpy (two, "hi there");
139 (void) strcpy (one, two);
140 equal (one, "hi there", 5); /* Basic test encore. */
141 equal (two, "hi there", 6); /* Stomped on source? */
143 (void) strcpy (one, "");
144 equal (one, "", 7); /* Boundary condition. */
146 for (i = 0; i < 16; i++)
148 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
149 equal (one + i, "hi there", 8 + (i * 2));
150 (void) strcpy (two, one + i); /* Unaligned source. */
151 equal (two, "hi there", 9 + (i * 2));
154 SIMPLE_COPY(strcpy, 0, "", 41);
155 SIMPLE_COPY(strcpy, 1, "1", 42);
156 SIMPLE_COPY(strcpy, 2, "22", 43);
157 SIMPLE_COPY(strcpy, 3, "333", 44);
158 SIMPLE_COPY(strcpy, 4, "4444", 45);
159 SIMPLE_COPY(strcpy, 5, "55555", 46);
160 SIMPLE_COPY(strcpy, 6, "666666", 47);
161 SIMPLE_COPY(strcpy, 7, "7777777", 48);
162 SIMPLE_COPY(strcpy, 8, "88888888", 49);
163 SIMPLE_COPY(strcpy, 9, "999999999", 50);
164 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
165 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
166 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
167 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
168 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
169 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
170 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
172 /* Simple test using implicitly coerced `void *' arguments. */
173 const void *src = "frobozz";
174 void *dst = one;
175 check (strcpy (dst, src) == dst, 1);
176 equal (dst, "frobozz", 2);
179 static void
180 test_stpcpy (void)
182 it = "stpcpy";
183 check ((stpcpy (one, "a") - one) == 1, 1);
184 equal (one, "a", 2);
186 check ((stpcpy (one, "ab") - one) == 2, 3);
187 equal (one, "ab", 4);
189 check ((stpcpy (one, "abc") - one) == 3, 5);
190 equal (one, "abc", 6);
192 check ((stpcpy (one, "abcd") - one) == 4, 7);
193 equal (one, "abcd", 8);
195 check ((stpcpy (one, "abcde") - one) == 5, 9);
196 equal (one, "abcde", 10);
198 check ((stpcpy (one, "abcdef") - one) == 6, 11);
199 equal (one, "abcdef", 12);
201 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
202 equal (one, "abcdefg", 14);
204 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
205 equal (one, "abcdefgh", 16);
207 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
208 equal (one, "abcdefghi", 18);
210 check ((stpcpy (one, "x") - one) == 1, 19);
211 equal (one, "x", 20); /* Writeover. */
212 equal (one+2, "cdefghi", 21); /* Wrote too much? */
214 check ((stpcpy (one, "xx") - one) == 2, 22);
215 equal (one, "xx", 23); /* Writeover. */
216 equal (one+3, "defghi", 24); /* Wrote too much? */
218 check ((stpcpy (one, "xxx") - one) == 3, 25);
219 equal (one, "xxx", 26); /* Writeover. */
220 equal (one+4, "efghi", 27); /* Wrote too much? */
222 check ((stpcpy (one, "xxxx") - one) == 4, 28);
223 equal (one, "xxxx", 29); /* Writeover. */
224 equal (one+5, "fghi", 30); /* Wrote too much? */
226 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
227 equal (one, "xxxxx", 32); /* Writeover. */
228 equal (one+6, "ghi", 33); /* Wrote too much? */
230 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
231 equal (one, "xxxxxx", 35); /* Writeover. */
232 equal (one+7, "hi", 36); /* Wrote too much? */
234 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
235 equal (one, "xxxxxxx", 38); /* Writeover. */
236 equal (one+8, "i", 39); /* Wrote too much? */
238 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
239 equal (one, "abc", 41);
240 equal (one + 4, "xxx", 42);
242 SIMPLE_COPY(stpcpy, 0, "", 43);
243 SIMPLE_COPY(stpcpy, 1, "1", 44);
244 SIMPLE_COPY(stpcpy, 2, "22", 45);
245 SIMPLE_COPY(stpcpy, 3, "333", 46);
246 SIMPLE_COPY(stpcpy, 4, "4444", 47);
247 SIMPLE_COPY(stpcpy, 5, "55555", 48);
248 SIMPLE_COPY(stpcpy, 6, "666666", 49);
249 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
250 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
251 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
252 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
253 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
254 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
255 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
256 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
257 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
258 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
261 static void
262 test_stpncpy (void)
264 it = "stpncpy";
265 memset (one, 'x', sizeof (one));
266 check (stpncpy (one, "abc", 2) == one + 2, 1);
267 check (stpncpy (one, "abc", 3) == one + 3, 2);
268 check (stpncpy (one, "abc", 4) == one + 3, 3);
269 check (one[3] == '\0' && one[4] == 'x', 4);
270 check (stpncpy (one, "abcd", 5) == one + 4, 5);
271 check (one[4] == '\0' && one[5] == 'x', 6);
272 check (stpncpy (one, "abcd", 6) == one + 4, 7);
273 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
276 static void
277 test_strcat (void)
279 it = "strcat";
280 (void) strcpy (one, "ijk");
281 check (strcat (one, "lmn") == one, 1); /* Returned value. */
282 equal (one, "ijklmn", 2); /* Basic test. */
284 (void) strcpy (one, "x");
285 (void) strcat (one, "yz");
286 equal (one, "xyz", 3); /* Writeover. */
287 equal (one+4, "mn", 4); /* Wrote too much? */
289 (void) strcpy (one, "gh");
290 (void) strcpy (two, "ef");
291 (void) strcat (one, two);
292 equal (one, "ghef", 5); /* Basic test encore. */
293 equal (two, "ef", 6); /* Stomped on source? */
295 (void) strcpy (one, "");
296 (void) strcat (one, "");
297 equal (one, "", 7); /* Boundary conditions. */
298 (void) strcpy (one, "ab");
299 (void) strcat (one, "");
300 equal (one, "ab", 8);
301 (void) strcpy (one, "");
302 (void) strcat (one, "cd");
303 equal (one, "cd", 9);
305 int ntest = 10;
306 char buf1[80] __attribute__ ((aligned (16)));
307 char buf2[32] __attribute__ ((aligned (16)));
308 for (size_t n1 = 0; n1 < 16; ++n1)
309 for (size_t n2 = 0; n2 < 16; ++n2)
310 for (size_t n3 = 0; n3 < 32; ++n3)
312 size_t olderrors = errors;
314 memset (buf1, 'b', sizeof (buf1));
316 memset (buf1 + n2, 'a', n3);
317 buf1[n2 + n3] = '\0';
318 strcpy (buf2 + n1, "123");
320 check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
321 if (errors == olderrors)
322 for (size_t i = 0; i < sizeof (buf1); ++i)
324 if (i < n2)
325 check (buf1[i] == 'b', ntest);
326 else if (i < n2 + n3)
327 check (buf1[i] == 'a', ntest);
328 else if (i < n2 + n3 + 3)
329 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
330 else if (i == n2 + n3 + 3)
331 check (buf1[i] == '\0', ntest);
332 else
333 check (buf1[i] == 'b', ntest);
335 if (errors != olderrors)
337 printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
338 n1, n2, n3, buf1[0]);
339 for (size_t j = 1; j < sizeof (buf1); ++j)
340 printf (",%02hhx", buf1[j]);
341 putchar_unlocked ('\n');
342 break;
348 static void
349 test_strncat (void)
351 /* First test it as strcat, with big counts, then test the count
352 mechanism. */
353 it = "strncat";
354 (void) strcpy (one, "ijk");
355 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
356 equal (one, "ijklmn", 2); /* Basic test. */
358 (void) strcpy (one, "x");
359 (void) strncat (one, "yz", 99);
360 equal (one, "xyz", 3); /* Writeover. */
361 equal (one+4, "mn", 4); /* Wrote too much? */
363 (void) strcpy (one, "gh");
364 (void) strcpy (two, "ef");
365 (void) strncat (one, two, 99);
366 equal (one, "ghef", 5); /* Basic test encore. */
367 equal (two, "ef", 6); /* Stomped on source? */
369 (void) strcpy (one, "");
370 (void) strncat (one, "", 99);
371 equal (one, "", 7); /* Boundary conditions. */
372 (void) strcpy (one, "ab");
373 (void) strncat (one, "", 99);
374 equal (one, "ab", 8);
375 (void) strcpy (one, "");
376 (void) strncat (one, "cd", 99);
377 equal (one, "cd", 9);
379 (void) strcpy (one, "ab");
380 (void) strncat (one, "cdef", 2);
381 equal (one, "abcd", 10); /* Count-limited. */
383 (void) strncat (one, "gh", 0);
384 equal (one, "abcd", 11); /* Zero count. */
386 (void) strncat (one, "gh", 2);
387 equal (one, "abcdgh", 12); /* Count and length equal. */
389 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
390 equal (one, "abcdghij", 13);
392 int ntest = 14;
393 char buf1[80] __attribute__ ((aligned (16)));
394 char buf2[32] __attribute__ ((aligned (16)));
395 for (size_t n1 = 0; n1 < 16; ++n1)
396 for (size_t n2 = 0; n2 < 16; ++n2)
397 for (size_t n3 = 0; n3 < 32; ++n3)
398 for (size_t n4 = 0; n4 < 16; ++n4)
400 size_t olderrors = errors;
402 memset (buf1, 'b', sizeof (buf1));
404 memset (buf1 + n2, 'a', n3);
405 buf1[n2 + n3] = '\0';
406 strcpy (buf2 + n1, "123");
408 check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
409 == buf1 + n2, ntest);
410 if (errors == olderrors)
411 for (size_t i = 0; i < sizeof (buf1); ++i)
413 if (i < n2)
414 check (buf1[i] == 'b', ntest);
415 else if (i < n2 + n3)
416 check (buf1[i] == 'a', ntest);
417 else if (i < n2 + n3 + 3)
418 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
419 else if (i == n2 + n3 + 3)
420 check (buf1[i] == '\0', ntest);
421 else
422 check (buf1[i] == 'b', ntest);
424 if (errors != olderrors)
426 printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
427 n1, n2, n3, n4, buf1[0]);
428 for (size_t j = 1; j < sizeof (buf1); ++j)
429 printf (",%02hhx", buf1[j]);
430 putchar_unlocked ('\n');
431 break;
437 static void
438 test_strncmp (void)
440 /* First test as strcmp with big counts, then test count code. */
441 it = "strncmp";
442 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
443 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
444 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
445 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
446 check (strncmp ("abcd", "abc", 99) > 0, 5);
447 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
448 check (strncmp ("abce", "abcd", 99) > 0, 7);
449 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
450 check (strncmp ("a\203", "a\003", 2) > 0, 9);
451 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
452 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
453 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
454 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
455 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
456 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
459 static void
460 test_strncpy (void)
462 /* Testing is a bit different because of odd semantics. */
463 it = "strncpy";
464 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
465 equal (one, "abc", 2); /* Did the copy go right? */
467 (void) strcpy (one, "abcdefgh");
468 (void) strncpy (one, "xyz", 2);
469 equal (one, "xycdefgh", 3); /* Copy cut by count. */
471 (void) strcpy (one, "abcdefgh");
472 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
473 equal (one, "xyzdefgh", 4);
475 (void) strcpy (one, "abcdefgh");
476 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
477 equal (one, "xyz", 5);
478 equal (one+4, "efgh", 6); /* Wrote too much? */
480 (void) strcpy (one, "abcdefgh");
481 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
482 equal (one, "xyz", 7);
483 equal (one+4, "", 8);
484 equal (one+5, "fgh", 9);
486 (void) strcpy (one, "abc");
487 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
488 equal (one, "abc", 10);
490 (void) strncpy (one, "", 2); /* Zero-length source. */
491 equal (one, "", 11);
492 equal (one+1, "", 12);
493 equal (one+2, "c", 13);
495 (void) strcpy (one, "hi there");
496 (void) strncpy (two, one, 9);
497 equal (two, "hi there", 14); /* Just paranoia. */
498 equal (one, "hi there", 15); /* Stomped on source? */
501 static void
502 test_strlen (void)
504 it = "strlen";
505 check (strlen ("") == 0, 1); /* Empty. */
506 check (strlen ("a") == 1, 2); /* Single char. */
507 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
509 char buf[4096];
510 int i;
511 char *p;
512 for (i=0; i < 0x100; i++)
514 p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
515 strcpy (p, "OK");
516 strcpy (p+3, "BAD/WRONG");
517 check (strlen (p) == 2, 4+i);
522 static void
523 test_strnlen (void)
525 it = "strnlen";
526 check (strnlen ("", 10) == 0, 1); /* Empty. */
527 check (strnlen ("a", 10) == 1, 2); /* Single char. */
528 check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
529 check (strnlen ("foo", (size_t) -1) == 3, 4); /* limits of n. */
530 check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
531 check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
532 check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
533 check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
534 check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
536 char buf[4096];
537 for (int i = 0; i < 0x100; ++i)
539 char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
540 strcpy (p, "OK");
541 strcpy (p + 3, "BAD/WRONG");
542 check (strnlen (p, 100) == 2, 10 + i);
546 static void
547 test_strchr (void)
549 it = "strchr";
550 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
551 (void) strcpy (one, "abcd");
552 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
553 check (strchr (one, 'd') == one+3, 3); /* End of string. */
554 check (strchr (one, 'a') == one, 4); /* Beginning. */
555 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
556 (void) strcpy (one, "ababa");
557 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
558 (void) strcpy (one, "");
559 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
560 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
562 char buf[4096];
563 int i;
564 char *p;
565 for (i=0; i < 0x100; i++)
567 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
568 strcpy (p, "OK");
569 strcpy (p+3, "BAD/WRONG");
570 check (strchr (p, '/') == NULL, 9+i);
575 static void
576 test_strchrnul (void)
578 const char *os;
579 it = "strchrnul";
580 cp = strchrnul ((os = "abcd"), 'z');
581 check (*cp == '\0', 1); /* Not found. */
582 check (cp == os + 4, 2);
583 (void) strcpy (one, "abcd");
584 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
585 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
586 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
587 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
588 (void) strcpy (one, "ababa");
589 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
590 (void) strcpy (one, "");
591 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
592 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
594 char buf[4096];
595 int i;
596 char *p;
597 for (i=0; i < 0x100; i++)
599 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
600 strcpy (p, "OK");
601 strcpy (p+3, "BAD/WRONG");
602 cp = strchrnul (p, '/');
603 check (*cp == '\0', 9+2*i);
604 check (cp == p+2, 10+2*i);
609 static void
610 test_rawmemchr (void)
612 it = "rawmemchr";
613 (void) strcpy (one, "abcd");
614 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
615 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
616 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
617 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
618 (void) strcpy (one, "ababa");
619 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
620 (void) strcpy (one, "");
621 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
623 char buf[4096];
624 int i;
625 char *p;
626 for (i=0; i < 0x100; i++)
628 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
629 strcpy (p, "OK");
630 strcpy (p+3, "BAD/WRONG");
631 check (rawmemchr (p, 'R') == p+8, 6+i);
636 static void
637 test_index (void)
639 it = "index";
640 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
641 (void) strcpy (one, "abcd");
642 check (index (one, 'c') == one+2, 2); /* Basic test. */
643 check (index (one, 'd') == one+3, 3); /* End of string. */
644 check (index (one, 'a') == one, 4); /* Beginning. */
645 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
646 (void) strcpy (one, "ababa");
647 check (index (one, 'b') == one+1, 6); /* Finding first. */
648 (void) strcpy (one, "");
649 check (index (one, 'b') == NULL, 7); /* Empty string. */
650 check (index (one, '\0') == one, 8); /* NUL in empty string. */
653 static void
654 test_strrchr (void)
656 it = "strrchr";
657 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
658 (void) strcpy (one, "abcd");
659 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
660 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
661 check (strrchr (one, 'a') == one, 4); /* Beginning. */
662 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
663 (void) strcpy (one, "ababa");
664 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
665 (void) strcpy (one, "");
666 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
667 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
669 char buf[4096];
670 int i;
671 char *p;
672 for (i=0; i < 0x100; i++)
674 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
675 strcpy (p, "OK");
676 strcpy (p+3, "BAD/WRONG");
677 check (strrchr (p, '/') == NULL, 9+i);
682 static void
683 test_memrchr (void)
685 size_t l;
686 it = "memrchr";
687 check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
688 (void) strcpy (one, "abcd");
689 l = strlen (one) + 1;
690 check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
691 check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
692 check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
693 check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
694 (void) strcpy (one, "ababa");
695 l = strlen (one) + 1;
696 check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
697 (void) strcpy (one, "");
698 l = strlen (one) + 1;
699 check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
700 check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
702 /* now test all possible alignment and length combinations to catch
703 bugs due to unrolled loops (assuming unrolling is limited to no
704 more than 128 byte chunks: */
706 char buf[128 + sizeof(long)];
707 long align, len, i, pos, n = 9;
709 for (align = 0; align < (long) sizeof(long); ++align) {
710 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
711 for (i = 0; i < len; ++i)
712 buf[align + i] = 'x'; /* don't depend on memset... */
714 for (pos = len - 1; pos >= 0; --pos) {
715 #if 0
716 printf("align %d, len %d, pos %d\n", align, len, pos);
717 #endif
718 check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
719 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
720 n++);
721 buf[align + pos] = '-';
728 static void
729 test_rindex (void)
731 it = "rindex";
732 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
733 (void) strcpy (one, "abcd");
734 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
735 check (rindex (one, 'd') == one+3, 3); /* End of string. */
736 check (rindex (one, 'a') == one, 4); /* Beginning. */
737 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
738 (void) strcpy (one, "ababa");
739 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
740 (void) strcpy (one, "");
741 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
742 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
745 static void
746 test_strpbrk (void)
748 it = "strpbrk";
749 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
750 (void) strcpy(one, "abcd");
751 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
752 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
753 check(strpbrk(one, "a") == one, 4); /* Beginning. */
754 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
755 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
756 (void) strcpy(one, "abcabdea");
757 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
758 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
759 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
760 (void) strcpy(one, "");
761 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
762 (void) strcpy(one, "");
763 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
764 (void) strcpy(one, "");
765 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
766 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
767 (void) strcpy(one, "abcabdea");
768 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
769 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
770 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
771 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
774 static void
775 test_strstr (void)
777 it = "strstr";
778 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
779 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
780 (void) strcpy(one, "abcd");
781 check(strstr(one, "c") == one+2, 3); /* Basic test. */
782 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
783 check(strstr(one, "d") == one+3, 5); /* End of string. */
784 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
785 check(strstr(one, "abc") == one, 7); /* Beginning. */
786 check(strstr(one, "abcd") == one, 8); /* Exact match. */
787 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
788 check(strstr(one, "de") == NULL, 10); /* Past end. */
789 check(strstr(one, "") == one, 11); /* Finding empty. */
790 (void) strcpy(one, "ababa");
791 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
792 (void) strcpy(one, "");
793 check(strstr(one, "b") == NULL, 13); /* Empty string. */
794 check(strstr(one, "") == one, 14); /* Empty in empty string. */
795 (void) strcpy(one, "bcbca");
796 check(strstr(one, "bca") == one+2, 15); /* False start. */
797 (void) strcpy(one, "bbbcabbca");
798 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
801 static void
802 test_strspn (void)
804 it = "strspn";
805 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
806 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
807 check(strspn("abc", "qx") == 0, 3); /* None. */
808 check(strspn("", "ab") == 0, 4); /* Null string. */
809 check(strspn("abc", "") == 0, 5); /* Null search list. */
812 static void
813 test_strcspn (void)
815 it = "strcspn";
816 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
817 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
818 check(strcspn("abc", "abc") == 0, 3); /* None. */
819 check(strcspn("", "ab") == 0, 4); /* Null string. */
820 check(strcspn("abc", "") == 3, 5); /* Null search list. */
823 static void
824 test_strtok (void)
826 it = "strtok";
827 (void) strcpy(one, "first, second, third");
828 equal(strtok(one, ", "), "first", 1); /* Basic test. */
829 equal(one, "first", 2);
830 equal(strtok((char *)NULL, ", "), "second", 3);
831 equal(strtok((char *)NULL, ", "), "third", 4);
832 check(strtok((char *)NULL, ", ") == NULL, 5);
833 (void) strcpy(one, ", first, ");
834 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
835 check(strtok((char *)NULL, ", ") == NULL, 7);
836 (void) strcpy(one, "1a, 1b; 2a, 2b");
837 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
838 equal(strtok((char *)NULL, "; "), "1b", 9);
839 equal(strtok((char *)NULL, ", "), "2a", 10);
840 (void) strcpy(two, "x-y");
841 equal(strtok(two, "-"), "x", 11); /* New string before done. */
842 equal(strtok((char *)NULL, "-"), "y", 12);
843 check(strtok((char *)NULL, "-") == NULL, 13);
844 (void) strcpy(one, "a,b, c,, ,d");
845 equal(strtok(one, ", "), "a", 14); /* Different separators. */
846 equal(strtok((char *)NULL, ", "), "b", 15);
847 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
848 equal(strtok((char *)NULL, " ,"), "d", 17);
849 check(strtok((char *)NULL, ", ") == NULL, 18);
850 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
851 (void) strcpy(one, ", ");
852 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
853 (void) strcpy(one, "");
854 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
855 (void) strcpy(one, "abc");
856 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
857 check(strtok((char *)NULL, ", ") == NULL, 23);
858 (void) strcpy(one, "abc");
859 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
860 check(strtok((char *)NULL, "") == NULL, 25);
861 (void) strcpy(one, "abcdefgh");
862 (void) strcpy(one, "a,b,c");
863 equal(strtok(one, ","), "a", 26); /* Basics again... */
864 equal(strtok((char *)NULL, ","), "b", 27);
865 equal(strtok((char *)NULL, ","), "c", 28);
866 check(strtok((char *)NULL, ",") == NULL, 29);
867 equal(one+6, "gh", 30); /* Stomped past end? */
868 equal(one, "a", 31); /* Stomped old tokens? */
869 equal(one+2, "b", 32);
870 equal(one+4, "c", 33);
873 static void
874 test_strtok_r (void)
876 it = "strtok_r";
877 (void) strcpy(one, "first, second, third");
878 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
879 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
880 equal(one, "first", 2);
881 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
882 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
883 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
884 (void) strcpy(one, ", first, ");
885 cp = NULL;
886 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
887 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
888 (void) strcpy(one, "1a, 1b; 2a, 2b");
889 cp = NULL;
890 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
891 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
892 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
893 (void) strcpy(two, "x-y");
894 cp = NULL;
895 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
896 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
897 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
898 (void) strcpy(one, "a,b, c,, ,d");
899 cp = NULL;
900 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
901 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
902 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
903 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
904 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
905 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
906 (void) strcpy(one, ", ");
907 cp = NULL;
908 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
909 (void) strcpy(one, "");
910 cp = NULL;
911 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
912 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
913 (void) strcpy(one, "abc");
914 cp = NULL;
915 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
916 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
917 (void) strcpy(one, "abc");
918 cp = NULL;
919 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
920 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
921 (void) strcpy(one, "abcdefgh");
922 (void) strcpy(one, "a,b,c");
923 cp = NULL;
924 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
925 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
926 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
927 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
928 equal(one+6, "gh", 31); /* Stomped past end? */
929 equal(one, "a", 32); /* Stomped old tokens? */
930 equal(one+2, "b", 33);
931 equal(one+4, "c", 34);
932 strcpy (one, ":::");
933 cp = NULL;
934 check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
935 check (strtok_r (NULL, ":", &cp) == NULL, 36);
938 static void
939 test_strsep (void)
941 char *ptr;
942 it = "strsep";
943 cp = strcpy(one, "first, second, third");
944 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
945 equal(one, "first", 2);
946 equal(strsep(&cp, ", "), "", 3);
947 equal(strsep(&cp, ", "), "second", 4);
948 equal(strsep(&cp, ", "), "", 5);
949 equal(strsep(&cp, ", "), "third", 6);
950 check(strsep(&cp, ", ") == NULL, 7);
951 cp = strcpy(one, ", first, ");
952 equal(strsep(&cp, ", "), "", 8);
953 equal(strsep(&cp, ", "), "", 9);
954 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
955 equal(strsep(&cp, ", "), "", 11);
956 equal(strsep(&cp, ", "), "", 12);
957 check(strsep(&cp, ", ") == NULL, 13);
958 cp = strcpy(one, "1a, 1b; 2a, 2b");
959 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
960 equal(strsep(&cp, ", "), "", 15);
961 equal(strsep(&cp, "; "), "1b", 16);
962 equal(strsep(&cp, ", "), "", 17);
963 equal(strsep(&cp, ", "), "2a", 18);
964 cp = strcpy(two, "x-y");
965 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
966 equal(strsep(&cp, "-"), "y", 20);
967 check(strsep(&cp, "-") == NULL, 21);
968 cp = strcpy(one, "a,b, c,, ,d ");
969 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
970 equal(strsep(&cp, ", "), "b", 23);
971 equal(strsep(&cp, " ,"), "", 24);
972 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
973 equal(strsep(&cp, " ,"), "", 26);
974 equal(strsep(&cp, " ,"), "", 27);
975 equal(strsep(&cp, " ,"), "", 28);
976 equal(strsep(&cp, " ,"), "d", 29);
977 equal(strsep(&cp, " ,"), "", 30);
978 check(strsep(&cp, ", ") == NULL, 31);
979 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
980 cp = strcpy(one, ", ");
981 equal(strsep(&cp, ", "), "", 33);
982 equal(strsep(&cp, ", "), "", 34);
983 equal(strsep(&cp, ", "), "", 35);
984 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
985 cp = strcpy(one, "");
986 equal(strsep(&cp, ", "), "", 37);
987 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
988 cp = strcpy(one, "abc");
989 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
990 check(strsep(&cp, ", ") == NULL, 40);
991 cp = strcpy(one, "abc");
992 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
993 check(strsep(&cp, "") == NULL, 42);
994 (void) strcpy(one, "abcdefgh");
995 cp = strcpy(one, "a,b,c");
996 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
997 equal(strsep(&cp, ","), "b", 44);
998 equal(strsep(&cp, ","), "c", 45);
999 check(strsep(&cp, ",") == NULL, 46);
1000 equal(one+6, "gh", 47); /* Stomped past end? */
1001 equal(one, "a", 48); /* Stomped old tokens? */
1002 equal(one+2, "b", 49);
1003 equal(one+4, "c", 50);
1006 char text[] = "This,is,a,test";
1007 char *list = strdupa (text);
1008 equal (strsep (&list, ","), "This", 51);
1009 equal (strsep (&list, ","), "is", 52);
1010 equal (strsep (&list, ","), "a", 53);
1011 equal (strsep (&list, ","), "test", 54);
1012 check (strsep (&list, ",") == NULL, 55);
1015 cp = strcpy(one, "a,b, c,, ,d,");
1016 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1017 equal(strsep(&cp, ","), "b", 57);
1018 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1019 equal(strsep(&cp, ","), "", 59);
1020 equal(strsep(&cp, ","), " ", 60);
1021 equal(strsep(&cp, ","), "d", 61);
1022 equal(strsep(&cp, ","), "", 62);
1023 check(strsep(&cp, ",") == NULL, 63);
1024 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1026 cp = strcpy(one, "a,b, c,, ,d,");
1027 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1028 equal(strsep(&cp, "x,y"), "b", 66);
1029 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1030 equal(strsep(&cp, "xy,"), "", 68);
1031 equal(strsep(&cp, "x,y"), " ", 69);
1032 equal(strsep(&cp, ",xy"), "d", 70);
1033 equal(strsep(&cp, "xy,"), "", 71);
1034 check(strsep(&cp, "x,y") == NULL, 72);
1035 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1037 cp = strcpy(one, "ABC");
1038 one[4] = ':';
1039 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1040 ptr = strsep(&cp, ":");
1041 equal(ptr, "", 75);
1042 check(ptr == one + 3, 76);
1043 check(cp == NULL, 77);
1045 cp = strcpy(one, "ABC");
1046 one[4] = ':';
1047 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1048 ptr = strsep(&cp, ":.");
1049 equal(ptr, "", 79);
1050 check(ptr == one + 3, 80);
1052 cp = strcpy(one, "ABC"); /* No token in string. */
1053 equal(strsep(&cp, ","), "ABC", 81);
1054 check(cp == NULL, 82);
1056 *one = '\0'; /* Empty string. */
1057 cp = one;
1058 ptr = strsep(&cp, ",");
1059 equal(ptr, "", 83);
1060 check(ptr == one, 84);
1061 check(cp == NULL, 85);
1063 *one = '\0'; /* Empty string and no token. */
1064 cp = one;
1065 ptr = strsep(&cp, "");
1066 equal(ptr, "", 86);
1067 check(ptr == one , 87);
1068 check(cp == NULL, 88);
1071 static void
1072 test_memcmp (void)
1074 int cnt = 1;
1075 char one[21];
1076 char two[21];
1078 it = "memcmp";
1079 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1080 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1081 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1082 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1083 check(memcmp("alph", "cold", 4) < 0, cnt++);
1084 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1085 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1086 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1087 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1088 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1089 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1090 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1091 /* Comparisons with shifting 4-byte boundaries. */
1092 for (int i = 0; i < 4; ++i)
1094 char *a = one + i;
1095 char *b = two + i;
1096 strncpy(a, "--------11112222", 16);
1097 strncpy(b, "--------33334444", 16);
1098 check(memcmp(b, a, 16) > 0, cnt++);
1099 check(memcmp(a, b, 16) < 0, cnt++);
1103 static void
1104 test_memchr (void)
1106 it = "memchr";
1107 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1108 (void) strcpy(one, "abcd");
1109 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1110 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1111 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1112 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1113 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1114 (void) strcpy(one, "ababa");
1115 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1116 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1117 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1118 (void) strcpy(one, "a\203b");
1119 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1121 /* now test all possible alignment and length combinations to catch
1122 bugs due to unrolled loops (assuming unrolling is limited to no
1123 more than 128 byte chunks: */
1125 char buf[128 + sizeof(long)];
1126 long align, len, i, pos;
1128 for (align = 0; align < (long) sizeof(long); ++align) {
1129 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
1130 for (i = 0; i < len; ++i) {
1131 buf[align + i] = 'x'; /* don't depend on memset... */
1133 for (pos = 0; pos < len; ++pos) {
1134 #if 0
1135 printf("align %d, len %d, pos %d\n", align, len, pos);
1136 #endif
1137 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1138 check(memchr(buf + align, 'x', pos) == NULL, 11);
1139 buf[align + pos] = '-';
1146 static void
1147 test_memcpy (void)
1149 int i;
1150 it = "memcpy";
1151 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1152 equal(one, "abc", 2); /* Did the copy go right? */
1154 (void) strcpy(one, "abcdefgh");
1155 (void) memcpy(one+1, "xyz", 2);
1156 equal(one, "axydefgh", 3); /* Basic test. */
1158 (void) strcpy(one, "abc");
1159 (void) memcpy(one, "xyz", 0);
1160 equal(one, "abc", 4); /* Zero-length copy. */
1162 (void) strcpy(one, "hi there");
1163 (void) strcpy(two, "foo");
1164 (void) memcpy(two, one, 9);
1165 equal(two, "hi there", 5); /* Just paranoia. */
1166 equal(one, "hi there", 6); /* Stomped on source? */
1168 for (i = 0; i < 16; i++)
1170 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1171 strcpy (one, x);
1172 check (memcpy (one + i, "hi there", 9) == one + i,
1173 7 + (i * 6)); /* Unaligned destination. */
1174 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1175 equal (one + i, "hi there", 9 + (i * 6));
1176 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1177 check (memcpy (two, one + i, 9) == two,
1178 11 + (i * 6)); /* Unaligned source. */
1179 equal (two, "hi there", 12 + (i * 6));
1183 static void
1184 test_mempcpy (void)
1186 int i;
1187 it = "mempcpy";
1188 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1189 equal(one, "abc", 2); /* Did the copy go right? */
1191 (void) strcpy(one, "abcdefgh");
1192 (void) mempcpy(one+1, "xyz", 2);
1193 equal(one, "axydefgh", 3); /* Basic test. */
1195 (void) strcpy(one, "abc");
1196 (void) mempcpy(one, "xyz", 0);
1197 equal(one, "abc", 4); /* Zero-length copy. */
1199 (void) strcpy(one, "hi there");
1200 (void) strcpy(two, "foo");
1201 (void) mempcpy(two, one, 9);
1202 equal(two, "hi there", 5); /* Just paranoia. */
1203 equal(one, "hi there", 6); /* Stomped on source? */
1205 for (i = 0; i < 16; i++)
1207 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1208 strcpy (one, x);
1209 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1210 7 + (i * 6)); /* Unaligned destination. */
1211 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1212 equal (one + i, "hi there", 9 + (i * 6));
1213 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1214 check (mempcpy (two, one + i, 9) == two + 9,
1215 11 + (i * 6)); /* Unaligned source. */
1216 equal (two, "hi there", 12 + (i * 6));
1220 static void
1221 test_memmove (void)
1223 it = "memmove";
1224 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1225 equal(one, "abc", 2); /* Did the copy go right? */
1227 (void) strcpy(one, "abcdefgh");
1228 (void) memmove(one+1, "xyz", 2);
1229 equal(one, "axydefgh", 3); /* Basic test. */
1231 (void) strcpy(one, "abc");
1232 (void) memmove(one, "xyz", 0);
1233 equal(one, "abc", 4); /* Zero-length copy. */
1235 (void) strcpy(one, "hi there");
1236 (void) strcpy(two, "foo");
1237 (void) memmove(two, one, 9);
1238 equal(two, "hi there", 5); /* Just paranoia. */
1239 equal(one, "hi there", 6); /* Stomped on source? */
1241 (void) strcpy(one, "abcdefgh");
1242 (void) memmove(one+1, one, 9);
1243 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1245 (void) strcpy(one, "abcdefgh");
1246 (void) memmove(one+1, one+2, 7);
1247 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1249 (void) strcpy(one, "abcdefgh");
1250 (void) memmove(one, one, 9);
1251 equal(one, "abcdefgh", 9); /* 100% overlap. */
1254 static void
1255 test_memccpy (void)
1257 /* First test like memcpy, then the search part The SVID, the only
1258 place where memccpy is mentioned, says overlap might fail, so we
1259 don't try it. Besides, it's hard to see the rationale for a
1260 non-left-to-right memccpy. */
1261 it = "memccpy";
1262 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1263 equal(one, "abc", 2); /* Did the copy go right? */
1265 (void) strcpy(one, "abcdefgh");
1266 (void) memccpy(one+1, "xyz", 'q', 2);
1267 equal(one, "axydefgh", 3); /* Basic test. */
1269 (void) strcpy(one, "abc");
1270 (void) memccpy(one, "xyz", 'q', 0);
1271 equal(one, "abc", 4); /* Zero-length copy. */
1273 (void) strcpy(one, "hi there");
1274 (void) strcpy(two, "foo");
1275 (void) memccpy(two, one, 'q', 9);
1276 equal(two, "hi there", 5); /* Just paranoia. */
1277 equal(one, "hi there", 6); /* Stomped on source? */
1279 (void) strcpy(one, "abcdefgh");
1280 (void) strcpy(two, "horsefeathers");
1281 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1282 equal(one, "abcdefgh", 8); /* Source intact? */
1283 equal(two, "abcdefeathers", 9); /* Copy correct? */
1285 (void) strcpy(one, "abcd");
1286 (void) strcpy(two, "bumblebee");
1287 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1288 equal(two, "aumblebee", 11);
1289 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1290 equal(two, "abcdlebee", 13);
1291 (void) strcpy(one, "xyz");
1292 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1293 equal(two, "xbcdlebee", 15);
1296 static void
1297 test_memset (void)
1299 int i;
1301 it = "memset";
1302 (void) strcpy(one, "abcdefgh");
1303 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1304 equal(one, "axxxefgh", 2); /* Basic test. */
1306 (void) memset(one+2, 'y', 0);
1307 equal(one, "axxxefgh", 3); /* Zero-length set. */
1309 (void) memset(one+5, 0, 1);
1310 equal(one, "axxxe", 4); /* Zero fill. */
1311 equal(one+6, "gh", 5); /* And the leftover. */
1313 (void) memset(one+2, 010045, 1);
1314 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1316 /* Non-8bit fill character. */
1317 memset (one, 0x101, sizeof (one));
1318 for (i = 0; i < (int) sizeof (one); ++i)
1319 check (one[i] == '\01', 7);
1321 /* Test for more complex versions of memset, for all alignments and
1322 lengths up to 256. This test takes a little while, perhaps it should
1323 be made weaker? */
1325 char data[512];
1326 int j;
1327 int k;
1328 int c;
1330 for (i = 0; i < 512; i++)
1331 data[i] = 'x';
1332 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1333 memset(,'y',) */
1334 for (j = 0; j < 256; j++)
1335 for (i = 0; i < 256; i++)
1337 memset (data + i, c, j);
1338 for (k = 0; k < i; k++)
1339 if (data[k] != 'x')
1340 goto fail;
1341 for (k = i; k < i+j; k++)
1343 if (data[k] != c)
1344 goto fail;
1345 data[k] = 'x';
1347 for (k = i+j; k < 512; k++)
1348 if (data[k] != 'x')
1349 goto fail;
1350 continue;
1352 fail:
1353 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1358 static void
1359 test_bcopy (void)
1361 /* Much like memcpy. Berklix manual is silent about overlap, so
1362 don't test it. */
1363 it = "bcopy";
1364 (void) bcopy("abc", one, 4);
1365 equal(one, "abc", 1); /* Simple copy. */
1367 (void) strcpy(one, "abcdefgh");
1368 (void) bcopy("xyz", one+1, 2);
1369 equal(one, "axydefgh", 2); /* Basic test. */
1371 (void) strcpy(one, "abc");
1372 (void) bcopy("xyz", one, 0);
1373 equal(one, "abc", 3); /* Zero-length copy. */
1375 (void) strcpy(one, "hi there");
1376 (void) strcpy(two, "foo");
1377 (void) bcopy(one, two, 9);
1378 equal(two, "hi there", 4); /* Just paranoia. */
1379 equal(one, "hi there", 5); /* Stomped on source? */
1382 static void
1383 test_bzero (void)
1385 it = "bzero";
1386 (void) strcpy(one, "abcdef");
1387 bzero(one+2, 2);
1388 equal(one, "ab", 1); /* Basic test. */
1389 equal(one+3, "", 2);
1390 equal(one+4, "ef", 3);
1392 (void) strcpy(one, "abcdef");
1393 bzero(one+2, 0);
1394 equal(one, "abcdef", 4); /* Zero-length copy. */
1397 static void
1398 test_strndup (void)
1400 char *p, *q;
1401 it = "strndup";
1402 p = strndup("abcdef", 12);
1403 check(p != NULL, 1);
1404 if (p != NULL)
1406 equal(p, "abcdef", 2);
1407 q = strndup(p + 1, 2);
1408 check(q != NULL, 3);
1409 if (q != NULL)
1410 equal(q, "bc", 4);
1411 free (q);
1413 free (p);
1414 p = strndup("abc def", 3);
1415 check(p != NULL, 5);
1416 if (p != NULL)
1417 equal(p, "abc", 6);
1418 free (p);
1421 static void
1422 test_bcmp (void)
1424 it = "bcmp";
1425 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1426 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1427 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1428 check(bcmp("abce", "abcd", 4) != 0, 4);
1429 check(bcmp("alph", "beta", 4) != 0, 5);
1430 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1431 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1434 static void
1435 test_strerror (void)
1437 it = "strerror";
1438 check(strerror(EDOM) != 0, 1);
1439 check(strerror(ERANGE) != 0, 2);
1440 check(strerror(ENOENT) != 0, 3);
1443 static void
1444 test_strcasecmp (void)
1446 it = "strcasecmp";
1447 /* Note that the locale is "C". */
1448 check(strcasecmp("a", "a") == 0, 1);
1449 check(strcasecmp("a", "A") == 0, 2);
1450 check(strcasecmp("A", "a") == 0, 3);
1451 check(strcasecmp("a", "b") < 0, 4);
1452 check(strcasecmp("c", "b") > 0, 5);
1453 check(strcasecmp("abc", "AbC") == 0, 6);
1454 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1455 check(strcasecmp("", "0123456789") < 0, 8);
1456 check(strcasecmp("AbC", "") > 0, 9);
1457 check(strcasecmp("AbC", "A") > 0, 10);
1458 check(strcasecmp("AbC", "Ab") > 0, 11);
1459 check(strcasecmp("AbC", "ab") > 0, 12);
1462 static void
1463 test_strncasecmp (void)
1465 it = "strncasecmp";
1466 /* Note that the locale is "C". */
1467 check(strncasecmp("a", "a", 5) == 0, 1);
1468 check(strncasecmp("a", "A", 5) == 0, 2);
1469 check(strncasecmp("A", "a", 5) == 0, 3);
1470 check(strncasecmp("a", "b", 5) < 0, 4);
1471 check(strncasecmp("c", "b", 5) > 0, 5);
1472 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1473 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1474 check(strncasecmp("", "0123456789", 10) < 0, 8);
1475 check(strncasecmp("AbC", "", 5) > 0, 9);
1476 check(strncasecmp("AbC", "A", 5) > 0, 10);
1477 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1478 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1479 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1480 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1481 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1482 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1483 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1484 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1485 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1486 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1490 main (void)
1492 int status;
1494 /* Test strcmp first because we use it to test other things. */
1495 test_strcmp ();
1497 /* Test strcpy next because we need it to set up other tests. */
1498 test_strcpy ();
1500 /* A closely related function is stpcpy. */
1501 test_stpcpy ();
1503 /* stpncpy. */
1504 test_stpncpy ();
1506 /* strcat. */
1507 test_strcat ();
1509 /* strncat. */
1510 test_strncat ();
1512 /* strncmp. */
1513 test_strncmp ();
1515 /* strncpy. */
1516 test_strncpy ();
1518 /* strlen. */
1519 test_strlen ();
1521 /* strnlen. */
1522 test_strnlen ();
1524 /* strchr. */
1525 test_strchr ();
1527 /* strchrnul. */
1528 test_strchrnul ();
1530 /* rawmemchr. */
1531 test_rawmemchr ();
1533 /* index - just like strchr. */
1534 test_index ();
1536 /* strrchr. */
1537 test_strrchr ();
1539 /* memrchr. */
1540 test_memrchr ();
1542 /* rindex - just like strrchr. */
1543 test_rindex ();
1545 /* strpbrk - somewhat like strchr. */
1546 test_strpbrk ();
1548 /* strstr - somewhat like strchr. */
1549 test_strstr ();
1551 /* strspn. */
1552 test_strspn ();
1554 /* strcspn. */
1555 test_strcspn ();
1557 /* strtok - the hard one. */
1558 test_strtok ();
1560 /* strtok_r. */
1561 test_strtok_r ();
1563 /* strsep. */
1564 test_strsep ();
1566 /* memcmp. */
1567 test_memcmp ();
1569 /* memchr. */
1570 test_memchr ();
1572 /* memcpy - need not work for overlap. */
1573 test_memcpy ();
1575 /* memmove - must work on overlap. */
1576 test_memmove ();
1578 /* mempcpy */
1579 test_mempcpy ();
1581 /* memccpy. */
1582 test_memccpy ();
1584 /* memset. */
1585 test_memset ();
1587 /* bcopy. */
1588 test_bcopy ();
1590 /* bzero. */
1591 test_bzero ();
1593 /* bcmp - somewhat like memcmp. */
1594 test_bcmp ();
1596 /* strndup. */
1597 test_strndup ();
1599 /* strerror - VERY system-dependent. */
1600 test_strerror ();
1602 /* strcasecmp. Without locale dependencies. */
1603 test_strcasecmp ();
1605 /* strncasecmp. Without locale dependencies. */
1606 test_strncasecmp ();
1608 if (errors == 0)
1610 status = EXIT_SUCCESS;
1611 puts("No errors.");
1613 else
1615 status = EXIT_FAILURE;
1616 printf("%Zd errors.\n", errors);
1619 return status;