Add feraiseexcept optimization for x86-32
[glibc.git] / string / tester.c
bloba86249de7db1f617d89ce3388d2aaa80102f0211
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, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE
23 #endif
25 /* Make sure we don't test the optimized inline functions if we want to
26 test the real implementation. */
27 #if !defined DO_STRING_INLINES
28 #undef __USE_STRING_INLINES
29 #endif
31 #include <errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <strings.h>
36 #include <fcntl.h>
39 #define STREQ(a, b) (strcmp((a), (b)) == 0)
41 const char *it = "<UNSET>"; /* Routine name for message routines. */
42 size_t errors = 0;
44 /* Complain if condition is not true. */
45 static void
46 check (int thing, int number)
48 if (!thing)
50 printf ("%s flunked test %d\n", it, number);
51 ++errors;
55 /* Complain if first two args don't strcmp as equal. */
56 static void
57 equal (const char *a, const char *b, int number)
59 check (a != NULL && b != NULL && STREQ (a, b), number);
62 char one[50];
63 char two[50];
64 char *cp;
66 static void
67 test_strcmp (void)
69 it = "strcmp";
70 check (strcmp ("", "") == 0, 1); /* Trivial case. */
71 check (strcmp ("a", "a") == 0, 2); /* Identity. */
72 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
73 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
74 check (strcmp ("abcd", "abc") > 0, 5);
75 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
76 check (strcmp ("abce", "abcd") > 0, 7);
77 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
78 check (strcmp ("a\203", "a\003") > 0, 9);
81 char buf1[0x40], buf2[0x40];
82 int i, j;
83 for (i=0; i < 0x10; i++)
84 for (j = 0; j < 0x10; j++)
86 int k;
87 for (k = 0; k < 0x3f; k++)
89 buf1[k] = '0' ^ (k & 4);
90 buf2[k] = '4' ^ (k & 4);
92 buf1[i] = buf1[0x3f] = 0;
93 buf2[j] = buf2[0x3f] = 0;
94 for (k = 0; k < 0xf; k++)
96 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
97 check (strcmp (buf1+i,buf2+j) == 0, cnum);
98 buf1[i+k] = 'A' + i + k;
99 buf1[i+k+1] = 0;
100 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
101 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
102 buf2[j+k] = 'B' + i + k;
103 buf2[j+k+1] = 0;
104 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
105 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
106 buf2[j+k] = 'A' + i + k;
107 buf1[i] = 'A' + i + 0x80;
108 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
109 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
110 buf1[i] = 'A' + i;
116 #define SIMPLE_COPY(fn, n, str, ntest) \
117 do { \
118 int __n; \
119 char *cp; \
120 for (__n = 0; __n < (int) sizeof (one); ++__n) \
121 one[__n] = 'Z'; \
122 fn (one, str); \
123 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
124 check (*cp == '0' + (n % 10), ntest); \
125 check (*cp == '\0', ntest); \
126 } while (0)
128 static void
129 test_strcpy (void)
131 int i;
132 it = "strcpy";
133 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
134 equal (one, "abcd", 2); /* Basic test. */
136 (void) strcpy (one, "x");
137 equal (one, "x", 3); /* Writeover. */
138 equal (one+2, "cd", 4); /* Wrote too much? */
140 (void) strcpy (two, "hi there");
141 (void) strcpy (one, two);
142 equal (one, "hi there", 5); /* Basic test encore. */
143 equal (two, "hi there", 6); /* Stomped on source? */
145 (void) strcpy (one, "");
146 equal (one, "", 7); /* Boundary condition. */
148 for (i = 0; i < 16; i++)
150 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
151 equal (one + i, "hi there", 8 + (i * 2));
152 (void) strcpy (two, one + i); /* Unaligned source. */
153 equal (two, "hi there", 9 + (i * 2));
156 SIMPLE_COPY(strcpy, 0, "", 41);
157 SIMPLE_COPY(strcpy, 1, "1", 42);
158 SIMPLE_COPY(strcpy, 2, "22", 43);
159 SIMPLE_COPY(strcpy, 3, "333", 44);
160 SIMPLE_COPY(strcpy, 4, "4444", 45);
161 SIMPLE_COPY(strcpy, 5, "55555", 46);
162 SIMPLE_COPY(strcpy, 6, "666666", 47);
163 SIMPLE_COPY(strcpy, 7, "7777777", 48);
164 SIMPLE_COPY(strcpy, 8, "88888888", 49);
165 SIMPLE_COPY(strcpy, 9, "999999999", 50);
166 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
167 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
168 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
169 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
170 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
171 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
172 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
174 /* Simple test using implicitly coerced `void *' arguments. */
175 const void *src = "frobozz";
176 void *dst = one;
177 check (strcpy (dst, src) == dst, 1);
178 equal (dst, "frobozz", 2);
181 static void
182 test_stpcpy (void)
184 it = "stpcpy";
185 check ((stpcpy (one, "a") - one) == 1, 1);
186 equal (one, "a", 2);
188 check ((stpcpy (one, "ab") - one) == 2, 3);
189 equal (one, "ab", 4);
191 check ((stpcpy (one, "abc") - one) == 3, 5);
192 equal (one, "abc", 6);
194 check ((stpcpy (one, "abcd") - one) == 4, 7);
195 equal (one, "abcd", 8);
197 check ((stpcpy (one, "abcde") - one) == 5, 9);
198 equal (one, "abcde", 10);
200 check ((stpcpy (one, "abcdef") - one) == 6, 11);
201 equal (one, "abcdef", 12);
203 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
204 equal (one, "abcdefg", 14);
206 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
207 equal (one, "abcdefgh", 16);
209 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
210 equal (one, "abcdefghi", 18);
212 check ((stpcpy (one, "x") - one) == 1, 19);
213 equal (one, "x", 20); /* Writeover. */
214 equal (one+2, "cdefghi", 21); /* Wrote too much? */
216 check ((stpcpy (one, "xx") - one) == 2, 22);
217 equal (one, "xx", 23); /* Writeover. */
218 equal (one+3, "defghi", 24); /* Wrote too much? */
220 check ((stpcpy (one, "xxx") - one) == 3, 25);
221 equal (one, "xxx", 26); /* Writeover. */
222 equal (one+4, "efghi", 27); /* Wrote too much? */
224 check ((stpcpy (one, "xxxx") - one) == 4, 28);
225 equal (one, "xxxx", 29); /* Writeover. */
226 equal (one+5, "fghi", 30); /* Wrote too much? */
228 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
229 equal (one, "xxxxx", 32); /* Writeover. */
230 equal (one+6, "ghi", 33); /* Wrote too much? */
232 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
233 equal (one, "xxxxxx", 35); /* Writeover. */
234 equal (one+7, "hi", 36); /* Wrote too much? */
236 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
237 equal (one, "xxxxxxx", 38); /* Writeover. */
238 equal (one+8, "i", 39); /* Wrote too much? */
240 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
241 equal (one, "abc", 41);
242 equal (one + 4, "xxx", 42);
244 SIMPLE_COPY(stpcpy, 0, "", 43);
245 SIMPLE_COPY(stpcpy, 1, "1", 44);
246 SIMPLE_COPY(stpcpy, 2, "22", 45);
247 SIMPLE_COPY(stpcpy, 3, "333", 46);
248 SIMPLE_COPY(stpcpy, 4, "4444", 47);
249 SIMPLE_COPY(stpcpy, 5, "55555", 48);
250 SIMPLE_COPY(stpcpy, 6, "666666", 49);
251 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
252 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
253 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
254 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
255 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
256 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
257 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
258 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
259 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
260 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
263 static void
264 test_stpncpy (void)
266 it = "stpncpy";
267 memset (one, 'x', sizeof (one));
268 check (stpncpy (one, "abc", 2) == one + 2, 1);
269 check (stpncpy (one, "abc", 3) == one + 3, 2);
270 check (stpncpy (one, "abc", 4) == one + 3, 3);
271 check (one[3] == '\0' && one[4] == 'x', 4);
272 check (stpncpy (one, "abcd", 5) == one + 4, 5);
273 check (one[4] == '\0' && one[5] == 'x', 6);
274 check (stpncpy (one, "abcd", 6) == one + 4, 7);
275 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
278 static void
279 test_strcat (void)
281 it = "strcat";
282 (void) strcpy (one, "ijk");
283 check (strcat (one, "lmn") == one, 1); /* Returned value. */
284 equal (one, "ijklmn", 2); /* Basic test. */
286 (void) strcpy (one, "x");
287 (void) strcat (one, "yz");
288 equal (one, "xyz", 3); /* Writeover. */
289 equal (one+4, "mn", 4); /* Wrote too much? */
291 (void) strcpy (one, "gh");
292 (void) strcpy (two, "ef");
293 (void) strcat (one, two);
294 equal (one, "ghef", 5); /* Basic test encore. */
295 equal (two, "ef", 6); /* Stomped on source? */
297 (void) strcpy (one, "");
298 (void) strcat (one, "");
299 equal (one, "", 7); /* Boundary conditions. */
300 (void) strcpy (one, "ab");
301 (void) strcat (one, "");
302 equal (one, "ab", 8);
303 (void) strcpy (one, "");
304 (void) strcat (one, "cd");
305 equal (one, "cd", 9);
307 int ntest = 10;
308 char buf1[80] __attribute__ ((aligned (16)));
309 char buf2[32] __attribute__ ((aligned (16)));
310 for (size_t n1 = 0; n1 < 16; ++n1)
311 for (size_t n2 = 0; n2 < 16; ++n2)
312 for (size_t n3 = 0; n3 < 32; ++n3)
314 size_t olderrors = errors;
316 memset (buf1, 'b', sizeof (buf1));
318 memset (buf1 + n2, 'a', n3);
319 buf1[n2 + n3] = '\0';
320 strcpy (buf2 + n1, "123");
322 check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
323 if (errors == olderrors)
324 for (size_t i = 0; i < sizeof (buf1); ++i)
326 if (i < n2)
327 check (buf1[i] == 'b', ntest);
328 else if (i < n2 + n3)
329 check (buf1[i] == 'a', ntest);
330 else if (i < n2 + n3 + 3)
331 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
332 else if (i == n2 + n3 + 3)
333 check (buf1[i] == '\0', ntest);
334 else
335 check (buf1[i] == 'b', ntest);
337 if (errors != olderrors)
339 printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
340 n1, n2, n3, buf1[0]);
341 for (size_t j = 1; j < sizeof (buf1); ++j)
342 printf (",%02hhx", buf1[j]);
343 putchar_unlocked ('\n');
344 break;
350 static void
351 test_strncat (void)
353 /* First test it as strcat, with big counts, then test the count
354 mechanism. */
355 it = "strncat";
356 (void) strcpy (one, "ijk");
357 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
358 equal (one, "ijklmn", 2); /* Basic test. */
360 (void) strcpy (one, "x");
361 (void) strncat (one, "yz", 99);
362 equal (one, "xyz", 3); /* Writeover. */
363 equal (one+4, "mn", 4); /* Wrote too much? */
365 (void) strcpy (one, "gh");
366 (void) strcpy (two, "ef");
367 (void) strncat (one, two, 99);
368 equal (one, "ghef", 5); /* Basic test encore. */
369 equal (two, "ef", 6); /* Stomped on source? */
371 (void) strcpy (one, "");
372 (void) strncat (one, "", 99);
373 equal (one, "", 7); /* Boundary conditions. */
374 (void) strcpy (one, "ab");
375 (void) strncat (one, "", 99);
376 equal (one, "ab", 8);
377 (void) strcpy (one, "");
378 (void) strncat (one, "cd", 99);
379 equal (one, "cd", 9);
381 (void) strcpy (one, "ab");
382 (void) strncat (one, "cdef", 2);
383 equal (one, "abcd", 10); /* Count-limited. */
385 (void) strncat (one, "gh", 0);
386 equal (one, "abcd", 11); /* Zero count. */
388 (void) strncat (one, "gh", 2);
389 equal (one, "abcdgh", 12); /* Count and length equal. */
391 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
392 equal (one, "abcdghij", 13);
394 int ntest = 14;
395 char buf1[80] __attribute__ ((aligned (16)));
396 char buf2[32] __attribute__ ((aligned (16)));
397 for (size_t n1 = 0; n1 < 16; ++n1)
398 for (size_t n2 = 0; n2 < 16; ++n2)
399 for (size_t n3 = 0; n3 < 32; ++n3)
400 for (size_t n4 = 0; n4 < 16; ++n4)
402 size_t olderrors = errors;
404 memset (buf1, 'b', sizeof (buf1));
406 memset (buf1 + n2, 'a', n3);
407 buf1[n2 + n3] = '\0';
408 strcpy (buf2 + n1, "123");
410 check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
411 == buf1 + n2, ntest);
412 if (errors == olderrors)
413 for (size_t i = 0; i < sizeof (buf1); ++i)
415 if (i < n2)
416 check (buf1[i] == 'b', ntest);
417 else if (i < n2 + n3)
418 check (buf1[i] == 'a', ntest);
419 else if (i < n2 + n3 + 3)
420 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
421 else if (i == n2 + n3 + 3)
422 check (buf1[i] == '\0', ntest);
423 else
424 check (buf1[i] == 'b', ntest);
426 if (errors != olderrors)
428 printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
429 n1, n2, n3, n4, buf1[0]);
430 for (size_t j = 1; j < sizeof (buf1); ++j)
431 printf (",%02hhx", buf1[j]);
432 putchar_unlocked ('\n');
433 break;
439 static void
440 test_strncmp (void)
442 /* First test as strcmp with big counts, then test count code. */
443 it = "strncmp";
444 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
445 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
446 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
447 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
448 check (strncmp ("abcd", "abc", 99) > 0, 5);
449 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
450 check (strncmp ("abce", "abcd", 99) > 0, 7);
451 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
452 check (strncmp ("a\203", "a\003", 2) > 0, 9);
453 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
454 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
455 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
456 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
457 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
458 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
461 static void
462 test_strncpy (void)
464 /* Testing is a bit different because of odd semantics. */
465 it = "strncpy";
466 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
467 equal (one, "abc", 2); /* Did the copy go right? */
469 (void) strcpy (one, "abcdefgh");
470 (void) strncpy (one, "xyz", 2);
471 equal (one, "xycdefgh", 3); /* Copy cut by count. */
473 (void) strcpy (one, "abcdefgh");
474 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
475 equal (one, "xyzdefgh", 4);
477 (void) strcpy (one, "abcdefgh");
478 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
479 equal (one, "xyz", 5);
480 equal (one+4, "efgh", 6); /* Wrote too much? */
482 (void) strcpy (one, "abcdefgh");
483 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
484 equal (one, "xyz", 7);
485 equal (one+4, "", 8);
486 equal (one+5, "fgh", 9);
488 (void) strcpy (one, "abc");
489 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
490 equal (one, "abc", 10);
492 (void) strncpy (one, "", 2); /* Zero-length source. */
493 equal (one, "", 11);
494 equal (one+1, "", 12);
495 equal (one+2, "c", 13);
497 (void) strcpy (one, "hi there");
498 (void) strncpy (two, one, 9);
499 equal (two, "hi there", 14); /* Just paranoia. */
500 equal (one, "hi there", 15); /* Stomped on source? */
503 static void
504 test_strlen (void)
506 it = "strlen";
507 check (strlen ("") == 0, 1); /* Empty. */
508 check (strlen ("a") == 1, 2); /* Single char. */
509 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
511 char buf[4096];
512 int i;
513 char *p;
514 for (i=0; i < 0x100; i++)
516 p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
517 strcpy (p, "OK");
518 strcpy (p+3, "BAD/WRONG");
519 check (strlen (p) == 2, 4+i);
524 static void
525 test_strnlen (void)
527 it = "strnlen";
528 check (strnlen ("", 10) == 0, 1); /* Empty. */
529 check (strnlen ("a", 10) == 1, 2); /* Single char. */
530 check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
531 check (strnlen ("foo", (size_t) -1) == 3, 4); /* limits of n. */
532 check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
533 check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
534 check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
535 check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
536 check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
538 char buf[4096];
539 for (int i = 0; i < 0x100; ++i)
541 char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
542 strcpy (p, "OK");
543 strcpy (p + 3, "BAD/WRONG");
544 check (strnlen (p, 100) == 2, 10 + i);
548 static void
549 test_strchr (void)
551 it = "strchr";
552 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
553 (void) strcpy (one, "abcd");
554 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
555 check (strchr (one, 'd') == one+3, 3); /* End of string. */
556 check (strchr (one, 'a') == one, 4); /* Beginning. */
557 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
558 (void) strcpy (one, "ababa");
559 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
560 (void) strcpy (one, "");
561 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
562 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
564 char buf[4096];
565 int i;
566 char *p;
567 for (i=0; i < 0x100; i++)
569 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
570 strcpy (p, "OK");
571 strcpy (p+3, "BAD/WRONG");
572 check (strchr (p, '/') == NULL, 9+i);
577 static void
578 test_strchrnul (void)
580 const char *os;
581 it = "strchrnul";
582 cp = strchrnul ((os = "abcd"), 'z');
583 check (*cp == '\0', 1); /* Not found. */
584 check (cp == os + 4, 2);
585 (void) strcpy (one, "abcd");
586 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
587 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
588 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
589 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
590 (void) strcpy (one, "ababa");
591 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
592 (void) strcpy (one, "");
593 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
594 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
596 char buf[4096];
597 int i;
598 char *p;
599 for (i=0; i < 0x100; i++)
601 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
602 strcpy (p, "OK");
603 strcpy (p+3, "BAD/WRONG");
604 cp = strchrnul (p, '/');
605 check (*cp == '\0', 9+2*i);
606 check (cp == p+2, 10+2*i);
611 static void
612 test_rawmemchr (void)
614 it = "rawmemchr";
615 (void) strcpy (one, "abcd");
616 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
617 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
618 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
619 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
620 (void) strcpy (one, "ababa");
621 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
622 (void) strcpy (one, "");
623 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
625 char buf[4096];
626 int i;
627 char *p;
628 for (i=0; i < 0x100; i++)
630 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
631 strcpy (p, "OK");
632 strcpy (p+3, "BAD/WRONG");
633 check (rawmemchr (p, 'R') == p+8, 6+i);
638 static void
639 test_index (void)
641 it = "index";
642 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
643 (void) strcpy (one, "abcd");
644 check (index (one, 'c') == one+2, 2); /* Basic test. */
645 check (index (one, 'd') == one+3, 3); /* End of string. */
646 check (index (one, 'a') == one, 4); /* Beginning. */
647 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
648 (void) strcpy (one, "ababa");
649 check (index (one, 'b') == one+1, 6); /* Finding first. */
650 (void) strcpy (one, "");
651 check (index (one, 'b') == NULL, 7); /* Empty string. */
652 check (index (one, '\0') == one, 8); /* NUL in empty string. */
655 static void
656 test_strrchr (void)
658 it = "strrchr";
659 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
660 (void) strcpy (one, "abcd");
661 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
662 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
663 check (strrchr (one, 'a') == one, 4); /* Beginning. */
664 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
665 (void) strcpy (one, "ababa");
666 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
667 (void) strcpy (one, "");
668 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
669 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
671 char buf[4096];
672 int i;
673 char *p;
674 for (i=0; i < 0x100; i++)
676 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
677 strcpy (p, "OK");
678 strcpy (p+3, "BAD/WRONG");
679 check (strrchr (p, '/') == NULL, 9+i);
684 static void
685 test_memrchr (void)
687 size_t l;
688 it = "memrchr";
689 check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
690 (void) strcpy (one, "abcd");
691 l = strlen (one) + 1;
692 check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
693 check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
694 check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
695 check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
696 (void) strcpy (one, "ababa");
697 l = strlen (one) + 1;
698 check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
699 (void) strcpy (one, "");
700 l = strlen (one) + 1;
701 check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
702 check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
704 /* now test all possible alignment and length combinations to catch
705 bugs due to unrolled loops (assuming unrolling is limited to no
706 more than 128 byte chunks: */
708 char buf[128 + sizeof(long)];
709 long align, len, i, pos;
711 for (align = 0; align < (long) sizeof(long); ++align) {
712 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
713 for (i = 0; i < len; ++i)
714 buf[align + i] = 'x'; /* don't depend on memset... */
716 for (pos = len - 1; pos >= 0; --pos) {
717 #if 0
718 printf("align %d, len %d, pos %d\n", align, len, pos);
719 #endif
720 check(memrchr(buf + align, 'x', len) == buf + align + pos, 9);
721 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
722 10);
723 buf[align + pos] = '-';
730 static void
731 test_rindex (void)
733 it = "rindex";
734 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
735 (void) strcpy (one, "abcd");
736 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
737 check (rindex (one, 'd') == one+3, 3); /* End of string. */
738 check (rindex (one, 'a') == one, 4); /* Beginning. */
739 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
740 (void) strcpy (one, "ababa");
741 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
742 (void) strcpy (one, "");
743 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
744 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
747 static void
748 test_strpbrk (void)
750 it = "strpbrk";
751 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
752 (void) strcpy(one, "abcd");
753 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
754 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
755 check(strpbrk(one, "a") == one, 4); /* Beginning. */
756 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
757 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
758 (void) strcpy(one, "abcabdea");
759 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
760 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
761 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
762 (void) strcpy(one, "");
763 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
764 (void) strcpy(one, "");
765 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
766 (void) strcpy(one, "");
767 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
768 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
769 (void) strcpy(one, "abcabdea");
770 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
771 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
772 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
773 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
776 static void
777 test_strstr (void)
779 it = "strstr";
780 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
781 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
782 (void) strcpy(one, "abcd");
783 check(strstr(one, "c") == one+2, 3); /* Basic test. */
784 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
785 check(strstr(one, "d") == one+3, 5); /* End of string. */
786 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
787 check(strstr(one, "abc") == one, 7); /* Beginning. */
788 check(strstr(one, "abcd") == one, 8); /* Exact match. */
789 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
790 check(strstr(one, "de") == NULL, 10); /* Past end. */
791 check(strstr(one, "") == one, 11); /* Finding empty. */
792 (void) strcpy(one, "ababa");
793 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
794 (void) strcpy(one, "");
795 check(strstr(one, "b") == NULL, 13); /* Empty string. */
796 check(strstr(one, "") == one, 14); /* Empty in empty string. */
797 (void) strcpy(one, "bcbca");
798 check(strstr(one, "bca") == one+2, 15); /* False start. */
799 (void) strcpy(one, "bbbcabbca");
800 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
803 static void
804 test_strspn (void)
806 it = "strspn";
807 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
808 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
809 check(strspn("abc", "qx") == 0, 3); /* None. */
810 check(strspn("", "ab") == 0, 4); /* Null string. */
811 check(strspn("abc", "") == 0, 5); /* Null search list. */
814 static void
815 test_strcspn (void)
817 it = "strcspn";
818 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
819 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
820 check(strcspn("abc", "abc") == 0, 3); /* None. */
821 check(strcspn("", "ab") == 0, 4); /* Null string. */
822 check(strcspn("abc", "") == 3, 5); /* Null search list. */
825 static void
826 test_strtok (void)
828 it = "strtok";
829 (void) strcpy(one, "first, second, third");
830 equal(strtok(one, ", "), "first", 1); /* Basic test. */
831 equal(one, "first", 2);
832 equal(strtok((char *)NULL, ", "), "second", 3);
833 equal(strtok((char *)NULL, ", "), "third", 4);
834 check(strtok((char *)NULL, ", ") == NULL, 5);
835 (void) strcpy(one, ", first, ");
836 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
837 check(strtok((char *)NULL, ", ") == NULL, 7);
838 (void) strcpy(one, "1a, 1b; 2a, 2b");
839 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
840 equal(strtok((char *)NULL, "; "), "1b", 9);
841 equal(strtok((char *)NULL, ", "), "2a", 10);
842 (void) strcpy(two, "x-y");
843 equal(strtok(two, "-"), "x", 11); /* New string before done. */
844 equal(strtok((char *)NULL, "-"), "y", 12);
845 check(strtok((char *)NULL, "-") == NULL, 13);
846 (void) strcpy(one, "a,b, c,, ,d");
847 equal(strtok(one, ", "), "a", 14); /* Different separators. */
848 equal(strtok((char *)NULL, ", "), "b", 15);
849 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
850 equal(strtok((char *)NULL, " ,"), "d", 17);
851 check(strtok((char *)NULL, ", ") == NULL, 18);
852 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
853 (void) strcpy(one, ", ");
854 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
855 (void) strcpy(one, "");
856 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
857 (void) strcpy(one, "abc");
858 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
859 check(strtok((char *)NULL, ", ") == NULL, 23);
860 (void) strcpy(one, "abc");
861 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
862 check(strtok((char *)NULL, "") == NULL, 25);
863 (void) strcpy(one, "abcdefgh");
864 (void) strcpy(one, "a,b,c");
865 equal(strtok(one, ","), "a", 26); /* Basics again... */
866 equal(strtok((char *)NULL, ","), "b", 27);
867 equal(strtok((char *)NULL, ","), "c", 28);
868 check(strtok((char *)NULL, ",") == NULL, 29);
869 equal(one+6, "gh", 30); /* Stomped past end? */
870 equal(one, "a", 31); /* Stomped old tokens? */
871 equal(one+2, "b", 32);
872 equal(one+4, "c", 33);
875 static void
876 test_strtok_r (void)
878 it = "strtok_r";
879 (void) strcpy(one, "first, second, third");
880 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
881 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
882 equal(one, "first", 2);
883 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
884 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
885 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
886 (void) strcpy(one, ", first, ");
887 cp = NULL;
888 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
889 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
890 (void) strcpy(one, "1a, 1b; 2a, 2b");
891 cp = NULL;
892 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
893 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
894 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
895 (void) strcpy(two, "x-y");
896 cp = NULL;
897 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
898 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
899 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
900 (void) strcpy(one, "a,b, c,, ,d");
901 cp = NULL;
902 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
903 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
904 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
905 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
906 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
907 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
908 (void) strcpy(one, ", ");
909 cp = NULL;
910 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
911 (void) strcpy(one, "");
912 cp = NULL;
913 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
914 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
915 (void) strcpy(one, "abc");
916 cp = NULL;
917 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
918 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
919 (void) strcpy(one, "abc");
920 cp = NULL;
921 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
922 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
923 (void) strcpy(one, "abcdefgh");
924 (void) strcpy(one, "a,b,c");
925 cp = NULL;
926 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
927 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
928 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
929 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
930 equal(one+6, "gh", 31); /* Stomped past end? */
931 equal(one, "a", 32); /* Stomped old tokens? */
932 equal(one+2, "b", 33);
933 equal(one+4, "c", 34);
934 strcpy (one, ":::");
935 cp = NULL;
936 check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
937 check (strtok_r (NULL, ":", &cp) == NULL, 36);
940 static void
941 test_strsep (void)
943 char *ptr;
944 it = "strsep";
945 cp = strcpy(one, "first, second, third");
946 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
947 equal(one, "first", 2);
948 equal(strsep(&cp, ", "), "", 3);
949 equal(strsep(&cp, ", "), "second", 4);
950 equal(strsep(&cp, ", "), "", 5);
951 equal(strsep(&cp, ", "), "third", 6);
952 check(strsep(&cp, ", ") == NULL, 7);
953 cp = strcpy(one, ", first, ");
954 equal(strsep(&cp, ", "), "", 8);
955 equal(strsep(&cp, ", "), "", 9);
956 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
957 equal(strsep(&cp, ", "), "", 11);
958 equal(strsep(&cp, ", "), "", 12);
959 check(strsep(&cp, ", ") == NULL, 13);
960 cp = strcpy(one, "1a, 1b; 2a, 2b");
961 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
962 equal(strsep(&cp, ", "), "", 15);
963 equal(strsep(&cp, "; "), "1b", 16);
964 equal(strsep(&cp, ", "), "", 17);
965 equal(strsep(&cp, ", "), "2a", 18);
966 cp = strcpy(two, "x-y");
967 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
968 equal(strsep(&cp, "-"), "y", 20);
969 check(strsep(&cp, "-") == NULL, 21);
970 cp = strcpy(one, "a,b, c,, ,d ");
971 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
972 equal(strsep(&cp, ", "), "b", 23);
973 equal(strsep(&cp, " ,"), "", 24);
974 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
975 equal(strsep(&cp, " ,"), "", 26);
976 equal(strsep(&cp, " ,"), "", 27);
977 equal(strsep(&cp, " ,"), "", 28);
978 equal(strsep(&cp, " ,"), "d", 29);
979 equal(strsep(&cp, " ,"), "", 30);
980 check(strsep(&cp, ", ") == NULL, 31);
981 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
982 cp = strcpy(one, ", ");
983 equal(strsep(&cp, ", "), "", 33);
984 equal(strsep(&cp, ", "), "", 34);
985 equal(strsep(&cp, ", "), "", 35);
986 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
987 cp = strcpy(one, "");
988 equal(strsep(&cp, ", "), "", 37);
989 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
990 cp = strcpy(one, "abc");
991 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
992 check(strsep(&cp, ", ") == NULL, 40);
993 cp = strcpy(one, "abc");
994 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
995 check(strsep(&cp, "") == NULL, 42);
996 (void) strcpy(one, "abcdefgh");
997 cp = strcpy(one, "a,b,c");
998 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
999 equal(strsep(&cp, ","), "b", 44);
1000 equal(strsep(&cp, ","), "c", 45);
1001 check(strsep(&cp, ",") == NULL, 46);
1002 equal(one+6, "gh", 47); /* Stomped past end? */
1003 equal(one, "a", 48); /* Stomped old tokens? */
1004 equal(one+2, "b", 49);
1005 equal(one+4, "c", 50);
1008 char text[] = "This,is,a,test";
1009 char *list = strdupa (text);
1010 equal (strsep (&list, ","), "This", 51);
1011 equal (strsep (&list, ","), "is", 52);
1012 equal (strsep (&list, ","), "a", 53);
1013 equal (strsep (&list, ","), "test", 54);
1014 check (strsep (&list, ",") == NULL, 55);
1017 cp = strcpy(one, "a,b, c,, ,d,");
1018 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1019 equal(strsep(&cp, ","), "b", 57);
1020 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1021 equal(strsep(&cp, ","), "", 59);
1022 equal(strsep(&cp, ","), " ", 60);
1023 equal(strsep(&cp, ","), "d", 61);
1024 equal(strsep(&cp, ","), "", 62);
1025 check(strsep(&cp, ",") == NULL, 63);
1026 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1028 cp = strcpy(one, "a,b, c,, ,d,");
1029 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1030 equal(strsep(&cp, "x,y"), "b", 66);
1031 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1032 equal(strsep(&cp, "xy,"), "", 68);
1033 equal(strsep(&cp, "x,y"), " ", 69);
1034 equal(strsep(&cp, ",xy"), "d", 70);
1035 equal(strsep(&cp, "xy,"), "", 71);
1036 check(strsep(&cp, "x,y") == NULL, 72);
1037 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1039 cp = strcpy(one, "ABC");
1040 one[4] = ':';
1041 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1042 ptr = strsep(&cp, ":");
1043 equal(ptr, "", 75);
1044 check(ptr == one + 3, 76);
1045 check(cp == NULL, 77);
1047 cp = strcpy(one, "ABC");
1048 one[4] = ':';
1049 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1050 ptr = strsep(&cp, ":.");
1051 equal(ptr, "", 79);
1052 check(ptr == one + 3, 80);
1054 cp = strcpy(one, "ABC"); /* No token in string. */
1055 equal(strsep(&cp, ","), "ABC", 81);
1056 check(cp == NULL, 82);
1058 *one = '\0'; /* Empty string. */
1059 cp = one;
1060 ptr = strsep(&cp, ",");
1061 equal(ptr, "", 83);
1062 check(ptr == one, 84);
1063 check(cp == NULL, 85);
1065 *one = '\0'; /* Empty string and no token. */
1066 cp = one;
1067 ptr = strsep(&cp, "");
1068 equal(ptr, "", 86);
1069 check(ptr == one , 87);
1070 check(cp == NULL, 88);
1073 static void
1074 test_memcmp (void)
1076 int cnt = 1;
1077 char one[21];
1078 char two[21];
1080 it = "memcmp";
1081 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1082 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1083 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1084 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1085 check(memcmp("alph", "cold", 4) < 0, cnt++);
1086 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1087 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1088 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1089 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1090 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1091 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1092 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1093 /* Comparisons with shifting 4-byte boundaries. */
1094 for (int i = 0; i < 4; ++i)
1096 char *a = one + i;
1097 char *b = two + i;
1098 strncpy(a, "--------11112222", 16);
1099 strncpy(b, "--------33334444", 16);
1100 check(memcmp(b, a, 16) > 0, cnt++);
1101 check(memcmp(a, b, 16) < 0, cnt++);
1105 static void
1106 test_memchr (void)
1108 it = "memchr";
1109 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1110 (void) strcpy(one, "abcd");
1111 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1112 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1113 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1114 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1115 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1116 (void) strcpy(one, "ababa");
1117 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1118 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1119 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1120 (void) strcpy(one, "a\203b");
1121 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1123 /* now test all possible alignment and length combinations to catch
1124 bugs due to unrolled loops (assuming unrolling is limited to no
1125 more than 128 byte chunks: */
1127 char buf[128 + sizeof(long)];
1128 long align, len, i, pos;
1130 for (align = 0; align < (long) sizeof(long); ++align) {
1131 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
1132 for (i = 0; i < len; ++i) {
1133 buf[align + i] = 'x'; /* don't depend on memset... */
1135 for (pos = 0; pos < len; ++pos) {
1136 #if 0
1137 printf("align %d, len %d, pos %d\n", align, len, pos);
1138 #endif
1139 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1140 check(memchr(buf + align, 'x', pos) == NULL, 11);
1141 buf[align + pos] = '-';
1148 static void
1149 test_memcpy (void)
1151 int i;
1152 it = "memcpy";
1153 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1154 equal(one, "abc", 2); /* Did the copy go right? */
1156 (void) strcpy(one, "abcdefgh");
1157 (void) memcpy(one+1, "xyz", 2);
1158 equal(one, "axydefgh", 3); /* Basic test. */
1160 (void) strcpy(one, "abc");
1161 (void) memcpy(one, "xyz", 0);
1162 equal(one, "abc", 4); /* Zero-length copy. */
1164 (void) strcpy(one, "hi there");
1165 (void) strcpy(two, "foo");
1166 (void) memcpy(two, one, 9);
1167 equal(two, "hi there", 5); /* Just paranoia. */
1168 equal(one, "hi there", 6); /* Stomped on source? */
1170 for (i = 0; i < 16; i++)
1172 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1173 strcpy (one, x);
1174 check (memcpy (one + i, "hi there", 9) == one + i,
1175 7 + (i * 6)); /* Unaligned destination. */
1176 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1177 equal (one + i, "hi there", 9 + (i * 6));
1178 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1179 check (memcpy (two, one + i, 9) == two,
1180 11 + (i * 6)); /* Unaligned source. */
1181 equal (two, "hi there", 12 + (i * 6));
1185 static void
1186 test_mempcpy (void)
1188 int i;
1189 it = "mempcpy";
1190 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1191 equal(one, "abc", 2); /* Did the copy go right? */
1193 (void) strcpy(one, "abcdefgh");
1194 (void) mempcpy(one+1, "xyz", 2);
1195 equal(one, "axydefgh", 3); /* Basic test. */
1197 (void) strcpy(one, "abc");
1198 (void) mempcpy(one, "xyz", 0);
1199 equal(one, "abc", 4); /* Zero-length copy. */
1201 (void) strcpy(one, "hi there");
1202 (void) strcpy(two, "foo");
1203 (void) mempcpy(two, one, 9);
1204 equal(two, "hi there", 5); /* Just paranoia. */
1205 equal(one, "hi there", 6); /* Stomped on source? */
1207 for (i = 0; i < 16; i++)
1209 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1210 strcpy (one, x);
1211 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1212 7 + (i * 6)); /* Unaligned destination. */
1213 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1214 equal (one + i, "hi there", 9 + (i * 6));
1215 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1216 check (mempcpy (two, one + i, 9) == two + 9,
1217 11 + (i * 6)); /* Unaligned source. */
1218 equal (two, "hi there", 12 + (i * 6));
1222 static void
1223 test_memmove (void)
1225 it = "memmove";
1226 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1227 equal(one, "abc", 2); /* Did the copy go right? */
1229 (void) strcpy(one, "abcdefgh");
1230 (void) memmove(one+1, "xyz", 2);
1231 equal(one, "axydefgh", 3); /* Basic test. */
1233 (void) strcpy(one, "abc");
1234 (void) memmove(one, "xyz", 0);
1235 equal(one, "abc", 4); /* Zero-length copy. */
1237 (void) strcpy(one, "hi there");
1238 (void) strcpy(two, "foo");
1239 (void) memmove(two, one, 9);
1240 equal(two, "hi there", 5); /* Just paranoia. */
1241 equal(one, "hi there", 6); /* Stomped on source? */
1243 (void) strcpy(one, "abcdefgh");
1244 (void) memmove(one+1, one, 9);
1245 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1247 (void) strcpy(one, "abcdefgh");
1248 (void) memmove(one+1, one+2, 7);
1249 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1251 (void) strcpy(one, "abcdefgh");
1252 (void) memmove(one, one, 9);
1253 equal(one, "abcdefgh", 9); /* 100% overlap. */
1256 static void
1257 test_memccpy (void)
1259 /* First test like memcpy, then the search part The SVID, the only
1260 place where memccpy is mentioned, says overlap might fail, so we
1261 don't try it. Besides, it's hard to see the rationale for a
1262 non-left-to-right memccpy. */
1263 it = "memccpy";
1264 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1265 equal(one, "abc", 2); /* Did the copy go right? */
1267 (void) strcpy(one, "abcdefgh");
1268 (void) memccpy(one+1, "xyz", 'q', 2);
1269 equal(one, "axydefgh", 3); /* Basic test. */
1271 (void) strcpy(one, "abc");
1272 (void) memccpy(one, "xyz", 'q', 0);
1273 equal(one, "abc", 4); /* Zero-length copy. */
1275 (void) strcpy(one, "hi there");
1276 (void) strcpy(two, "foo");
1277 (void) memccpy(two, one, 'q', 9);
1278 equal(two, "hi there", 5); /* Just paranoia. */
1279 equal(one, "hi there", 6); /* Stomped on source? */
1281 (void) strcpy(one, "abcdefgh");
1282 (void) strcpy(two, "horsefeathers");
1283 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1284 equal(one, "abcdefgh", 8); /* Source intact? */
1285 equal(two, "abcdefeathers", 9); /* Copy correct? */
1287 (void) strcpy(one, "abcd");
1288 (void) strcpy(two, "bumblebee");
1289 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1290 equal(two, "aumblebee", 11);
1291 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1292 equal(two, "abcdlebee", 13);
1293 (void) strcpy(one, "xyz");
1294 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1295 equal(two, "xbcdlebee", 15);
1298 static void
1299 test_memset (void)
1301 int i;
1303 it = "memset";
1304 (void) strcpy(one, "abcdefgh");
1305 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1306 equal(one, "axxxefgh", 2); /* Basic test. */
1308 (void) memset(one+2, 'y', 0);
1309 equal(one, "axxxefgh", 3); /* Zero-length set. */
1311 (void) memset(one+5, 0, 1);
1312 equal(one, "axxxe", 4); /* Zero fill. */
1313 equal(one+6, "gh", 5); /* And the leftover. */
1315 (void) memset(one+2, 010045, 1);
1316 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1318 /* Non-8bit fill character. */
1319 memset (one, 0x101, sizeof (one));
1320 for (i = 0; i < (int) sizeof (one); ++i)
1321 check (one[i] == '\01', 7);
1323 /* Test for more complex versions of memset, for all alignments and
1324 lengths up to 256. This test takes a little while, perhaps it should
1325 be made weaker? */
1327 char data[512];
1328 int j;
1329 int k;
1330 int c;
1332 for (i = 0; i < 512; i++)
1333 data[i] = 'x';
1334 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1335 memset(,'y',) */
1336 for (j = 0; j < 256; j++)
1337 for (i = 0; i < 256; i++)
1339 memset (data + i, c, j);
1340 for (k = 0; k < i; k++)
1341 if (data[k] != 'x')
1342 goto fail;
1343 for (k = i; k < i+j; k++)
1345 if (data[k] != c)
1346 goto fail;
1347 data[k] = 'x';
1349 for (k = i+j; k < 512; k++)
1350 if (data[k] != 'x')
1351 goto fail;
1352 continue;
1354 fail:
1355 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1360 static void
1361 test_bcopy (void)
1363 /* Much like memcpy. Berklix manual is silent about overlap, so
1364 don't test it. */
1365 it = "bcopy";
1366 (void) bcopy("abc", one, 4);
1367 equal(one, "abc", 1); /* Simple copy. */
1369 (void) strcpy(one, "abcdefgh");
1370 (void) bcopy("xyz", one+1, 2);
1371 equal(one, "axydefgh", 2); /* Basic test. */
1373 (void) strcpy(one, "abc");
1374 (void) bcopy("xyz", one, 0);
1375 equal(one, "abc", 3); /* Zero-length copy. */
1377 (void) strcpy(one, "hi there");
1378 (void) strcpy(two, "foo");
1379 (void) bcopy(one, two, 9);
1380 equal(two, "hi there", 4); /* Just paranoia. */
1381 equal(one, "hi there", 5); /* Stomped on source? */
1384 static void
1385 test_bzero (void)
1387 it = "bzero";
1388 (void) strcpy(one, "abcdef");
1389 bzero(one+2, 2);
1390 equal(one, "ab", 1); /* Basic test. */
1391 equal(one+3, "", 2);
1392 equal(one+4, "ef", 3);
1394 (void) strcpy(one, "abcdef");
1395 bzero(one+2, 0);
1396 equal(one, "abcdef", 4); /* Zero-length copy. */
1399 static void
1400 test_strndup (void)
1402 char *p, *q;
1403 it = "strndup";
1404 p = strndup("abcdef", 12);
1405 check(p != NULL, 1);
1406 if (p != NULL)
1408 equal(p, "abcdef", 2);
1409 q = strndup(p + 1, 2);
1410 check(q != NULL, 3);
1411 if (q != NULL)
1412 equal(q, "bc", 4);
1413 free (q);
1415 free (p);
1416 p = strndup("abc def", 3);
1417 check(p != NULL, 5);
1418 if (p != NULL)
1419 equal(p, "abc", 6);
1420 free (p);
1423 static void
1424 test_bcmp (void)
1426 it = "bcmp";
1427 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1428 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1429 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1430 check(bcmp("abce", "abcd", 4) != 0, 4);
1431 check(bcmp("alph", "beta", 4) != 0, 5);
1432 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1433 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1436 static void
1437 test_strerror (void)
1439 it = "strerror";
1440 check(strerror(EDOM) != 0, 1);
1441 check(strerror(ERANGE) != 0, 2);
1442 check(strerror(ENOENT) != 0, 3);
1445 static void
1446 test_strcasecmp (void)
1448 it = "strcasecmp";
1449 /* Note that the locale is "C". */
1450 check(strcasecmp("a", "a") == 0, 1);
1451 check(strcasecmp("a", "A") == 0, 2);
1452 check(strcasecmp("A", "a") == 0, 3);
1453 check(strcasecmp("a", "b") < 0, 4);
1454 check(strcasecmp("c", "b") > 0, 5);
1455 check(strcasecmp("abc", "AbC") == 0, 6);
1456 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1457 check(strcasecmp("", "0123456789") < 0, 8);
1458 check(strcasecmp("AbC", "") > 0, 9);
1459 check(strcasecmp("AbC", "A") > 0, 10);
1460 check(strcasecmp("AbC", "Ab") > 0, 11);
1461 check(strcasecmp("AbC", "ab") > 0, 12);
1464 static void
1465 test_strncasecmp (void)
1467 it = "strncasecmp";
1468 /* Note that the locale is "C". */
1469 check(strncasecmp("a", "a", 5) == 0, 1);
1470 check(strncasecmp("a", "A", 5) == 0, 2);
1471 check(strncasecmp("A", "a", 5) == 0, 3);
1472 check(strncasecmp("a", "b", 5) < 0, 4);
1473 check(strncasecmp("c", "b", 5) > 0, 5);
1474 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1475 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1476 check(strncasecmp("", "0123456789", 10) < 0, 8);
1477 check(strncasecmp("AbC", "", 5) > 0, 9);
1478 check(strncasecmp("AbC", "A", 5) > 0, 10);
1479 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1480 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1481 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1482 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1483 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1484 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1485 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1486 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1487 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1488 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1492 main (void)
1494 int status;
1496 /* Test strcmp first because we use it to test other things. */
1497 test_strcmp ();
1499 /* Test strcpy next because we need it to set up other tests. */
1500 test_strcpy ();
1502 /* A closely related function is stpcpy. */
1503 test_stpcpy ();
1505 /* stpncpy. */
1506 test_stpncpy ();
1508 /* strcat. */
1509 test_strcat ();
1511 /* strncat. */
1512 test_strncat ();
1514 /* strncmp. */
1515 test_strncmp ();
1517 /* strncpy. */
1518 test_strncpy ();
1520 /* strlen. */
1521 test_strlen ();
1523 /* strnlen. */
1524 test_strnlen ();
1526 /* strchr. */
1527 test_strchr ();
1529 /* strchrnul. */
1530 test_strchrnul ();
1532 /* rawmemchr. */
1533 test_rawmemchr ();
1535 /* index - just like strchr. */
1536 test_index ();
1538 /* strrchr. */
1539 test_strrchr ();
1541 /* memrchr. */
1542 test_memrchr ();
1544 /* rindex - just like strrchr. */
1545 test_rindex ();
1547 /* strpbrk - somewhat like strchr. */
1548 test_strpbrk ();
1550 /* strstr - somewhat like strchr. */
1551 test_strstr ();
1553 /* strspn. */
1554 test_strspn ();
1556 /* strcspn. */
1557 test_strcspn ();
1559 /* strtok - the hard one. */
1560 test_strtok ();
1562 /* strtok_r. */
1563 test_strtok_r ();
1565 /* strsep. */
1566 test_strsep ();
1568 /* memcmp. */
1569 test_memcmp ();
1571 /* memchr. */
1572 test_memchr ();
1574 /* memcpy - need not work for overlap. */
1575 test_memcpy ();
1577 /* memmove - must work on overlap. */
1578 test_memmove ();
1580 /* mempcpy */
1581 test_mempcpy ();
1583 /* memccpy. */
1584 test_memccpy ();
1586 /* memset. */
1587 test_memset ();
1589 /* bcopy. */
1590 test_bcopy ();
1592 /* bzero. */
1593 test_bzero ();
1595 /* bcmp - somewhat like memcmp. */
1596 test_bcmp ();
1598 /* strndup. */
1599 test_strndup ();
1601 /* strerror - VERY system-dependent. */
1602 test_strerror ();
1604 /* strcasecmp. Without locale dependencies. */
1605 test_strcasecmp ();
1607 /* strncasecmp. Without locale dependencies. */
1608 test_strncasecmp ();
1610 if (errors == 0)
1612 status = EXIT_SUCCESS;
1613 puts("No errors.");
1615 else
1617 status = EXIT_FAILURE;
1618 printf("%Zd errors.\n", errors);
1621 return status;