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