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