OSDN Git Service

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