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