Fix strchr test
[platform/upstream/glibc.git] / string / tester.c
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.
5
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.
10
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.
15
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.  */
20
21 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE
23 #endif
24
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
30
31 #include <errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <strings.h>
36 #include <fcntl.h>
37
38
39 #define STREQ(a, b)     (strcmp((a), (b)) == 0)
40
41 const char *it = "<UNSET>";     /* Routine name for message routines. */
42 size_t errors = 0;
43
44 /* Complain if condition is not true.  */
45 static void
46 check (int thing, int number)
47 {
48   if (!thing)
49     {
50       printf ("%s flunked test %d\n", it, number);
51       ++errors;
52     }
53 }
54
55 /* Complain if first two args don't strcmp as equal.  */
56 static void
57 equal (const char *a, const char *b, int number)
58 {
59   check (a != NULL && b != NULL && STREQ (a, b), number);
60 }
61
62 char one[50];
63 char two[50];
64 char *cp;
65
66 static void
67 test_strcmp (void)
68 {
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);
79
80   {
81     char buf1[0x40], buf2[0x40];
82     int i, j;
83     for (i=0; i < 0x10; i++)
84       for (j = 0; j < 0x10; j++)
85         {
86           int k;
87           for (k = 0; k < 0x3f; k++)
88             {
89               buf1[k] = '0' ^ (k & 4);
90               buf2[k] = '4' ^ (k & 4);
91             }
92           buf1[i] = buf1[0x3f] = 0;
93           buf2[j] = buf2[0x3f] = 0;
94           for (k = 0; k < 0xf; k++)
95             {
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;
111             }
112         }
113   }
114 }
115
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)
127
128 static void
129 test_strcpy (void)
130 {
131   int i;
132   it = "strcpy";
133   check (strcpy (one, "abcd") == one, 1); /* Returned value. */
134   equal (one, "abcd", 2);               /* Basic test. */
135
136   (void) strcpy (one, "x");
137   equal (one, "x", 3);                  /* Writeover. */
138   equal (one+2, "cd", 4);               /* Wrote too much? */
139
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? */
144
145   (void) strcpy (one, "");
146   equal (one, "", 7);                   /* Boundary condition. */
147
148   for (i = 0; i < 16; i++)
149     {
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));
154     }
155
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);
173
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);
179 }
180
181 static void
182 test_stpcpy (void)
183 {
184   it = "stpcpy";
185   check ((stpcpy (one, "a") - one) == 1, 1);
186   equal (one, "a", 2);
187
188   check ((stpcpy (one, "ab") - one) == 2, 3);
189   equal (one, "ab", 4);
190
191   check ((stpcpy (one, "abc") - one) == 3, 5);
192   equal (one, "abc", 6);
193
194   check ((stpcpy (one, "abcd") - one) == 4, 7);
195   equal (one, "abcd", 8);
196
197   check ((stpcpy (one, "abcde") - one) == 5, 9);
198   equal (one, "abcde", 10);
199
200   check ((stpcpy (one, "abcdef") - one) == 6, 11);
201   equal (one, "abcdef", 12);
202
203   check ((stpcpy (one, "abcdefg") - one) == 7, 13);
204   equal (one, "abcdefg", 14);
205
206   check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
207   equal (one, "abcdefgh", 16);
208
209   check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
210   equal (one, "abcdefghi", 18);
211
212   check ((stpcpy (one, "x") - one) == 1, 19);
213   equal (one, "x", 20);                 /* Writeover. */
214   equal (one+2, "cdefghi", 21);         /* Wrote too much? */
215
216   check ((stpcpy (one, "xx") - one) == 2, 22);
217   equal (one, "xx", 23);                /* Writeover. */
218   equal (one+3, "defghi", 24);          /* Wrote too much? */
219
220   check ((stpcpy (one, "xxx") - one) == 3, 25);
221   equal (one, "xxx", 26);               /* Writeover. */
222   equal (one+4, "efghi", 27);           /* Wrote too much? */
223
224   check ((stpcpy (one, "xxxx") - one) == 4, 28);
225   equal (one, "xxxx", 29);              /* Writeover. */
226   equal (one+5, "fghi", 30);            /* Wrote too much? */
227
228   check ((stpcpy (one, "xxxxx") - one) == 5, 31);
229   equal (one, "xxxxx", 32);             /* Writeover. */
230   equal (one+6, "ghi", 33);             /* Wrote too much? */
231
232   check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
233   equal (one, "xxxxxx", 35);            /* Writeover. */
234   equal (one+7, "hi", 36);              /* Wrote too much? */
235
236   check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
237   equal (one, "xxxxxxx", 38);           /* Writeover. */
238   equal (one+8, "i", 39);               /* Wrote too much? */
239
240   check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
241   equal (one, "abc", 41);
242   equal (one + 4, "xxx", 42);
243
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);
261 }
262
263 static void
264 test_stpncpy (void)
265 {
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);
276 }
277
278 static void
279 test_strcat (void)
280 {
281   it = "strcat";
282   (void) strcpy (one, "ijk");
283   check (strcat (one, "lmn") == one, 1); /* Returned value. */
284   equal (one, "ijklmn", 2);             /* Basic test. */
285
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? */
290
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? */
296
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);
306
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)
313         {
314           size_t olderrors = errors;
315
316           memset (buf1, 'b', sizeof (buf1));
317
318           memset (buf1 + n2, 'a', n3);
319           buf1[n2 + n3] = '\0';
320           strcpy (buf2 + n1, "123");
321
322           check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
323           if (errors == olderrors)
324             for (size_t i = 0; i < sizeof (buf1); ++i)
325               {
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);
336
337                 if (errors != olderrors)
338                   {
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;
345                   }
346               }
347         }
348 }
349
350 static void
351 test_strncat (void)
352 {
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. */
359
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? */
364
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? */
370
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);
380
381   (void) strcpy (one, "ab");
382   (void) strncat (one, "cdef", 2);
383   equal (one, "abcd", 10);                      /* Count-limited. */
384
385   (void) strncat (one, "gh", 0);
386   equal (one, "abcd", 11);                      /* Zero count. */
387
388   (void) strncat (one, "gh", 2);
389   equal (one, "abcdgh", 12);            /* Count and length equal. */
390
391   (void) strncat (one, "ij", (size_t)-1);       /* set sign bit in count */
392   equal (one, "abcdghij", 13);
393
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)
401           {
402             size_t olderrors = errors;
403
404             memset (buf1, 'b', sizeof (buf1));
405
406             memset (buf1 + n2, 'a', n3);
407             buf1[n2 + n3] = '\0';
408             strcpy (buf2 + n1, "123");
409
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)
414                 {
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);
425
426                   if (errors != olderrors)
427                     {
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;
434                     }
435                 }
436           }
437 }
438
439 static void
440 test_strncmp (void)
441 {
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);
459 }
460
461 static void
462 test_strncpy (void)
463 {
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? */
468
469   (void) strcpy (one, "abcdefgh");
470   (void) strncpy (one, "xyz", 2);
471   equal (one, "xycdefgh", 3);                   /* Copy cut by count. */
472
473   (void) strcpy (one, "abcdefgh");
474   (void) strncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
475   equal (one, "xyzdefgh", 4);
476
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? */
481
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);
487
488   (void) strcpy (one, "abc");
489   (void) strncpy (one, "xyz", 0);               /* Zero-length copy. */
490   equal (one, "abc", 10);
491
492   (void) strncpy (one, "", 2);          /* Zero-length source. */
493   equal (one, "", 11);
494   equal (one+1, "", 12);
495   equal (one+2, "c", 13);
496
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? */
501 }
502
503 static void
504 test_strlen (void)
505 {
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. */
510   {
511     char buf[4096];
512     int i;
513     char *p;
514     for (i=0; i < 0x100; i++)
515       {
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);
520       }
521    }
522 }
523
524 static void
525 test_strnlen (void)
526 {
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. */
537
538   char buf[4096];
539   for (int i = 0; i < 0x100; ++i)
540     {
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);
545     }
546 }
547
548 static void
549 test_strchr (void)
550 {
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. */
563   {
564     char buf[4096];
565     int i;
566     char *p;
567     for (i=0; i < 0x100; i++)
568       {
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);
573       }
574    }
575 }
576
577 static void
578 test_strchrnul (void)
579 {
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. */
595   {
596     char buf[4096];
597     int i;
598     char *p;
599     for (i=0; i < 0x100; i++)
600       {
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);
607       }
608    }
609 }
610
611 static void
612 test_rawmemchr (void)
613 {
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. */
624   {
625     char buf[4096];
626     int i;
627     char *p;
628     for (i=0; i < 0x100; i++)
629       {
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);
634       }
635    }
636 }
637
638 static void
639 test_index (void)
640 {
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. */
653 }
654
655 static void
656 test_strrchr (void)
657 {
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. */
670   {
671     char buf[4096];
672     int i;
673     char *p;
674     for (i=0; i < 0x100; i++)
675       {
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);
680       }
681    }
682 }
683
684 static void
685 test_memrchr (void)
686 {
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. */
703
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: */
707   {
708     char buf[128 + sizeof(long)];
709     long align, len, i, pos;
710
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... */
715
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] = '-';
724         }
725       }
726     }
727   }
728 }
729
730 static void
731 test_rindex (void)
732 {
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. */
745 }
746
747 static void
748 test_strpbrk (void)
749 {
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. */
774 }
775
776 static void
777 test_strstr (void)
778 {
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. */
801 }
802
803 static void
804 test_strspn (void)
805 {
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. */
812 }
813
814 static void
815 test_strcspn (void)
816 {
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. */
823 }
824
825 static void
826 test_strtok (void)
827 {
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);
873 }
874
875 static void
876 test_strtok_r (void)
877 {
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);
938 }
939
940 static void
941 test_strsep (void)
942 {
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);
1006
1007   {
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);
1015   }
1016
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. */
1027
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. */
1038
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);
1046
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);
1053
1054   cp = strcpy(one, "ABC");              /* No token in string.  */
1055   equal(strsep(&cp, ","), "ABC", 81);
1056   check(cp == NULL, 82);
1057
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);
1064
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);
1071 }
1072
1073 static void
1074 test_memcmp (void)
1075 {
1076   int cnt = 1;
1077   char one[21];
1078   char two[21];
1079
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)
1095     {
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++);
1102     }
1103 }
1104
1105 static void
1106 test_memchr (void)
1107 {
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. */
1122
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: */
1126   {
1127     char buf[128 + sizeof(long)];
1128     long align, len, i, pos;
1129
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... */
1134         }
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] = '-';
1142         }
1143       }
1144     }
1145   }
1146 }
1147
1148 static void
1149 test_memcpy (void)
1150 {
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? */
1155
1156   (void) strcpy(one, "abcdefgh");
1157   (void) memcpy(one+1, "xyz", 2);
1158   equal(one, "axydefgh", 3);            /* Basic test. */
1159
1160   (void) strcpy(one, "abc");
1161   (void) memcpy(one, "xyz", 0);
1162   equal(one, "abc", 4);                 /* Zero-length copy. */
1163
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? */
1169
1170   for (i = 0; i < 16; i++)
1171     {
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));
1182     }
1183 }
1184
1185 static void
1186 test_mempcpy (void)
1187 {
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? */
1192
1193   (void) strcpy(one, "abcdefgh");
1194   (void) mempcpy(one+1, "xyz", 2);
1195   equal(one, "axydefgh", 3);            /* Basic test. */
1196
1197   (void) strcpy(one, "abc");
1198   (void) mempcpy(one, "xyz", 0);
1199   equal(one, "abc", 4);                 /* Zero-length copy. */
1200
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? */
1206
1207   for (i = 0; i < 16; i++)
1208     {
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));
1219     }
1220 }
1221
1222 static void
1223 test_memmove (void)
1224 {
1225   it = "memmove";
1226   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
1227   equal(one, "abc", 2);                 /* Did the copy go right? */
1228
1229   (void) strcpy(one, "abcdefgh");
1230   (void) memmove(one+1, "xyz", 2);
1231   equal(one, "axydefgh", 3);            /* Basic test. */
1232
1233   (void) strcpy(one, "abc");
1234   (void) memmove(one, "xyz", 0);
1235   equal(one, "abc", 4);                 /* Zero-length copy. */
1236
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? */
1242
1243   (void) strcpy(one, "abcdefgh");
1244   (void) memmove(one+1, one, 9);
1245   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
1246
1247   (void) strcpy(one, "abcdefgh");
1248   (void) memmove(one+1, one+2, 7);
1249   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
1250
1251   (void) strcpy(one, "abcdefgh");
1252   (void) memmove(one, one, 9);
1253   equal(one, "abcdefgh", 9);            /* 100% overlap. */
1254 }
1255
1256 static void
1257 test_memccpy (void)
1258 {
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? */
1266
1267   (void) strcpy(one, "abcdefgh");
1268   (void) memccpy(one+1, "xyz", 'q', 2);
1269   equal(one, "axydefgh", 3);            /* Basic test. */
1270
1271   (void) strcpy(one, "abc");
1272   (void) memccpy(one, "xyz", 'q', 0);
1273   equal(one, "abc", 4);                 /* Zero-length copy. */
1274
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? */
1280
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? */
1286
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);
1296 }
1297
1298 static void
1299 test_memset (void)
1300 {
1301   int i;
1302
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. */
1307
1308   (void) memset(one+2, 'y', 0);
1309   equal(one, "axxxefgh", 3);            /* Zero-length set. */
1310
1311   (void) memset(one+5, 0, 1);
1312   equal(one, "axxxe", 4);                       /* Zero fill. */
1313   equal(one+6, "gh", 5);                        /* And the leftover. */
1314
1315   (void) memset(one+2, 010045, 1);
1316   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
1317
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);
1322
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?  */
1326   {
1327     char data[512];
1328     int j;
1329     int k;
1330     int c;
1331
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++)
1338           {
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++)
1344               {
1345                 if (data[k] != c)
1346                   goto fail;
1347                 data[k] = 'x';
1348               }
1349             for (k = i+j; k < 512; k++)
1350               if (data[k] != 'x')
1351                 goto fail;
1352             continue;
1353
1354           fail:
1355             check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1356           }
1357   }
1358 }
1359
1360 static void
1361 test_bcopy (void)
1362 {
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. */
1368
1369   (void) strcpy(one, "abcdefgh");
1370   (void) bcopy("xyz", one+1, 2);
1371   equal(one, "axydefgh", 2);            /* Basic test. */
1372
1373   (void) strcpy(one, "abc");
1374   (void) bcopy("xyz", one, 0);
1375   equal(one, "abc", 3);                 /* Zero-length copy. */
1376
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? */
1382 }
1383
1384 static void
1385 test_bzero (void)
1386 {
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);
1393
1394   (void) strcpy(one, "abcdef");
1395   bzero(one+2, 0);
1396   equal(one, "abcdef", 4);              /* Zero-length copy. */
1397 }
1398
1399 static void
1400 test_strndup (void)
1401 {
1402   char *p, *q;
1403   it = "strndup";
1404   p = strndup("abcdef", 12);
1405   check(p != NULL, 1);
1406   if (p != NULL)
1407     {
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);
1414     }
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);
1421 }
1422
1423 static void
1424 test_bcmp (void)
1425 {
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. */
1434 }
1435
1436 static void
1437 test_strerror (void)
1438 {
1439   it = "strerror";
1440   check(strerror(EDOM) != 0, 1);
1441   check(strerror(ERANGE) != 0, 2);
1442   check(strerror(ENOENT) != 0, 3);
1443 }
1444
1445 static void
1446 test_strcasecmp (void)
1447 {
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);
1462 }
1463
1464 static void
1465 test_strncasecmp (void)
1466 {
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);
1489 }
1490
1491 int
1492 main (void)
1493 {
1494   int status;
1495
1496   /* Test strcmp first because we use it to test other things.  */
1497   test_strcmp ();
1498
1499   /* Test strcpy next because we need it to set up other tests.  */
1500   test_strcpy ();
1501
1502   /* A closely related function is stpcpy.  */
1503   test_stpcpy ();
1504
1505   /* stpncpy.  */
1506   test_stpncpy ();
1507
1508   /* strcat.  */
1509   test_strcat ();
1510
1511   /* strncat.  */
1512   test_strncat ();
1513
1514   /* strncmp.  */
1515   test_strncmp ();
1516
1517   /* strncpy.  */
1518   test_strncpy ();
1519
1520   /* strlen.  */
1521   test_strlen ();
1522
1523   /* strnlen.  */
1524   test_strnlen ();
1525
1526   /* strchr.  */
1527   test_strchr ();
1528
1529   /* strchrnul.  */
1530   test_strchrnul ();
1531
1532   /* rawmemchr.  */
1533   test_rawmemchr ();
1534
1535   /* index - just like strchr.  */
1536   test_index ();
1537
1538   /* strrchr.  */
1539   test_strrchr ();
1540
1541   /* memrchr.  */
1542   test_memrchr ();
1543
1544   /* rindex - just like strrchr.  */
1545   test_rindex ();
1546
1547   /* strpbrk - somewhat like strchr.  */
1548   test_strpbrk ();
1549
1550   /* strstr - somewhat like strchr.  */
1551   test_strstr ();
1552
1553   /* strspn.  */
1554   test_strspn ();
1555
1556   /* strcspn.  */
1557   test_strcspn ();
1558
1559   /* strtok - the hard one.  */
1560   test_strtok ();
1561
1562   /* strtok_r.  */
1563   test_strtok_r ();
1564
1565   /* strsep.  */
1566   test_strsep ();
1567
1568   /* memcmp.  */
1569   test_memcmp ();
1570
1571   /* memchr.  */
1572   test_memchr ();
1573
1574   /* memcpy - need not work for overlap.  */
1575   test_memcpy ();
1576
1577   /* memmove - must work on overlap.  */
1578   test_memmove ();
1579
1580   /* mempcpy */
1581   test_mempcpy ();
1582
1583   /* memccpy.  */
1584   test_memccpy ();
1585
1586   /* memset.  */
1587   test_memset ();
1588
1589   /* bcopy.  */
1590   test_bcopy ();
1591
1592   /* bzero.  */
1593   test_bzero ();
1594
1595   /* bcmp - somewhat like memcmp.  */
1596   test_bcmp ();
1597
1598   /* strndup.  */
1599   test_strndup ();
1600
1601   /* strerror - VERY system-dependent.  */
1602   test_strerror ();
1603
1604   /* strcasecmp.  Without locale dependencies.  */
1605   test_strcasecmp ();
1606
1607   /* strncasecmp.  Without locale dependencies.  */
1608   test_strncasecmp ();
1609
1610   if (errors == 0)
1611     {
1612       status = EXIT_SUCCESS;
1613       puts("No errors.");
1614     }
1615   else
1616     {
1617       status = EXIT_FAILURE;
1618       printf("%Zd errors.\n", errors);
1619     }
1620
1621   return status;
1622 }