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