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