Wed May 29 00:52:20 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[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, ", "), "second", 3);
417   equal(strsep(&cp, ", "), "third", 4);
418   check(strsep(&cp, ", ") == NULL, 5);
419   cp = strcpy(one, ", first, ");
420   equal(strsep(&cp, ", "), "", 6);      /* null token. */
421   equal(strsep(&cp, ", "), "", 7);
422   cp = strcpy(one, "1a, 1b; 2a, 2b");
423   equal(strsep(&cp, ", "), "1a", 8);    /* Changing delim lists. */
424   equal(strsep(&cp, "; "), "1b", 9);
425   equal(strsep(&cp, ", "), "2a", 10);
426   cp = strcpy(two, "x-y");
427   equal(strsep(&cp, "-"), "x", 11);     /* New string before done. */
428   equal(strsep(&cp, "-"), "y", 12);
429   check(strsep(&cp, "-") == NULL, 13);
430   cp = strcpy(one, "a,b, c,, ,d");
431   equal(strsep(&cp, ", "), "a", 14);    /* Different separators. */
432   equal(strsep(&cp, ", "), "b", 15);
433   equal(strsep(&cp, " ,"), "c", 16);    /* Permute list too. */
434   equal(strsep(&cp, " ,"), "d", 17);
435   check(strsep(&cp, ", ") == NULL, 18);
436   check(strsep(&cp, ", ") == NULL, 19); /* Persistence. */
437   cp = strcpy(one, ", ");
438   check(strsep(&cp, ", ") == one, 20);  /* Null token. */
439   cp = strcpy(one, "");
440   check(strsep(&cp, ", ") == NULL, 21); /* Empty string. */
441   cp = strcpy(one, "abc");
442   equal(strsep(&cp, ", "), "abc", 22);  /* No delimiters. */
443   check(strsep(&cp, ", ") == NULL, 23);
444   cp = strcpy(one, "abc");
445   equal(strsep(&cp, ""), "abc", 24);    /* Empty delimiter list. */
446   check(strsep(&cp, "") == NULL, 25);
447   (void) strcpy(one, "abcdefgh");
448   cp = strcpy(one, "a,b,c");
449   equal(strsep(&cp, ","), "a", 26);     /* Basics again... */
450   equal(strsep(&cp, ","), "b", 27);
451   equal(strsep(&cp, ","), "c", 28);
452   check(strsep(&cp, ",") == NULL, 29);
453   equal(one+6, "gh", 30);                       /* Stomped past end? */
454   equal(one, "a", 31);                  /* Stomped old tokens? */
455   equal(one+2, "b", 32);
456   equal(one+4, "c", 33);
457
458   /* memcmp.  */
459   it = "memcmp";
460   check(memcmp("a", "a", 1) == 0, 1);   /* Identity. */
461   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
462   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
463   check(memcmp("abce", "abcd", 4) > 0, 4);
464   check(memcmp("alph", "beta", 4) < 0, 5);
465   check(memcmp("a\203", "a\003", 2) > 0, 6);
466   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
467   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
468
469   /* memchr.  */
470   it = "memchr";
471   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
472   (void) strcpy(one, "abcd");
473   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
474   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
475   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
476   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
477   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
478   (void) strcpy(one, "ababa");
479   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
480   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
481   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
482   (void) strcpy(one, "a\203b");
483   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
484
485   /* now test all possible alignment and length combinations to catch
486      bugs due to unrolled loops (assuming unrolling is limited to no
487      more than 128 byte chunks: */
488   {
489     char buf[128 + sizeof(long)];
490     long align, len, i, pos;
491
492     for (align = 0; align < sizeof(long); ++align) {
493       for (len = 0; len < sizeof(buf) - align; ++len) {
494         for (i = 0; i < len; ++i) {
495           buf[align + i] = 'x';         /* don't depend on memset... */
496         }
497         for (pos = 0; pos < len; ++pos) {
498 #if 0
499           printf("align %d, len %d, pos %d\n", align, len, pos);
500 #endif
501           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
502           check(memchr(buf + align, 'x', pos) == NULL, 11);
503           buf[align + pos] = '-';
504         }
505       }
506     }
507   }
508
509   /* memcpy - need not work for overlap.  */
510   it = "memcpy";
511   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
512   equal(one, "abc", 2);                 /* Did the copy go right? */
513
514   (void) strcpy(one, "abcdefgh");
515   (void) memcpy(one+1, "xyz", 2);
516   equal(one, "axydefgh", 3);            /* Basic test. */
517
518   (void) strcpy(one, "abc");
519   (void) memcpy(one, "xyz", 0);
520   equal(one, "abc", 4);                 /* Zero-length copy. */
521
522   (void) strcpy(one, "hi there");
523   (void) strcpy(two, "foo");
524   (void) memcpy(two, one, 9);
525   equal(two, "hi there", 5);            /* Just paranoia. */
526   equal(one, "hi there", 6);            /* Stomped on source? */
527
528   /* memmove - must work on overlap.  */
529   it = "memmove";
530   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
531   equal(one, "abc", 2);                 /* Did the copy go right? */
532
533   (void) strcpy(one, "abcdefgh");
534   (void) memmove(one+1, "xyz", 2);
535   equal(one, "axydefgh", 3);            /* Basic test. */
536
537   (void) strcpy(one, "abc");
538   (void) memmove(one, "xyz", 0);
539   equal(one, "abc", 4);                 /* Zero-length copy. */
540
541   (void) strcpy(one, "hi there");
542   (void) strcpy(two, "foo");
543   (void) memmove(two, one, 9);
544   equal(two, "hi there", 5);            /* Just paranoia. */
545   equal(one, "hi there", 6);            /* Stomped on source? */
546
547   (void) strcpy(one, "abcdefgh");
548   (void) memmove(one+1, one, 9);
549   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
550
551   (void) strcpy(one, "abcdefgh");
552   (void) memmove(one+1, one+2, 7);
553   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
554
555   (void) strcpy(one, "abcdefgh");
556   (void) memmove(one, one, 9);
557   equal(one, "abcdefgh", 9);            /* 100% overlap. */
558
559   /* memccpy - first test like memcpy, then the search part
560      The SVID, the only place where memccpy is mentioned, says
561      overlap might fail, so we don't try it.  Besides, it's hard
562      to see the rationale for a non-left-to-right memccpy.  */
563   it = "memccpy";
564   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
565   equal(one, "abc", 2);                 /* Did the copy go right? */
566
567   (void) strcpy(one, "abcdefgh");
568   (void) memccpy(one+1, "xyz", 'q', 2);
569   equal(one, "axydefgh", 3);            /* Basic test. */
570
571   (void) strcpy(one, "abc");
572   (void) memccpy(one, "xyz", 'q', 0);
573   equal(one, "abc", 4);                 /* Zero-length copy. */
574
575   (void) strcpy(one, "hi there");
576   (void) strcpy(two, "foo");
577   (void) memccpy(two, one, 'q', 9);
578   equal(two, "hi there", 5);            /* Just paranoia. */
579   equal(one, "hi there", 6);            /* Stomped on source? */
580
581   (void) strcpy(one, "abcdefgh");
582   (void) strcpy(two, "horsefeathers");
583   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
584   equal(one, "abcdefgh", 8);            /* Source intact? */
585   equal(two, "abcdefeathers", 9);               /* Copy correct? */
586
587   (void) strcpy(one, "abcd");
588   (void) strcpy(two, "bumblebee");
589   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
590   equal(two, "aumblebee", 11);
591   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
592   equal(two, "abcdlebee", 13);
593   (void) strcpy(one, "xyz");
594   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
595   equal(two, "xbcdlebee", 15);
596
597   /* memset.  */
598   it = "memset";
599   (void) strcpy(one, "abcdefgh");
600   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
601   equal(one, "axxxefgh", 2);            /* Basic test. */
602
603   (void) memset(one+2, 'y', 0);
604   equal(one, "axxxefgh", 3);            /* Zero-length set. */
605
606   (void) memset(one+5, 0, 1);
607   equal(one, "axxxe", 4);                       /* Zero fill. */
608   equal(one+6, "gh", 5);                        /* And the leftover. */
609
610   (void) memset(one+2, 010045, 1);
611   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
612
613   /* bcopy - much like memcpy.
614      Berklix manual is silent about overlap, so don't test it.  */
615   it = "bcopy";
616   (void) bcopy("abc", one, 4);
617   equal(one, "abc", 1);                 /* Simple copy. */
618
619   (void) strcpy(one, "abcdefgh");
620   (void) bcopy("xyz", one+1, 2);
621   equal(one, "axydefgh", 2);            /* Basic test. */
622
623   (void) strcpy(one, "abc");
624   (void) bcopy("xyz", one, 0);
625   equal(one, "abc", 3);                 /* Zero-length copy. */
626
627   (void) strcpy(one, "hi there");
628   (void) strcpy(two, "foo");
629   (void) bcopy(one, two, 9);
630   equal(two, "hi there", 4);            /* Just paranoia. */
631   equal(one, "hi there", 5);            /* Stomped on source? */
632
633   /* bzero.  */
634   it = "bzero";
635   (void) strcpy(one, "abcdef");
636   bzero(one+2, 2);
637   equal(one, "ab", 1);                  /* Basic test. */
638   equal(one+3, "", 2);
639   equal(one+4, "ef", 3);
640
641   (void) strcpy(one, "abcdef");
642   bzero(one+2, 0);
643   equal(one, "abcdef", 4);              /* Zero-length copy. */
644
645 #if 0
646   /* bcmp - somewhat like memcmp.  */
647   it = "bcmp";
648   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
649   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
650   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
651   check(bcmp("abce", "abcd", 4) != 0, 4);
652   check(bcmp("alph", "beta", 4) != 0, 5);
653   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
654   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
655 #endif
656
657   {
658     char text[] = "This,is,a,test";
659     char *list = text;
660     it = "strsep";
661     check (!strcmp ("This", strsep (&list, ",")), 1);
662     check (!strcmp ("is", strsep (&list, ",")), 2);
663     check (!strcmp ("a", strsep (&list, ",")), 3);
664     check (!strcmp ("test", strsep (&list, ",")), 4);
665     check (strsep (&list, ",") == NULL, 5);
666   }
667
668   /* strerror - VERY system-dependent.  */
669   {
670     int f;
671     it = "strerror";
672     f = __open("/", O_WRONLY);  /* Should always fail. */
673     check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
674     equal(strerror(errno), _sys_errlist[errno], 2);
675   }
676
677   {
678     int status;
679     if (errors == 0)
680       {
681         status = EXIT_SUCCESS;
682         puts("No errors.");
683       }
684     else
685       {
686         status = EXIT_FAILURE;
687         printf("%Zd errors.\n", errors);
688       }
689     exit(status);
690   }
691 }