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