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