Rewrite. Split in many small functions to not exceed gcc's limits.
[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 = text;
699     it = "strsep";
700     check (!strcmp ("This", strsep (&list, ",")), 1);
701     check (!strcmp ("is", strsep (&list, ",")), 2);
702     check (!strcmp ("a", strsep (&list, ",")), 3);
703     check (!strcmp ("test", strsep (&list, ",")), 4);
704     check (strsep (&list, ",") == NULL, 5);
705   }
706 }
707
708 void
709 test_memcmp (void)
710 {
711   it = "memcmp";
712   check(memcmp("a", "a", 1) == 0, 1);           /* Identity. */
713   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
714   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
715   check(memcmp("abce", "abcd", 4) > 0, 4);
716   check(memcmp("alph", "beta", 4) < 0, 5);
717   check(memcmp("a\203", "a\003", 2) > 0, 6);
718   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
719   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
720 }
721
722 void
723 test_memchr (void)
724 {
725   it = "memchr";
726   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
727   (void) strcpy(one, "abcd");
728   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
729   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
730   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
731   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
732   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
733   (void) strcpy(one, "ababa");
734   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
735   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
736   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
737   (void) strcpy(one, "a\203b");
738   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
739
740   /* now test all possible alignment and length combinations to catch
741      bugs due to unrolled loops (assuming unrolling is limited to no
742      more than 128 byte chunks: */
743   {
744     char buf[128 + sizeof(long)];
745     long align, len, i, pos;
746
747     for (align = 0; align < (long) sizeof(long); ++align) {
748       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
749         for (i = 0; i < len; ++i) {
750           buf[align + i] = 'x';         /* don't depend on memset... */
751         }
752         for (pos = 0; pos < len; ++pos) {
753 #if 0
754           printf("align %d, len %d, pos %d\n", align, len, pos);
755 #endif
756           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
757           check(memchr(buf + align, 'x', pos) == NULL, 11);
758           buf[align + pos] = '-';
759         }
760       }
761     }
762   }
763 }
764
765 void
766 test_memcpy (void)
767 {
768   it = "memcpy";
769   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
770   equal(one, "abc", 2);                 /* Did the copy go right? */
771
772   (void) strcpy(one, "abcdefgh");
773   (void) memcpy(one+1, "xyz", 2);
774   equal(one, "axydefgh", 3);            /* Basic test. */
775
776   (void) strcpy(one, "abc");
777   (void) memcpy(one, "xyz", 0);
778   equal(one, "abc", 4);                 /* Zero-length copy. */
779
780   (void) strcpy(one, "hi there");
781   (void) strcpy(two, "foo");
782   (void) memcpy(two, one, 9);
783   equal(two, "hi there", 5);            /* Just paranoia. */
784   equal(one, "hi there", 6);            /* Stomped on source? */
785 }
786
787 void
788 test_memmove (void)
789 {
790   it = "memmove";
791   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
792   equal(one, "abc", 2);                 /* Did the copy go right? */
793
794   (void) strcpy(one, "abcdefgh");
795   (void) memmove(one+1, "xyz", 2);
796   equal(one, "axydefgh", 3);            /* Basic test. */
797
798   (void) strcpy(one, "abc");
799   (void) memmove(one, "xyz", 0);
800   equal(one, "abc", 4);                 /* Zero-length copy. */
801
802   (void) strcpy(one, "hi there");
803   (void) strcpy(two, "foo");
804   (void) memmove(two, one, 9);
805   equal(two, "hi there", 5);            /* Just paranoia. */
806   equal(one, "hi there", 6);            /* Stomped on source? */
807
808   (void) strcpy(one, "abcdefgh");
809   (void) memmove(one+1, one, 9);
810   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
811
812   (void) strcpy(one, "abcdefgh");
813   (void) memmove(one+1, one+2, 7);
814   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
815
816   (void) strcpy(one, "abcdefgh");
817   (void) memmove(one, one, 9);
818   equal(one, "abcdefgh", 9);            /* 100% overlap. */
819 }
820
821 void
822 test_memccpy (void)
823 {
824   /* First test like memcpy, then the search part The SVID, the only
825      place where memccpy is mentioned, says overlap might fail, so we
826      don't try it.  Besides, it's hard to see the rationale for a
827      non-left-to-right memccpy.  */
828   it = "memccpy";
829   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
830   equal(one, "abc", 2);                 /* Did the copy go right? */
831
832   (void) strcpy(one, "abcdefgh");
833   (void) memccpy(one+1, "xyz", 'q', 2);
834   equal(one, "axydefgh", 3);            /* Basic test. */
835
836   (void) strcpy(one, "abc");
837   (void) memccpy(one, "xyz", 'q', 0);
838   equal(one, "abc", 4);                 /* Zero-length copy. */
839
840   (void) strcpy(one, "hi there");
841   (void) strcpy(two, "foo");
842   (void) memccpy(two, one, 'q', 9);
843   equal(two, "hi there", 5);            /* Just paranoia. */
844   equal(one, "hi there", 6);            /* Stomped on source? */
845
846   (void) strcpy(one, "abcdefgh");
847   (void) strcpy(two, "horsefeathers");
848   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
849   equal(one, "abcdefgh", 8);            /* Source intact? */
850   equal(two, "abcdefeathers", 9);               /* Copy correct? */
851
852   (void) strcpy(one, "abcd");
853   (void) strcpy(two, "bumblebee");
854   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
855   equal(two, "aumblebee", 11);
856   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
857   equal(two, "abcdlebee", 13);
858   (void) strcpy(one, "xyz");
859   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
860   equal(two, "xbcdlebee", 15);
861 }
862
863 void
864 test_memset (void)
865 {
866   it = "memset";
867   (void) strcpy(one, "abcdefgh");
868   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
869   equal(one, "axxxefgh", 2);            /* Basic test. */
870
871   (void) memset(one+2, 'y', 0);
872   equal(one, "axxxefgh", 3);            /* Zero-length set. */
873
874   (void) memset(one+5, 0, 1);
875   equal(one, "axxxe", 4);                       /* Zero fill. */
876   equal(one+6, "gh", 5);                        /* And the leftover. */
877
878   (void) memset(one+2, 010045, 1);
879   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
880
881   /* Test for more complex versions of memset, for all alignments and
882      lengths up to 256. This test takes a little while, perhaps it should
883      be made weaker? */
884   {
885     char data[512];
886     int i;
887     int j;
888     int k;
889     int c;
890
891     for (i = 0; i < 512; i++)
892       data[i] = 'x';
893     for (c = 0; c <= 'y'; c += 'y')  /* check for memset(,0,) and
894                                         memset(,'y',) */
895       for (j = 0; j < 256; j++)
896         for (i = 0; i < 256; i++)
897           {
898             memset(data+i,c,j);
899             for (k = 0; k < i; k++)
900               if (data[k] != 'x')
901                 goto fail;
902             for (k = i; k < i+j; k++)
903               {
904                 if (data[k] != c)
905                   goto fail;
906                 data[k] = 'x';
907               }
908             for (k = i+j; k < 512; k++)
909               if (data[k] != 'x')
910                 goto fail;
911             continue;
912
913           fail:
914             check(0,7+i+j*256+(c != 0)*256*256);
915           }
916   }
917 }
918
919 void
920 test_bcopy (void)
921 {
922   /* Much like memcpy.  Berklix manual is silent about overlap, so
923      don't test it.  */
924   it = "bcopy";
925   (void) bcopy("abc", one, 4);
926   equal(one, "abc", 1);                 /* Simple copy. */
927
928   (void) strcpy(one, "abcdefgh");
929   (void) bcopy("xyz", one+1, 2);
930   equal(one, "axydefgh", 2);            /* Basic test. */
931
932   (void) strcpy(one, "abc");
933   (void) bcopy("xyz", one, 0);
934   equal(one, "abc", 3);                 /* Zero-length copy. */
935
936   (void) strcpy(one, "hi there");
937   (void) strcpy(two, "foo");
938   (void) bcopy(one, two, 9);
939   equal(two, "hi there", 4);            /* Just paranoia. */
940   equal(one, "hi there", 5);            /* Stomped on source? */
941 }
942
943 void
944 test_bzero (void)
945 {
946   it = "bzero";
947   (void) strcpy(one, "abcdef");
948   bzero(one+2, 2);
949   equal(one, "ab", 1);                  /* Basic test. */
950   equal(one+3, "", 2);
951   equal(one+4, "ef", 3);
952
953   (void) strcpy(one, "abcdef");
954   bzero(one+2, 0);
955   equal(one, "abcdef", 4);              /* Zero-length copy. */
956 }
957
958 void
959 test_bcmp (void)
960 {
961   it = "bcmp";
962   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
963   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
964   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
965   check(bcmp("abce", "abcd", 4) != 0, 4);
966   check(bcmp("alph", "beta", 4) != 0, 5);
967   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
968   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
969 }
970
971 void
972 test_strerror (void)
973 {
974   int f;
975   it = "strerror";
976   f = __open("/", O_WRONLY);    /* Should always fail. */
977   check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
978   equal(strerror(errno), _sys_errlist[errno], 2);
979 }
980
981 int
982 main (void)
983 {
984   int status;
985
986   /* Test strcmp first because we use it to test other things.  */
987   test_strcmp ();
988
989   /* Test strcpy next because we need it to set up other tests.  */
990   test_strcpy ();
991
992   /* A closely related function is stpcpy.  */
993   test_stpcpy ();
994
995   /* stpncpy.  */
996   test_stpncpy ();
997
998   /* strcat.  */
999   test_strcat ();
1000
1001   /* strncat.  */
1002   test_strncat ();
1003
1004   /* strncmp.  */
1005   test_strncmp ();
1006
1007   /* strncpy.  */
1008   test_strncpy ();
1009
1010   /* strlen.  */
1011   test_strlen ();
1012
1013   /* strchr.  */
1014   test_strchr ();
1015
1016   /* index - just like strchr.  */
1017   test_index ();
1018
1019   /* strrchr.  */
1020   test_strrchr ();
1021
1022   /* rindex - just like strrchr.  */
1023   test_rindex ();
1024
1025   /* strpbrk - somewhat like strchr.  */
1026   test_strpbrk ();
1027
1028   /* strstr - somewhat like strchr.  */
1029   test_strstr ();
1030
1031   /* strspn.  */
1032   test_strspn ();
1033
1034   /* strcspn.  */
1035   test_strcspn ();
1036
1037   /* strtok - the hard one.  */
1038   test_strtok ();
1039
1040   /* strtok_r.  */
1041   test_strtok_r ();
1042
1043   /* strsep.  */
1044   test_strsep ();
1045
1046   /* memcmp.  */
1047   test_memcmp ();
1048
1049   /* memchr.  */
1050   test_memchr ();
1051
1052   /* memcpy - need not work for overlap.  */
1053   test_memcpy ();
1054
1055   /* memmove - must work on overlap.  */
1056   test_memmove ();
1057
1058   /* memccpy.  */
1059   test_memccpy ();
1060
1061   /* memset.  */
1062   test_memset ();
1063
1064   /* bcopy.  */
1065   test_bcopy ();
1066
1067   /* bzero.  */
1068   test_bzero ();
1069
1070   /* bcmp - somewhat like memcmp.  */
1071   test_bcmp ();
1072
1073   /* strerror - VERY system-dependent.  */
1074   test_strerror ();
1075
1076
1077   if (errors == 0)
1078     {
1079       status = EXIT_SUCCESS;
1080       puts("No errors.");
1081     }
1082   else
1083     {
1084       status = EXIT_FAILURE;
1085       printf("%Zd errors.\n", errors);
1086     }
1087   exit(status);
1088 }