Update.
[platform/upstream/glibc.git] / string / tester.c
1 /* Tester for string functions.
2    Copyright (C) 1995, 1996, 1997, 1998 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   (void) strcpy(one, "");
483   check(strpbrk(one, "bcd") == NULL, 11);       /* Empty string. */
484   (void) strcpy(one, "");
485   check(strpbrk(one, "bcde") == NULL, 12);      /* Empty string. */
486   check(strpbrk(one, "") == NULL, 13);  /* Both strings empty. */
487   (void) strcpy(one, "abcabdea");
488   check(strpbrk(one, "befg") == one+1, 14);     /* Finding first. */
489   check(strpbrk(one, "cbr") == one+1, 15);      /* With multiple search. */
490   check(strpbrk(one, "db") == one+1, 16);       /* Another variant. */
491   check(strpbrk(one, "efgh") == one+6, 17);     /* And yet another. */
492 }
493
494 void
495 test_strstr (void)
496 {
497   it = "strstr";
498   check(strstr("abcd", "z") == NULL, 1);        /* Not found. */
499   check(strstr("abcd", "abx") == NULL, 2);      /* Dead end. */
500   (void) strcpy(one, "abcd");
501   check(strstr(one, "c") == one+2, 3);  /* Basic test. */
502   check(strstr(one, "bc") == one+1, 4); /* Multichar. */
503   check(strstr(one, "d") == one+3, 5);  /* End of string. */
504   check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
505   check(strstr(one, "abc") == one, 7);  /* Beginning. */
506   check(strstr(one, "abcd") == one, 8); /* Exact match. */
507   check(strstr(one, "abcde") == NULL, 9);       /* Too long. */
508   check(strstr(one, "de") == NULL, 10); /* Past end. */
509   check(strstr(one, "") == one, 11);    /* Finding empty. */
510   (void) strcpy(one, "ababa");
511   check(strstr(one, "ba") == one+1, 12);        /* Finding first. */
512   (void) strcpy(one, "");
513   check(strstr(one, "b") == NULL, 13);  /* Empty string. */
514   check(strstr(one, "") == one, 14);    /* Empty in empty string. */
515   (void) strcpy(one, "bcbca");
516   check(strstr(one, "bca") == one+2, 15);       /* False start. */
517   (void) strcpy(one, "bbbcabbca");
518   check(strstr(one, "bbca") == one+1, 16);      /* With overlap. */
519 }
520
521 void
522 test_strspn (void)
523 {
524   it = "strspn";
525   check(strspn("abcba", "abc") == 5, 1);        /* Whole string. */
526   check(strspn("abcba", "ab") == 2, 2); /* Partial. */
527   check(strspn("abc", "qx") == 0, 3);   /* None. */
528   check(strspn("", "ab") == 0, 4);      /* Null string. */
529   check(strspn("abc", "") == 0, 5);     /* Null search list. */
530 }
531
532 void
533 test_strcspn (void)
534 {
535   it = "strcspn";
536   check(strcspn("abcba", "qx") == 5, 1);        /* Whole string. */
537   check(strcspn("abcba", "cx") == 2, 2);        /* Partial. */
538   check(strcspn("abc", "abc") == 0, 3); /* None. */
539   check(strcspn("", "ab") == 0, 4);     /* Null string. */
540   check(strcspn("abc", "") == 3, 5);    /* Null search list. */
541 }
542
543 void
544 test_strtok (void)
545 {
546   it = "strtok";
547   (void) strcpy(one, "first, second, third");
548   equal(strtok(one, ", "), "first", 1); /* Basic test. */
549   equal(one, "first", 2);
550   equal(strtok((char *)NULL, ", "), "second", 3);
551   equal(strtok((char *)NULL, ", "), "third", 4);
552   check(strtok((char *)NULL, ", ") == NULL, 5);
553   (void) strcpy(one, ", first, ");
554   equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
555   check(strtok((char *)NULL, ", ") == NULL, 7);
556   (void) strcpy(one, "1a, 1b; 2a, 2b");
557   equal(strtok(one, ", "), "1a", 8);    /* Changing delim lists. */
558   equal(strtok((char *)NULL, "; "), "1b", 9);
559   equal(strtok((char *)NULL, ", "), "2a", 10);
560   (void) strcpy(two, "x-y");
561   equal(strtok(two, "-"), "x", 11);     /* New string before done. */
562   equal(strtok((char *)NULL, "-"), "y", 12);
563   check(strtok((char *)NULL, "-") == NULL, 13);
564   (void) strcpy(one, "a,b, c,, ,d");
565   equal(strtok(one, ", "), "a", 14);    /* Different separators. */
566   equal(strtok((char *)NULL, ", "), "b", 15);
567   equal(strtok((char *)NULL, " ,"), "c", 16);   /* Permute list too. */
568   equal(strtok((char *)NULL, " ,"), "d", 17);
569   check(strtok((char *)NULL, ", ") == NULL, 18);
570   check(strtok((char *)NULL, ", ") == NULL, 19);        /* Persistence. */
571   (void) strcpy(one, ", ");
572   check(strtok(one, ", ") == NULL, 20); /* No tokens. */
573   (void) strcpy(one, "");
574   check(strtok(one, ", ") == NULL, 21); /* Empty string. */
575   (void) strcpy(one, "abc");
576   equal(strtok(one, ", "), "abc", 22);  /* No delimiters. */
577   check(strtok((char *)NULL, ", ") == NULL, 23);
578   (void) strcpy(one, "abc");
579   equal(strtok(one, ""), "abc", 24);    /* Empty delimiter list. */
580   check(strtok((char *)NULL, "") == NULL, 25);
581   (void) strcpy(one, "abcdefgh");
582   (void) strcpy(one, "a,b,c");
583   equal(strtok(one, ","), "a", 26);     /* Basics again... */
584   equal(strtok((char *)NULL, ","), "b", 27);
585   equal(strtok((char *)NULL, ","), "c", 28);
586   check(strtok((char *)NULL, ",") == NULL, 29);
587   equal(one+6, "gh", 30);                       /* Stomped past end? */
588   equal(one, "a", 31);                  /* Stomped old tokens? */
589   equal(one+2, "b", 32);
590   equal(one+4, "c", 33);
591 }
592
593 void
594 test_strtok_r (void)
595 {
596   it = "strtok_r";
597   (void) strcpy(one, "first, second, third");
598   equal(strtok_r(one, ", ", &cp), "first", 1);  /* Basic test. */
599   equal(one, "first", 2);
600   equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
601   equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
602   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
603   (void) strcpy(one, ", first, ");
604   equal(strtok_r(one, ", ", &cp), "first", 6);  /* Extra delims, 1 tok. */
605   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
606   (void) strcpy(one, "1a, 1b; 2a, 2b");
607   equal(strtok_r(one, ", ", &cp), "1a", 8);     /* Changing delim lists. */
608   equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
609   equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
610   (void) strcpy(two, "x-y");
611   equal(strtok_r(two, "-", &cp), "x", 11);      /* New string before done. */
612   equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
613   check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
614   (void) strcpy(one, "a,b, c,, ,d");
615   equal(strtok_r(one, ", ", &cp), "a", 14);     /* Different separators. */
616   equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
617   equal(strtok_r((char *)NULL, " ,", &cp), "c", 16);    /* Permute list too. */
618   equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
619   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
620   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
621   (void) strcpy(one, ", ");
622   check(strtok_r(one, ", ", &cp) == NULL, 20);  /* No tokens. */
623   (void) strcpy(one, "");
624   check(strtok_r(one, ", ", &cp) == NULL, 21);  /* Empty string. */
625   (void) strcpy(one, "abc");
626   equal(strtok_r(one, ", ", &cp), "abc", 22);   /* No delimiters. */
627   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23);
628   (void) strcpy(one, "abc");
629   equal(strtok_r(one, "", &cp), "abc", 24);     /* Empty delimiter list. */
630   check(strtok_r((char *)NULL, "", &cp) == NULL, 25);
631   (void) strcpy(one, "abcdefgh");
632   (void) strcpy(one, "a,b,c");
633   equal(strtok_r(one, ",", &cp), "a", 26);      /* Basics again... */
634   equal(strtok_r((char *)NULL, ",", &cp), "b", 27);
635   equal(strtok_r((char *)NULL, ",", &cp), "c", 28);
636   check(strtok_r((char *)NULL, ",", &cp) == NULL, 29);
637   equal(one+6, "gh", 30);                       /* Stomped past end? */
638   equal(one, "a", 31);                  /* Stomped old tokens? */
639   equal(one+2, "b", 32);
640   equal(one+4, "c", 33);
641 }
642
643 void
644 test_strsep (void)
645 {
646   it = "strsep";
647   cp = strcpy(one, "first, second, third");
648   equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
649   equal(one, "first", 2);
650   equal(strsep(&cp, ", "), "", 3);
651   equal(strsep(&cp, ", "), "second", 4);
652   equal(strsep(&cp, ", "), "", 5);
653   equal(strsep(&cp, ", "), "third", 6);
654   check(strsep(&cp, ", ") == NULL, 7);
655   cp = strcpy(one, ", first, ");
656   equal(strsep(&cp, ", "), "", 8);
657   equal(strsep(&cp, ", "), "", 9);
658   equal(strsep(&cp, ", "), "first", 10);        /* Extra delims, 1 tok. */
659   equal(strsep(&cp, ", "), "", 11);
660   equal(strsep(&cp, ", "), "", 12);
661   check(strsep(&cp, ", ") == NULL, 13);
662   cp = strcpy(one, "1a, 1b; 2a, 2b");
663   equal(strsep(&cp, ", "), "1a", 14);   /* Changing delim lists. */
664   equal(strsep(&cp, ", "), "", 15);
665   equal(strsep(&cp, "; "), "1b", 16);
666   equal(strsep(&cp, ", "), "", 17);
667   equal(strsep(&cp, ", "), "2a", 18);
668   cp = strcpy(two, "x-y");
669   equal(strsep(&cp, "-"), "x", 19);     /* New string before done. */
670   equal(strsep(&cp, "-"), "y", 20);
671   check(strsep(&cp, "-") == NULL, 21);
672   cp = strcpy(one, "a,b, c,, ,d ");
673   equal(strsep(&cp, ", "), "a", 22);    /* Different separators. */
674   equal(strsep(&cp, ", "), "b", 23);
675   equal(strsep(&cp, " ,"), "", 24);
676   equal(strsep(&cp, " ,"), "c", 25);    /* Permute list too. */
677   equal(strsep(&cp, " ,"), "", 26);
678   equal(strsep(&cp, " ,"), "", 27);
679   equal(strsep(&cp, " ,"), "", 28);
680   equal(strsep(&cp, " ,"), "d", 29);
681   equal(strsep(&cp, " ,"), "", 30);
682   check(strsep(&cp, ", ") == NULL, 31);
683   check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
684   cp = strcpy(one, ", ");
685   equal(strsep(&cp, ", "), "", 33);
686   equal(strsep(&cp, ", "), "", 34);
687   equal(strsep(&cp, ", "), "", 35);
688   check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
689   cp = strcpy(one, "");
690   equal(strsep(&cp, ", "), "", 37);
691   check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
692   cp = strcpy(one, "abc");
693   equal(strsep(&cp, ", "), "abc", 39);  /* No delimiters. */
694   check(strsep(&cp, ", ") == NULL, 40);
695   cp = strcpy(one, "abc");
696   equal(strsep(&cp, ""), "abc", 41);    /* Empty delimiter list. */
697   check(strsep(&cp, "") == NULL, 42);
698   (void) strcpy(one, "abcdefgh");
699   cp = strcpy(one, "a,b,c");
700   equal(strsep(&cp, ","), "a", 43);     /* Basics again... */
701   equal(strsep(&cp, ","), "b", 44);
702   equal(strsep(&cp, ","), "c", 45);
703   check(strsep(&cp, ",") == NULL, 46);
704   equal(one+6, "gh", 47);               /* Stomped past end? */
705   equal(one, "a", 48);                  /* Stomped old tokens? */
706   equal(one+2, "b", 49);
707   equal(one+4, "c", 50);
708
709   {
710     char text[] = "This,is,a,test";
711     char *list = strdupa (text);
712     equal (strsep (&list, ","), "This", 51);
713     equal (strsep (&list, ","), "is", 52);
714     equal (strsep (&list, ","), "a", 53);
715     equal (strsep (&list, ","), "test", 54);
716     check (strsep (&list, ",") == NULL, 55);
717   }
718
719   cp = strcpy(one, "a,b, c,, ,d,");
720   equal(strsep(&cp, ","), "a", 56);     /* Different separators. */
721   equal(strsep(&cp, ","), "b", 57);
722   equal(strsep(&cp, ","), " c", 58);    /* Permute list too. */
723   equal(strsep(&cp, ","), "", 59);
724   equal(strsep(&cp, ","), " ", 60);
725   equal(strsep(&cp, ","), "d", 61);
726   equal(strsep(&cp, ","), "", 62);
727   check(strsep(&cp, ",") == NULL, 63);
728   check(strsep(&cp, ",") == NULL, 64);  /* Persistence. */
729
730   cp = strcpy(one, "a,b, c,, ,d,");
731   equal(strsep(&cp, "xy,"), "a", 65);   /* Different separators. */
732   equal(strsep(&cp, "x,y"), "b", 66);
733   equal(strsep(&cp, ",xy"), " c", 67);  /* Permute list too. */
734   equal(strsep(&cp, "xy,"), "", 68);
735   equal(strsep(&cp, "x,y"), " ", 69);
736   equal(strsep(&cp, ",xy"), "d", 70);
737   equal(strsep(&cp, "xy,"), "", 71);
738   check(strsep(&cp, "x,y") == NULL, 72);
739   check(strsep(&cp, ",xy") == NULL, 73);        /* Persistence. */
740 }
741
742 void
743 test_memcmp (void)
744 {
745   it = "memcmp";
746   check(memcmp("a", "a", 1) == 0, 1);           /* Identity. */
747   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
748   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
749   check(memcmp("abce", "abcd", 4) > 0, 4);
750   check(memcmp("alph", "beta", 4) < 0, 5);
751   check(memcmp("a\203", "a\003", 2) > 0, 6);
752   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
753   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
754 }
755
756 void
757 test_memchr (void)
758 {
759   it = "memchr";
760   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
761   (void) strcpy(one, "abcd");
762   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
763   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
764   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
765   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
766   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
767   (void) strcpy(one, "ababa");
768   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
769   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
770   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
771   (void) strcpy(one, "a\203b");
772   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
773
774   /* now test all possible alignment and length combinations to catch
775      bugs due to unrolled loops (assuming unrolling is limited to no
776      more than 128 byte chunks: */
777   {
778     char buf[128 + sizeof(long)];
779     long align, len, i, pos;
780
781     for (align = 0; align < (long) sizeof(long); ++align) {
782       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
783         for (i = 0; i < len; ++i) {
784           buf[align + i] = 'x';         /* don't depend on memset... */
785         }
786         for (pos = 0; pos < len; ++pos) {
787 #if 0
788           printf("align %d, len %d, pos %d\n", align, len, pos);
789 #endif
790           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
791           check(memchr(buf + align, 'x', pos) == NULL, 11);
792           buf[align + pos] = '-';
793         }
794       }
795     }
796   }
797 }
798
799 void
800 test_memcpy (void)
801 {
802   it = "memcpy";
803   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
804   equal(one, "abc", 2);                 /* Did the copy go right? */
805
806   (void) strcpy(one, "abcdefgh");
807   (void) memcpy(one+1, "xyz", 2);
808   equal(one, "axydefgh", 3);            /* Basic test. */
809
810   (void) strcpy(one, "abc");
811   (void) memcpy(one, "xyz", 0);
812   equal(one, "abc", 4);                 /* Zero-length copy. */
813
814   (void) strcpy(one, "hi there");
815   (void) strcpy(two, "foo");
816   (void) memcpy(two, one, 9);
817   equal(two, "hi there", 5);            /* Just paranoia. */
818   equal(one, "hi there", 6);            /* Stomped on source? */
819 }
820
821 void
822 test_memmove (void)
823 {
824   it = "memmove";
825   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
826   equal(one, "abc", 2);                 /* Did the copy go right? */
827
828   (void) strcpy(one, "abcdefgh");
829   (void) memmove(one+1, "xyz", 2);
830   equal(one, "axydefgh", 3);            /* Basic test. */
831
832   (void) strcpy(one, "abc");
833   (void) memmove(one, "xyz", 0);
834   equal(one, "abc", 4);                 /* Zero-length copy. */
835
836   (void) strcpy(one, "hi there");
837   (void) strcpy(two, "foo");
838   (void) memmove(two, one, 9);
839   equal(two, "hi there", 5);            /* Just paranoia. */
840   equal(one, "hi there", 6);            /* Stomped on source? */
841
842   (void) strcpy(one, "abcdefgh");
843   (void) memmove(one+1, one, 9);
844   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
845
846   (void) strcpy(one, "abcdefgh");
847   (void) memmove(one+1, one+2, 7);
848   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
849
850   (void) strcpy(one, "abcdefgh");
851   (void) memmove(one, one, 9);
852   equal(one, "abcdefgh", 9);            /* 100% overlap. */
853 }
854
855 void
856 test_memccpy (void)
857 {
858   /* First test like memcpy, then the search part The SVID, the only
859      place where memccpy is mentioned, says overlap might fail, so we
860      don't try it.  Besides, it's hard to see the rationale for a
861      non-left-to-right memccpy.  */
862   it = "memccpy";
863   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
864   equal(one, "abc", 2);                 /* Did the copy go right? */
865
866   (void) strcpy(one, "abcdefgh");
867   (void) memccpy(one+1, "xyz", 'q', 2);
868   equal(one, "axydefgh", 3);            /* Basic test. */
869
870   (void) strcpy(one, "abc");
871   (void) memccpy(one, "xyz", 'q', 0);
872   equal(one, "abc", 4);                 /* Zero-length copy. */
873
874   (void) strcpy(one, "hi there");
875   (void) strcpy(two, "foo");
876   (void) memccpy(two, one, 'q', 9);
877   equal(two, "hi there", 5);            /* Just paranoia. */
878   equal(one, "hi there", 6);            /* Stomped on source? */
879
880   (void) strcpy(one, "abcdefgh");
881   (void) strcpy(two, "horsefeathers");
882   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
883   equal(one, "abcdefgh", 8);            /* Source intact? */
884   equal(two, "abcdefeathers", 9);               /* Copy correct? */
885
886   (void) strcpy(one, "abcd");
887   (void) strcpy(two, "bumblebee");
888   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
889   equal(two, "aumblebee", 11);
890   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
891   equal(two, "abcdlebee", 13);
892   (void) strcpy(one, "xyz");
893   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
894   equal(two, "xbcdlebee", 15);
895 }
896
897 void
898 test_memset (void)
899 {
900   it = "memset";
901   (void) strcpy(one, "abcdefgh");
902   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
903   equal(one, "axxxefgh", 2);            /* Basic test. */
904
905   (void) memset(one+2, 'y', 0);
906   equal(one, "axxxefgh", 3);            /* Zero-length set. */
907
908   (void) memset(one+5, 0, 1);
909   equal(one, "axxxe", 4);                       /* Zero fill. */
910   equal(one+6, "gh", 5);                        /* And the leftover. */
911
912   (void) memset(one+2, 010045, 1);
913   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
914
915   /* Test for more complex versions of memset, for all alignments and
916      lengths up to 256. This test takes a little while, perhaps it should
917      be made weaker? */
918   {
919     char data[512];
920     int i;
921     int j;
922     int k;
923     int c;
924
925     for (i = 0; i < 512; i++)
926       data[i] = 'x';
927     for (c = 0; c <= 'y'; c += 'y')  /* check for memset(,0,) and
928                                         memset(,'y',) */
929       for (j = 0; j < 256; j++)
930         for (i = 0; i < 256; i++)
931           {
932             memset(data+i,c,j);
933             for (k = 0; k < i; k++)
934               if (data[k] != 'x')
935                 goto fail;
936             for (k = i; k < i+j; k++)
937               {
938                 if (data[k] != c)
939                   goto fail;
940                 data[k] = 'x';
941               }
942             for (k = i+j; k < 512; k++)
943               if (data[k] != 'x')
944                 goto fail;
945             continue;
946
947           fail:
948             check(0,7+i+j*256+(c != 0)*256*256);
949           }
950   }
951 }
952
953 void
954 test_bcopy (void)
955 {
956   /* Much like memcpy.  Berklix manual is silent about overlap, so
957      don't test it.  */
958   it = "bcopy";
959   (void) bcopy("abc", one, 4);
960   equal(one, "abc", 1);                 /* Simple copy. */
961
962   (void) strcpy(one, "abcdefgh");
963   (void) bcopy("xyz", one+1, 2);
964   equal(one, "axydefgh", 2);            /* Basic test. */
965
966   (void) strcpy(one, "abc");
967   (void) bcopy("xyz", one, 0);
968   equal(one, "abc", 3);                 /* Zero-length copy. */
969
970   (void) strcpy(one, "hi there");
971   (void) strcpy(two, "foo");
972   (void) bcopy(one, two, 9);
973   equal(two, "hi there", 4);            /* Just paranoia. */
974   equal(one, "hi there", 5);            /* Stomped on source? */
975 }
976
977 void
978 test_bzero (void)
979 {
980   it = "bzero";
981   (void) strcpy(one, "abcdef");
982   bzero(one+2, 2);
983   equal(one, "ab", 1);                  /* Basic test. */
984   equal(one+3, "", 2);
985   equal(one+4, "ef", 3);
986
987   (void) strcpy(one, "abcdef");
988   bzero(one+2, 0);
989   equal(one, "abcdef", 4);              /* Zero-length copy. */
990 }
991
992 void
993 test_bcmp (void)
994 {
995   it = "bcmp";
996   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
997   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
998   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
999   check(bcmp("abce", "abcd", 4) != 0, 4);
1000   check(bcmp("alph", "beta", 4) != 0, 5);
1001   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
1002   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1003 }
1004
1005 void
1006 test_strerror (void)
1007 {
1008   int f;
1009   it = "strerror";
1010   f = __open("/", O_WRONLY);    /* Should always fail. */
1011   check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
1012   equal(strerror(errno), _sys_errlist[errno], 2);
1013 }
1014
1015 int
1016 main (void)
1017 {
1018   int status;
1019
1020   /* Test strcmp first because we use it to test other things.  */
1021   test_strcmp ();
1022
1023   /* Test strcpy next because we need it to set up other tests.  */
1024   test_strcpy ();
1025
1026   /* A closely related function is stpcpy.  */
1027   test_stpcpy ();
1028
1029   /* stpncpy.  */
1030   test_stpncpy ();
1031
1032   /* strcat.  */
1033   test_strcat ();
1034
1035   /* strncat.  */
1036   test_strncat ();
1037
1038   /* strncmp.  */
1039   test_strncmp ();
1040
1041   /* strncpy.  */
1042   test_strncpy ();
1043
1044   /* strlen.  */
1045   test_strlen ();
1046
1047   /* strchr.  */
1048   test_strchr ();
1049
1050   /* index - just like strchr.  */
1051   test_index ();
1052
1053   /* strrchr.  */
1054   test_strrchr ();
1055
1056   /* rindex - just like strrchr.  */
1057   test_rindex ();
1058
1059   /* strpbrk - somewhat like strchr.  */
1060   test_strpbrk ();
1061
1062   /* strstr - somewhat like strchr.  */
1063   test_strstr ();
1064
1065   /* strspn.  */
1066   test_strspn ();
1067
1068   /* strcspn.  */
1069   test_strcspn ();
1070
1071   /* strtok - the hard one.  */
1072   test_strtok ();
1073
1074   /* strtok_r.  */
1075   test_strtok_r ();
1076
1077   /* strsep.  */
1078   test_strsep ();
1079
1080   /* memcmp.  */
1081   test_memcmp ();
1082
1083   /* memchr.  */
1084   test_memchr ();
1085
1086   /* memcpy - need not work for overlap.  */
1087   test_memcpy ();
1088
1089   /* memmove - must work on overlap.  */
1090   test_memmove ();
1091
1092   /* memccpy.  */
1093   test_memccpy ();
1094
1095   /* memset.  */
1096   test_memset ();
1097
1098   /* bcopy.  */
1099   test_bcopy ();
1100
1101   /* bzero.  */
1102   test_bzero ();
1103
1104   /* bcmp - somewhat like memcmp.  */
1105   test_bcmp ();
1106
1107   /* strerror - VERY system-dependent.  */
1108   test_strerror ();
1109
1110
1111   if (errors == 0)
1112     {
1113       status = EXIT_SUCCESS;
1114       puts("No errors.");
1115     }
1116   else
1117     {
1118       status = EXIT_FAILURE;
1119       printf("%Zd errors.\n", errors);
1120     }
1121   exit(status);
1122 }