OSDN Git Service

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