Define USE_NSCD.
[kopensolaris-gnu/glibc.git] / string / tester.c
1 /* Tester for string functions.
2    Copyright (C) 1995, 1996, 1997 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 Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    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    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 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 #ifndef HAVE_GNU_LD
38 #define _sys_nerr       sys_nerr
39 #define _sys_errlist    sys_errlist
40 #endif
41
42 #define STREQ(a, b)     (strcmp((a), (b)) == 0)
43
44 const char *it = "<UNSET>";     /* Routine name for message routines. */
45 size_t errors = 0;
46
47 /* Complain if condition is not true.  */
48 void
49 check (int thing, int number)
50 {
51   if (!thing)
52     {
53       printf("%s flunked test %d\n", it, number);
54       ++errors;
55     }
56 }
57
58 /* Complain if first two args don't strcmp as equal.  */
59 void
60 equal (const char *a, const char *b, int number)
61 {
62   check(a != NULL && b != NULL && STREQ (a, b), number);
63 }
64
65 char one[50];
66 char two[50];
67 char *cp;
68
69 void
70 test_strcmp (void)
71 {
72   it = "strcmp";
73   check (strcmp ("", "") == 0, 1);              /* Trivial case. */
74   check (strcmp ("a", "a") == 0, 2);            /* Identity. */
75   check (strcmp ("abc", "abc") == 0, 3);        /* Multicharacter. */
76   check (strcmp ("abc", "abcd") < 0, 4);        /* Length mismatches. */
77   check (strcmp ("abcd", "abc") > 0, 5);
78   check (strcmp ("abcd", "abce") < 0, 6);       /* Honest miscompares. */
79   check (strcmp ("abce", "abcd") > 0, 7);
80   check (strcmp ("a\203", "a") > 0, 8);         /* Tricky if char signed. */
81   check (strcmp ("a\203", "a\003") > 0, 9);
82
83   {
84     char buf1[0x40], buf2[0x40];
85     int i, j;
86     for (i=0; i < 0x10; i++)
87       for (j = 0; j < 0x10; j++)
88         {
89           int k;
90           for (k = 0; k < 0x3f; k++)
91             {
92               buf1[j] = '0' ^ (k & 4);
93               buf2[j] = '4' ^ (k & 4);
94             }
95           buf1[i] = buf1[0x3f] = 0;
96           buf2[j] = buf2[0x3f] = 0;
97           for (k = 0; k < 0xf; k++)
98             {
99               int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
100               check (strcmp (buf1+i,buf2+j) == 0, cnum);
101               buf1[i+k] = 'A' + i + k;
102               buf1[i+k+1] = 0;
103               check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
104               check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
105               buf2[j+k] = 'B' + i + k;
106               buf2[j+k+1] = 0;
107               check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
108               check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
109               buf2[j+k] = 'A' + i + k;
110               buf1[i] = 'A' + i + 0x80;
111               check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
112               check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
113               buf1[i] = 'A' + i;
114             }
115         }
116   }
117 }
118
119 void
120 test_strcpy (void)
121 {
122   it = "strcpy";
123   check (strcpy (one, "abcd") == one, 1); /* Returned value. */
124   equal (one, "abcd", 2);               /* Basic test. */
125
126   (void) strcpy (one, "x");
127   equal (one, "x", 3);                  /* Writeover. */
128   equal (one+2, "cd", 4);               /* Wrote too much? */
129
130   (void) strcpy (two, "hi there");
131   (void) strcpy (one, two);
132   equal (one, "hi there", 5);           /* Basic test encore. */
133   equal (two, "hi there", 6);           /* Stomped on source? */
134
135   (void) strcpy (one, "");
136   equal (one, "", 7);                   /* Boundary condition. */
137 }
138
139 void
140 test_stpcpy (void)
141 {
142   it = "stpcpy";
143   check ((stpcpy (one, "a") - one) == 1, 1);
144   equal (one, "a", 2);
145
146   check ((stpcpy (one, "ab") - one) == 2, 3);
147   equal (one, "ab", 4);
148
149   check ((stpcpy (one, "abc") - one) == 3, 5);
150   equal (one, "abc", 6);
151
152   check ((stpcpy (one, "abcd") - one) == 4, 7);
153   equal (one, "abcd", 8);
154
155   check ((stpcpy (one, "abcde") - one) == 5, 9);
156   equal (one, "abcde", 10);
157
158   check ((stpcpy (one, "abcdef") - one) == 6, 11);
159   equal (one, "abcdef", 12);
160
161   check ((stpcpy (one, "abcdefg") - one) == 7, 13);
162   equal (one, "abcdefg", 14);
163
164   check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
165   equal (one, "abcdefgh", 16);
166
167   check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
168   equal (one, "abcdefghi", 18);
169
170   check ((stpcpy (one, "x") - one) == 1, 19);
171   equal (one, "x", 20);                 /* Writeover. */
172   equal (one+2, "cdefghi", 21);         /* Wrote too much? */
173
174   check ((stpcpy (one, "xx") - one) == 2, 22);
175   equal (one, "xx", 23);                /* Writeover. */
176   equal (one+3, "defghi", 24);          /* Wrote too much? */
177
178   check ((stpcpy (one, "xxx") - one) == 3, 25);
179   equal (one, "xxx", 26);               /* Writeover. */
180   equal (one+4, "efghi", 27);           /* Wrote too much? */
181
182   check ((stpcpy (one, "xxxx") - one) == 4, 28);
183   equal (one, "xxxx", 29);              /* Writeover. */
184   equal (one+5, "fghi", 30);            /* Wrote too much? */
185
186   check ((stpcpy (one, "xxxxx") - one) == 5, 31);
187   equal (one, "xxxxx", 32);             /* Writeover. */
188   equal (one+6, "ghi", 33);             /* Wrote too much? */
189
190   check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
191   equal (one, "xxxxxx", 35);            /* Writeover. */
192   equal (one+7, "hi", 36);              /* Wrote too much? */
193
194   check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
195   equal (one, "xxxxxxx", 38);           /* Writeover. */
196   equal (one+8, "i", 39);               /* Wrote too much? */
197
198   check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
199   equal (one, "abc", 41);
200   equal (one + 4, "xxx", 42);
201 }
202
203 void
204 test_stpncpy (void)
205 {
206   it = "stpncpy";
207   memset (one, 'x', sizeof (one));
208   check (stpncpy (one, "abc", 2) == one + 2, 1);
209   check (stpncpy (one, "abc", 3) == one + 3, 2);
210   check (stpncpy (one, "abc", 4) == one + 3, 3);
211   check (one[3] == '\0' && one[4] == 'x', 4);
212   check (stpncpy (one, "abcd", 5) == one + 4, 5);
213   check (one[4] == '\0' && one[5] == 'x', 6);
214   check (stpncpy (one, "abcd", 6) == one + 4, 7);
215   check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
216 }
217
218 void
219 test_strcat (void)
220 {
221   it = "strcat";
222   (void) strcpy (one, "ijk");
223   check (strcat (one, "lmn") == one, 1); /* Returned value. */
224   equal (one, "ijklmn", 2);             /* Basic test. */
225
226   (void) strcpy (one, "x");
227   (void) strcat (one, "yz");
228   equal (one, "xyz", 3);                        /* Writeover. */
229   equal (one+4, "mn", 4);                       /* Wrote too much? */
230
231   (void) strcpy (one, "gh");
232   (void) strcpy (two, "ef");
233   (void) strcat (one, two);
234   equal (one, "ghef", 5);                       /* Basic test encore. */
235   equal (two, "ef", 6);                 /* Stomped on source? */
236
237   (void) strcpy (one, "");
238   (void) strcat (one, "");
239   equal (one, "", 7);                   /* Boundary conditions. */
240   (void) strcpy (one, "ab");
241   (void) strcat (one, "");
242   equal (one, "ab", 8);
243   (void) strcpy (one, "");
244   (void) strcat (one, "cd");
245   equal (one, "cd", 9);
246 }
247
248 void
249 test_strncat (void)
250 {
251   /* First test it as strcat, with big counts, then test the count
252      mechanism.  */
253   it = "strncat";
254   (void) strcpy (one, "ijk");
255   check (strncat (one, "lmn", 99) == one, 1);   /* Returned value. */
256   equal (one, "ijklmn", 2);             /* Basic test. */
257
258   (void) strcpy (one, "x");
259   (void) strncat (one, "yz", 99);
260   equal (one, "xyz", 3);                /* Writeover. */
261   equal (one+4, "mn", 4);               /* Wrote too much? */
262
263   (void) strcpy (one, "gh");
264   (void) strcpy (two, "ef");
265   (void) strncat (one, two, 99);
266   equal (one, "ghef", 5);                       /* Basic test encore. */
267   equal (two, "ef", 6);                 /* Stomped on source? */
268
269   (void) strcpy (one, "");
270   (void) strncat (one, "", 99);
271   equal (one, "", 7);                   /* Boundary conditions. */
272   (void) strcpy (one, "ab");
273   (void) strncat (one, "", 99);
274   equal (one, "ab", 8);
275   (void) strcpy (one, "");
276   (void) strncat (one, "cd", 99);
277   equal (one, "cd", 9);
278
279   (void) strcpy (one, "ab");
280   (void) strncat (one, "cdef", 2);
281   equal (one, "abcd", 10);                      /* Count-limited. */
282
283   (void) strncat (one, "gh", 0);
284   equal (one, "abcd", 11);                      /* Zero count. */
285
286   (void) strncat (one, "gh", 2);
287   equal (one, "abcdgh", 12);            /* Count and length equal. */
288 }
289
290 void
291 test_strncmp (void)
292 {
293   /* First test as strcmp with big counts, then test count code.  */
294   it = "strncmp";
295   check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
296   check (strncmp ("a", "a", 99) == 0, 2);       /* Identity. */
297   check (strncmp ("abc", "abc", 99) == 0, 3);   /* Multicharacter. */
298   check (strncmp ("abc", "abcd", 99) < 0, 4);   /* Length unequal. */
299   check (strncmp ("abcd", "abc", 99) > 0, 5);
300   check (strncmp ("abcd", "abce", 99) < 0, 6);  /* Honestly unequal. */
301   check (strncmp ("abce", "abcd", 99) > 0, 7);
302   check (strncmp ("a\203", "a", 2) > 0, 8);     /* Tricky if '\203' < 0 */
303   check (strncmp ("a\203", "a\003", 2) > 0, 9);
304   check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
305   check (strncmp ("abce", "abc", 3) == 0, 11);  /* Count == length. */
306   check (strncmp ("abcd", "abce", 4) < 0, 12);  /* Nudging limit. */
307   check (strncmp ("abc", "def", 0) == 0, 13);   /* Zero count. */
308 }
309
310 void
311 test_strncpy (void)
312 {
313   /* Testing is a bit different because of odd semantics.  */
314   it = "strncpy";
315   check (strncpy (one, "abc", 4) == one, 1);    /* Returned value. */
316   equal (one, "abc", 2);                        /* Did the copy go right? */
317
318   (void) strcpy (one, "abcdefgh");
319   (void) strncpy (one, "xyz", 2);
320   equal (one, "xycdefgh", 3);                   /* Copy cut by count. */
321
322   (void) strcpy (one, "abcdefgh");
323   (void) strncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
324   equal (one, "xyzdefgh", 4);
325
326   (void) strcpy (one, "abcdefgh");
327   (void) strncpy (one, "xyz", 4);               /* Copy just includes NUL. */
328   equal (one, "xyz", 5);
329   equal (one+4, "efgh", 6);                     /* Wrote too much? */
330
331   (void) strcpy (one, "abcdefgh");
332   (void) strncpy (one, "xyz", 5);               /* Copy includes padding. */
333   equal (one, "xyz", 7);
334   equal (one+4, "", 8);
335   equal (one+5, "fgh", 9);
336
337   (void) strcpy (one, "abc");
338   (void) strncpy (one, "xyz", 0);               /* Zero-length copy. */
339   equal (one, "abc", 10);
340
341   (void) strncpy (one, "", 2);          /* Zero-length source. */
342   equal (one, "", 11);
343   equal (one+1, "", 12);
344   equal (one+2, "c", 13);
345
346   (void) strcpy (one, "hi there");
347   (void) strncpy (two, one, 9);
348   equal (two, "hi there", 14);          /* Just paranoia. */
349   equal (one, "hi there", 15);          /* Stomped on source? */
350 }
351
352 void
353 test_strlen (void)
354 {
355   it = "strlen";
356   check (strlen ("") == 0, 1);          /* Empty. */
357   check (strlen ("a") == 1, 2);         /* Single char. */
358   check (strlen ("abcd") == 4, 3);      /* Multiple chars. */
359   {
360     char buf[4096];
361     int i;
362     char *p;
363     for (i=0; i < 0x100; i++)
364       {
365         p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
366         strcpy (p, "OK");
367         strcpy (p+3, "BAD/WRONG");
368         check (strlen (p) == 2, 4+i);
369       }
370    }
371 }
372
373 void
374 test_strchr (void)
375 {
376   it = "strchr";
377   check (strchr ("abcd", 'z') == NULL, 1);      /* Not found. */
378   (void) strcpy (one, "abcd");
379   check (strchr (one, 'c') == one+2, 2);        /* Basic test. */
380   check (strchr (one, 'd') == one+3, 3);        /* End of string. */
381   check (strchr (one, 'a') == one, 4);          /* Beginning. */
382   check (strchr (one, '\0') == one+4, 5);       /* Finding NUL. */
383   (void) strcpy (one, "ababa");
384   check (strchr (one, 'b') == one+1, 6);        /* Finding first. */
385   (void) strcpy (one, "");
386   check (strchr (one, 'b') == NULL, 7);         /* Empty string. */
387   check (strchr (one, '\0') == one, 8);         /* NUL in empty string. */
388   {
389     char buf[4096];
390     int i;
391     char *p;
392     for (i=0; i < 0x100; i++)
393       {
394         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
395         strcpy (p, "OK");
396         strcpy (p+3, "BAD/WRONG");
397         check (strchr (p, '/') == NULL, 9+i);
398       }
399    }
400 }
401
402 void
403 test_index (void)
404 {
405   it = "index";
406   check (index ("abcd", 'z') == NULL, 1);       /* Not found. */
407   (void) strcpy (one, "abcd");
408   check (index (one, 'c') == one+2, 2); /* Basic test. */
409   check (index (one, 'd') == one+3, 3); /* End of string. */
410   check (index (one, 'a') == one, 4);   /* Beginning. */
411   check (index (one, '\0') == one+4, 5);        /* Finding NUL. */
412   (void) strcpy (one, "ababa");
413   check (index (one, 'b') == one+1, 6); /* Finding first. */
414   (void) strcpy (one, "");
415   check (index (one, 'b') == NULL, 7);  /* Empty string. */
416   check (index (one, '\0') == one, 8);  /* NUL in empty string. */
417 }
418
419 void
420 test_strrchr (void)
421 {
422   it = "strrchr";
423   check (strrchr ("abcd", 'z') == NULL, 1);     /* Not found. */
424   (void) strcpy (one, "abcd");
425   check (strrchr (one, 'c') == one+2, 2);       /* Basic test. */
426   check (strrchr (one, 'd') == one+3, 3);       /* End of string. */
427   check (strrchr (one, 'a') == one, 4);         /* Beginning. */
428   check (strrchr (one, '\0') == one+4, 5);      /* Finding NUL. */
429   (void) strcpy (one, "ababa");
430   check (strrchr (one, 'b') == one+3, 6);       /* Finding last. */
431   (void) strcpy (one, "");
432   check (strrchr (one, 'b') == NULL, 7);        /* Empty string. */
433   check (strrchr (one, '\0') == one, 8);        /* NUL in empty string. */
434   {
435     char buf[4096];
436     int i;
437     char *p;
438     for (i=0; i < 0x100; i++)
439       {
440         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
441         strcpy (p, "OK");
442         strcpy (p+3, "BAD/WRONG");
443         check (strrchr (p, '/') == NULL, 9+i);
444       }
445    }
446 }
447
448 void
449 test_rindex (void)
450 {
451   it = "rindex";
452   check (rindex ("abcd", 'z') == NULL, 1);      /* Not found. */
453   (void) strcpy (one, "abcd");
454   check (rindex (one, 'c') == one+2, 2);        /* Basic test. */
455   check (rindex (one, 'd') == one+3, 3);        /* End of string. */
456   check (rindex (one, 'a') == one, 4);  /* Beginning. */
457   check (rindex (one, '\0') == one+4, 5);       /* Finding NUL. */
458   (void) strcpy (one, "ababa");
459   check (rindex (one, 'b') == one+3, 6);        /* Finding last. */
460   (void) strcpy (one, "");
461   check (rindex (one, 'b') == NULL, 7); /* Empty string. */
462   check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
463 }
464
465 void
466 test_strpbrk (void)
467 {
468   it = "strpbrk";
469   check(strpbrk("abcd", "z") == NULL, 1);       /* Not found. */
470   (void) strcpy(one, "abcd");
471   check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
472   check(strpbrk(one, "d") == one+3, 3); /* End of string. */
473   check(strpbrk(one, "a") == one, 4);   /* Beginning. */
474   check(strpbrk(one, "") == NULL, 5);   /* Empty search list. */
475   check(strpbrk(one, "cb") == one+1, 6);        /* Multiple search. */
476   (void) strcpy(one, "abcabdea");
477   check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
478   check(strpbrk(one, "cb") == one+1, 8);        /* With multiple search. */
479   check(strpbrk(one, "db") == one+1, 9);        /* Another variant. */
480   (void) strcpy(one, "");
481   check(strpbrk(one, "bc") == NULL, 10);        /* Empty string. */
482   check(strpbrk(one, "") == NULL, 11);  /* Both strings empty. */
483 }
484
485 void
486 test_strstr (void)
487 {
488   it = "strstr";
489   check(strstr("abcd", "z") == NULL, 1);        /* Not found. */
490   check(strstr("abcd", "abx") == NULL, 2);      /* Dead end. */
491   (void) strcpy(one, "abcd");
492   check(strstr(one, "c") == one+2, 3);  /* Basic test. */
493   check(strstr(one, "bc") == one+1, 4); /* Multichar. */
494   check(strstr(one, "d") == one+3, 5);  /* End of string. */
495   check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
496   check(strstr(one, "abc") == one, 7);  /* Beginning. */
497   check(strstr(one, "abcd") == one, 8); /* Exact match. */
498   check(strstr(one, "abcde") == NULL, 9);       /* Too long. */
499   check(strstr(one, "de") == NULL, 10); /* Past end. */
500   check(strstr(one, "") == one, 11);    /* Finding empty. */
501   (void) strcpy(one, "ababa");
502   check(strstr(one, "ba") == one+1, 12);        /* Finding first. */
503   (void) strcpy(one, "");
504   check(strstr(one, "b") == NULL, 13);  /* Empty string. */
505   check(strstr(one, "") == one, 14);    /* Empty in empty string. */
506   (void) strcpy(one, "bcbca");
507   check(strstr(one, "bca") == one+2, 15);       /* False start. */
508   (void) strcpy(one, "bbbcabbca");
509   check(strstr(one, "bbca") == one+1, 16);      /* With overlap. */
510 }
511
512 void
513 test_strspn (void)
514 {
515   it = "strspn";
516   check(strspn("abcba", "abc") == 5, 1);        /* Whole string. */
517   check(strspn("abcba", "ab") == 2, 2); /* Partial. */
518   check(strspn("abc", "qx") == 0, 3);   /* None. */
519   check(strspn("", "ab") == 0, 4);      /* Null string. */
520   check(strspn("abc", "") == 0, 5);     /* Null search list. */
521 }
522
523 void
524 test_strcspn (void)
525 {
526   it = "strcspn";
527   check(strcspn("abcba", "qx") == 5, 1);        /* Whole string. */
528   check(strcspn("abcba", "cx") == 2, 2);        /* Partial. */
529   check(strcspn("abc", "abc") == 0, 3); /* None. */
530   check(strcspn("", "ab") == 0, 4);     /* Null string. */
531   check(strcspn("abc", "") == 3, 5);    /* Null search list. */
532 }
533
534 void
535 test_strtok (void)
536 {
537   it = "strtok";
538   (void) strcpy(one, "first, second, third");
539   equal(strtok(one, ", "), "first", 1); /* Basic test. */
540   equal(one, "first", 2);
541   equal(strtok((char *)NULL, ", "), "second", 3);
542   equal(strtok((char *)NULL, ", "), "third", 4);
543   check(strtok((char *)NULL, ", ") == NULL, 5);
544   (void) strcpy(one, ", first, ");
545   equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
546   check(strtok((char *)NULL, ", ") == NULL, 7);
547   (void) strcpy(one, "1a, 1b; 2a, 2b");
548   equal(strtok(one, ", "), "1a", 8);    /* Changing delim lists. */
549   equal(strtok((char *)NULL, "; "), "1b", 9);
550   equal(strtok((char *)NULL, ", "), "2a", 10);
551   (void) strcpy(two, "x-y");
552   equal(strtok(two, "-"), "x", 11);     /* New string before done. */
553   equal(strtok((char *)NULL, "-"), "y", 12);
554   check(strtok((char *)NULL, "-") == NULL, 13);
555   (void) strcpy(one, "a,b, c,, ,d");
556   equal(strtok(one, ", "), "a", 14);    /* Different separators. */
557   equal(strtok((char *)NULL, ", "), "b", 15);
558   equal(strtok((char *)NULL, " ,"), "c", 16);   /* Permute list too. */
559   equal(strtok((char *)NULL, " ,"), "d", 17);
560   check(strtok((char *)NULL, ", ") == NULL, 18);
561   check(strtok((char *)NULL, ", ") == NULL, 19);        /* Persistence. */
562   (void) strcpy(one, ", ");
563   check(strtok(one, ", ") == NULL, 20); /* No tokens. */
564   (void) strcpy(one, "");
565   check(strtok(one, ", ") == NULL, 21); /* Empty string. */
566   (void) strcpy(one, "abc");
567   equal(strtok(one, ", "), "abc", 22);  /* No delimiters. */
568   check(strtok((char *)NULL, ", ") == NULL, 23);
569   (void) strcpy(one, "abc");
570   equal(strtok(one, ""), "abc", 24);    /* Empty delimiter list. */
571   check(strtok((char *)NULL, "") == NULL, 25);
572   (void) strcpy(one, "abcdefgh");
573   (void) strcpy(one, "a,b,c");
574   equal(strtok(one, ","), "a", 26);     /* Basics again... */
575   equal(strtok((char *)NULL, ","), "b", 27);
576   equal(strtok((char *)NULL, ","), "c", 28);
577   check(strtok((char *)NULL, ",") == NULL, 29);
578   equal(one+6, "gh", 30);                       /* Stomped past end? */
579   equal(one, "a", 31);                  /* Stomped old tokens? */
580   equal(one+2, "b", 32);
581   equal(one+4, "c", 33);
582 }
583
584 void
585 test_strtok_r (void)
586 {
587   it = "strtok_r";
588   (void) strcpy(one, "first, second, third");
589   equal(strtok_r(one, ", ", &cp), "first", 1);  /* Basic test. */
590   equal(one, "first", 2);
591   equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
592   equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
593   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
594   (void) strcpy(one, ", first, ");
595   equal(strtok_r(one, ", ", &cp), "first", 6);  /* Extra delims, 1 tok. */
596   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
597   (void) strcpy(one, "1a, 1b; 2a, 2b");
598   equal(strtok_r(one, ", ", &cp), "1a", 8);     /* Changing delim lists. */
599   equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
600   equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
601   (void) strcpy(two, "x-y");
602   equal(strtok_r(two, "-", &cp), "x", 11);      /* New string before done. */
603   equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
604   check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
605   (void) strcpy(one, "a,b, c,, ,d");
606   equal(strtok_r(one, ", ", &cp), "a", 14);     /* Different separators. */
607   equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
608   equal(strtok_r((char *)NULL, " ,", &cp), "c", 16);    /* Permute list too. */
609   equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
610   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
611   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
612   (void) strcpy(one, ", ");
613   check(strtok_r(one, ", ", &cp) == NULL, 20);  /* No tokens. */
614   (void) strcpy(one, "");
615   check(strtok_r(one, ", ", &cp) == NULL, 21);  /* Empty string. */
616   (void) strcpy(one, "abc");
617   equal(strtok_r(one, ", ", &cp), "abc", 22);   /* No delimiters. */
618   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23);
619   (void) strcpy(one, "abc");
620   equal(strtok_r(one, "", &cp), "abc", 24);     /* Empty delimiter list. */
621   check(strtok_r((char *)NULL, "", &cp) == NULL, 25);
622   (void) strcpy(one, "abcdefgh");
623   (void) strcpy(one, "a,b,c");
624   equal(strtok_r(one, ",", &cp), "a", 26);      /* Basics again... */
625   equal(strtok_r((char *)NULL, ",", &cp), "b", 27);
626   equal(strtok_r((char *)NULL, ",", &cp), "c", 28);
627   check(strtok_r((char *)NULL, ",", &cp) == NULL, 29);
628   equal(one+6, "gh", 30);                       /* Stomped past end? */
629   equal(one, "a", 31);                  /* Stomped old tokens? */
630   equal(one+2, "b", 32);
631   equal(one+4, "c", 33);
632 }
633
634 void
635 test_strsep (void)
636 {
637   it = "strsep";
638   cp = strcpy(one, "first, second, third");
639   equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
640   equal(one, "first", 2);
641   equal(strsep(&cp, ", "), "", 3);
642   equal(strsep(&cp, ", "), "second", 4);
643   equal(strsep(&cp, ", "), "", 5);
644   equal(strsep(&cp, ", "), "third", 6);
645   check(strsep(&cp, ", ") == NULL, 7);
646   cp = strcpy(one, ", first, ");
647   equal(strsep(&cp, ", "), "", 8);
648   equal(strsep(&cp, ", "), "", 9);
649   equal(strsep(&cp, ", "), "first", 10);        /* Extra delims, 1 tok. */
650   equal(strsep(&cp, ", "), "", 11);
651   check(strsep(&cp, ", ") == NULL, 12);
652   cp = strcpy(one, "1a, 1b; 2a, 2b");
653   equal(strsep(&cp, ", "), "1a", 13);   /* Changing delim lists. */
654   equal(strsep(&cp, ", "), "", 14);
655   equal(strsep(&cp, "; "), "1b", 15);
656   equal(strsep(&cp, ", "), "", 16);
657   equal(strsep(&cp, ", "), "2a", 17);
658   cp = strcpy(two, "x-y");
659   equal(strsep(&cp, "-"), "x", 18);     /* New string before done. */
660   equal(strsep(&cp, "-"), "y", 19);
661   check(strsep(&cp, "-") == NULL, 20);
662   cp = strcpy(one, "a,b, c,, ,d");
663   equal(strsep(&cp, ", "), "a", 21);    /* Different separators. */
664   equal(strsep(&cp, ", "), "b", 22);
665   equal(strsep(&cp, " ,"), "", 23);
666   equal(strsep(&cp, " ,"), "c", 24);    /* Permute list too. */
667   equal(strsep(&cp, " ,"), "", 25);
668   equal(strsep(&cp, " ,"), "", 26);
669   equal(strsep(&cp, " ,"), "", 27);
670   equal(strsep(&cp, " ,"), "d", 28);
671   check(strsep(&cp, ", ") == NULL, 29);
672   check(strsep(&cp, ", ") == NULL, 30); /* Persistence. */
673   cp = strcpy(one, ", ");
674   equal(strsep(&cp, ", "), "", 31);
675   equal(strsep(&cp, ", "), "", 32);
676   check(strsep(&cp, ", ") == NULL, 33); /* No tokens. */
677   cp = strcpy(one, "");
678   check(strsep(&cp, ", ") == NULL, 34); /* Empty string. */
679   cp = strcpy(one, "abc");
680   equal(strsep(&cp, ", "), "abc", 35);  /* No delimiters. */
681   check(strsep(&cp, ", ") == NULL, 36);
682   cp = strcpy(one, "abc");
683   equal(strsep(&cp, ""), "abc", 37);    /* Empty delimiter list. */
684   check(strsep(&cp, "") == NULL, 38);
685   (void) strcpy(one, "abcdefgh");
686   cp = strcpy(one, "a,b,c");
687   equal(strsep(&cp, ","), "a", 39);     /* Basics again... */
688   equal(strsep(&cp, ","), "b", 40);
689   equal(strsep(&cp, ","), "c", 41);
690   check(strsep(&cp, ",") == NULL, 42);
691   equal(one+6, "gh", 43);               /* Stomped past end? */
692   equal(one, "a", 44);                  /* Stomped old tokens? */
693   equal(one+2, "b", 45);
694   equal(one+4, "c", 46);
695
696   {
697     char text[] = "This,is,a,test";
698     char *list = strdupa (text);
699     equal (strsep (&list, ","), "This", 47);
700     equal (strsep (&list, ","), "is", 48);
701     equal (strsep (&list, ","), "a", 49);
702     equal (strsep (&list, ","), "test", 50);
703     check (strsep (&list, ",") == NULL, 51);
704   }
705 }
706
707 void
708 test_memcmp (void)
709 {
710   it = "memcmp";
711   check(memcmp("a", "a", 1) == 0, 1);           /* Identity. */
712   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
713   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
714   check(memcmp("abce", "abcd", 4) > 0, 4);
715   check(memcmp("alph", "beta", 4) < 0, 5);
716   check(memcmp("a\203", "a\003", 2) > 0, 6);
717   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
718   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
719 }
720
721 void
722 test_memchr (void)
723 {
724   it = "memchr";
725   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
726   (void) strcpy(one, "abcd");
727   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
728   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
729   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
730   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
731   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
732   (void) strcpy(one, "ababa");
733   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
734   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
735   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
736   (void) strcpy(one, "a\203b");
737   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
738
739   /* now test all possible alignment and length combinations to catch
740      bugs due to unrolled loops (assuming unrolling is limited to no
741      more than 128 byte chunks: */
742   {
743     char buf[128 + sizeof(long)];
744     long align, len, i, pos;
745
746     for (align = 0; align < (long) sizeof(long); ++align) {
747       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
748         for (i = 0; i < len; ++i) {
749           buf[align + i] = 'x';         /* don't depend on memset... */
750         }
751         for (pos = 0; pos < len; ++pos) {
752 #if 0
753           printf("align %d, len %d, pos %d\n", align, len, pos);
754 #endif
755           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
756           check(memchr(buf + align, 'x', pos) == NULL, 11);
757           buf[align + pos] = '-';
758         }
759       }
760     }
761   }
762 }
763
764 void
765 test_memcpy (void)
766 {
767   it = "memcpy";
768   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
769   equal(one, "abc", 2);                 /* Did the copy go right? */
770
771   (void) strcpy(one, "abcdefgh");
772   (void) memcpy(one+1, "xyz", 2);
773   equal(one, "axydefgh", 3);            /* Basic test. */
774
775   (void) strcpy(one, "abc");
776   (void) memcpy(one, "xyz", 0);
777   equal(one, "abc", 4);                 /* Zero-length copy. */
778
779   (void) strcpy(one, "hi there");
780   (void) strcpy(two, "foo");
781   (void) memcpy(two, one, 9);
782   equal(two, "hi there", 5);            /* Just paranoia. */
783   equal(one, "hi there", 6);            /* Stomped on source? */
784 }
785
786 void
787 test_memmove (void)
788 {
789   it = "memmove";
790   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
791   equal(one, "abc", 2);                 /* Did the copy go right? */
792
793   (void) strcpy(one, "abcdefgh");
794   (void) memmove(one+1, "xyz", 2);
795   equal(one, "axydefgh", 3);            /* Basic test. */
796
797   (void) strcpy(one, "abc");
798   (void) memmove(one, "xyz", 0);
799   equal(one, "abc", 4);                 /* Zero-length copy. */
800
801   (void) strcpy(one, "hi there");
802   (void) strcpy(two, "foo");
803   (void) memmove(two, one, 9);
804   equal(two, "hi there", 5);            /* Just paranoia. */
805   equal(one, "hi there", 6);            /* Stomped on source? */
806
807   (void) strcpy(one, "abcdefgh");
808   (void) memmove(one+1, one, 9);
809   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
810
811   (void) strcpy(one, "abcdefgh");
812   (void) memmove(one+1, one+2, 7);
813   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
814
815   (void) strcpy(one, "abcdefgh");
816   (void) memmove(one, one, 9);
817   equal(one, "abcdefgh", 9);            /* 100% overlap. */
818 }
819
820 void
821 test_memccpy (void)
822 {
823   /* First test like memcpy, then the search part The SVID, the only
824      place where memccpy is mentioned, says overlap might fail, so we
825      don't try it.  Besides, it's hard to see the rationale for a
826      non-left-to-right memccpy.  */
827   it = "memccpy";
828   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
829   equal(one, "abc", 2);                 /* Did the copy go right? */
830
831   (void) strcpy(one, "abcdefgh");
832   (void) memccpy(one+1, "xyz", 'q', 2);
833   equal(one, "axydefgh", 3);            /* Basic test. */
834
835   (void) strcpy(one, "abc");
836   (void) memccpy(one, "xyz", 'q', 0);
837   equal(one, "abc", 4);                 /* Zero-length copy. */
838
839   (void) strcpy(one, "hi there");
840   (void) strcpy(two, "foo");
841   (void) memccpy(two, one, 'q', 9);
842   equal(two, "hi there", 5);            /* Just paranoia. */
843   equal(one, "hi there", 6);            /* Stomped on source? */
844
845   (void) strcpy(one, "abcdefgh");
846   (void) strcpy(two, "horsefeathers");
847   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
848   equal(one, "abcdefgh", 8);            /* Source intact? */
849   equal(two, "abcdefeathers", 9);               /* Copy correct? */
850
851   (void) strcpy(one, "abcd");
852   (void) strcpy(two, "bumblebee");
853   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
854   equal(two, "aumblebee", 11);
855   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
856   equal(two, "abcdlebee", 13);
857   (void) strcpy(one, "xyz");
858   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
859   equal(two, "xbcdlebee", 15);
860 }
861
862 void
863 test_memset (void)
864 {
865   it = "memset";
866   (void) strcpy(one, "abcdefgh");
867   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
868   equal(one, "axxxefgh", 2);            /* Basic test. */
869
870   (void) memset(one+2, 'y', 0);
871   equal(one, "axxxefgh", 3);            /* Zero-length set. */
872
873   (void) memset(one+5, 0, 1);
874   equal(one, "axxxe", 4);                       /* Zero fill. */
875   equal(one+6, "gh", 5);                        /* And the leftover. */
876
877   (void) memset(one+2, 010045, 1);
878   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
879
880   /* Test for more complex versions of memset, for all alignments and
881      lengths up to 256. This test takes a little while, perhaps it should
882      be made weaker? */
883   {
884     char data[512];
885     int i;
886     int j;
887     int k;
888     int c;
889
890     for (i = 0; i < 512; i++)
891       data[i] = 'x';
892     for (c = 0; c <= 'y'; c += 'y')  /* check for memset(,0,) and
893                                         memset(,'y',) */
894       for (j = 0; j < 256; j++)
895         for (i = 0; i < 256; i++)
896           {
897             memset(data+i,c,j);
898             for (k = 0; k < i; k++)
899               if (data[k] != 'x')
900                 goto fail;
901             for (k = i; k < i+j; k++)
902               {
903                 if (data[k] != c)
904                   goto fail;
905                 data[k] = 'x';
906               }
907             for (k = i+j; k < 512; k++)
908               if (data[k] != 'x')
909                 goto fail;
910             continue;
911
912           fail:
913             check(0,7+i+j*256+(c != 0)*256*256);
914           }
915   }
916 }
917
918 void
919 test_bcopy (void)
920 {
921   /* Much like memcpy.  Berklix manual is silent about overlap, so
922      don't test it.  */
923   it = "bcopy";
924   (void) bcopy("abc", one, 4);
925   equal(one, "abc", 1);                 /* Simple copy. */
926
927   (void) strcpy(one, "abcdefgh");
928   (void) bcopy("xyz", one+1, 2);
929   equal(one, "axydefgh", 2);            /* Basic test. */
930
931   (void) strcpy(one, "abc");
932   (void) bcopy("xyz", one, 0);
933   equal(one, "abc", 3);                 /* Zero-length copy. */
934
935   (void) strcpy(one, "hi there");
936   (void) strcpy(two, "foo");
937   (void) bcopy(one, two, 9);
938   equal(two, "hi there", 4);            /* Just paranoia. */
939   equal(one, "hi there", 5);            /* Stomped on source? */
940 }
941
942 void
943 test_bzero (void)
944 {
945   it = "bzero";
946   (void) strcpy(one, "abcdef");
947   bzero(one+2, 2);
948   equal(one, "ab", 1);                  /* Basic test. */
949   equal(one+3, "", 2);
950   equal(one+4, "ef", 3);
951
952   (void) strcpy(one, "abcdef");
953   bzero(one+2, 0);
954   equal(one, "abcdef", 4);              /* Zero-length copy. */
955 }
956
957 void
958 test_bcmp (void)
959 {
960   it = "bcmp";
961   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
962   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
963   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
964   check(bcmp("abce", "abcd", 4) != 0, 4);
965   check(bcmp("alph", "beta", 4) != 0, 5);
966   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
967   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
968 }
969
970 void
971 test_strerror (void)
972 {
973   int f;
974   it = "strerror";
975   f = __open("/", O_WRONLY);    /* Should always fail. */
976   check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
977   equal(strerror(errno), _sys_errlist[errno], 2);
978 }
979
980 int
981 main (void)
982 {
983   int status;
984
985   /* Test strcmp first because we use it to test other things.  */
986   test_strcmp ();
987
988   /* Test strcpy next because we need it to set up other tests.  */
989   test_strcpy ();
990
991   /* A closely related function is stpcpy.  */
992   test_stpcpy ();
993
994   /* stpncpy.  */
995   test_stpncpy ();
996
997   /* strcat.  */
998   test_strcat ();
999
1000   /* strncat.  */
1001   test_strncat ();
1002
1003   /* strncmp.  */
1004   test_strncmp ();
1005
1006   /* strncpy.  */
1007   test_strncpy ();
1008
1009   /* strlen.  */
1010   test_strlen ();
1011
1012   /* strchr.  */
1013   test_strchr ();
1014
1015   /* index - just like strchr.  */
1016   test_index ();
1017
1018   /* strrchr.  */
1019   test_strrchr ();
1020
1021   /* rindex - just like strrchr.  */
1022   test_rindex ();
1023
1024   /* strpbrk - somewhat like strchr.  */
1025   test_strpbrk ();
1026
1027   /* strstr - somewhat like strchr.  */
1028   test_strstr ();
1029
1030   /* strspn.  */
1031   test_strspn ();
1032
1033   /* strcspn.  */
1034   test_strcspn ();
1035
1036   /* strtok - the hard one.  */
1037   test_strtok ();
1038
1039   /* strtok_r.  */
1040   test_strtok_r ();
1041
1042   /* strsep.  */
1043   test_strsep ();
1044
1045   /* memcmp.  */
1046   test_memcmp ();
1047
1048   /* memchr.  */
1049   test_memchr ();
1050
1051   /* memcpy - need not work for overlap.  */
1052   test_memcpy ();
1053
1054   /* memmove - must work on overlap.  */
1055   test_memmove ();
1056
1057   /* memccpy.  */
1058   test_memccpy ();
1059
1060   /* memset.  */
1061   test_memset ();
1062
1063   /* bcopy.  */
1064   test_bcopy ();
1065
1066   /* bzero.  */
1067   test_bzero ();
1068
1069   /* bcmp - somewhat like memcmp.  */
1070   test_bcmp ();
1071
1072   /* strerror - VERY system-dependent.  */
1073   test_strerror ();
1074
1075
1076   if (errors == 0)
1077     {
1078       status = EXIT_SUCCESS;
1079       puts("No errors.");
1080     }
1081   else
1082     {
1083       status = EXIT_FAILURE;
1084       printf("%Zd errors.\n", errors);
1085     }
1086   exit(status);
1087 }