b8155397379f5ee177ed5712baa7e1657795b38a
[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     char buf[4096];
214     int i;
215     char *p;
216     for (i=0; i < 0x100; i++)
217       {
218         p = (char *)((unsigned long int)(buf + 0xff) & ~0xff) + i;
219         strcpy (p, "OK");
220         strcpy (p+3, "BAD/WRONG");
221         check(strlen(p) == 2, 4+i);
222       }
223    }
224
225   /* strchr.  */
226   it = "strchr";
227   check(strchr("abcd", 'z') == NULL, 1);        /* Not found. */
228   (void) strcpy(one, "abcd");
229   check(strchr(one, 'c') == one+2, 2);  /* Basic test. */
230   check(strchr(one, 'd') == one+3, 3);  /* End of string. */
231   check(strchr(one, 'a') == one, 4);    /* Beginning. */
232   check(strchr(one, '\0') == one+4, 5); /* Finding NUL. */
233   (void) strcpy(one, "ababa");
234   check(strchr(one, 'b') == one+1, 6);  /* Finding first. */
235   (void) strcpy(one, "");
236   check(strchr(one, 'b') == NULL, 7);   /* Empty string. */
237   check(strchr(one, '\0') == one, 8);   /* NUL in empty string. */
238   {
239     char buf[4096];
240     int i;
241     char *p;
242     for (i=0; i < 0x100; i++)
243       {
244         p = (char *)((unsigned long int)(buf + 0xff) & ~0xff) + i;
245         strcpy (p, "OK");
246         strcpy (p+3, "BAD/WRONG");
247         check(strchr(p, '/') == NULL, 9+i);
248       }
249    }
250
251 #if 0
252   /* index - just like strchr.  */
253   it = "index";
254   check(index("abcd", 'z') == NULL, 1); /* Not found. */
255   (void) strcpy(one, "abcd");
256   check(index(one, 'c') == one+2, 2);   /* Basic test. */
257   check(index(one, 'd') == one+3, 3);   /* End of string. */
258   check(index(one, 'a') == one, 4);     /* Beginning. */
259   check(index(one, '\0') == one+4, 5);  /* Finding NUL. */
260   (void) strcpy(one, "ababa");
261   check(index(one, 'b') == one+1, 6);   /* Finding first. */
262   (void) strcpy(one, "");
263   check(index(one, 'b') == NULL, 7);    /* Empty string. */
264   check(index(one, '\0') == one, 8);    /* NUL in empty string. */
265 #endif
266
267   /* strrchr.  */
268   it = "strrchr";
269   check(strrchr("abcd", 'z') == NULL, 1);       /* Not found. */
270   (void) strcpy(one, "abcd");
271   check(strrchr(one, 'c') == one+2, 2); /* Basic test. */
272   check(strrchr(one, 'd') == one+3, 3); /* End of string. */
273   check(strrchr(one, 'a') == one, 4);   /* Beginning. */
274   check(strrchr(one, '\0') == one+4, 5);        /* Finding NUL. */
275   (void) strcpy(one, "ababa");
276   check(strrchr(one, 'b') == one+3, 6); /* Finding last. */
277   (void) strcpy(one, "");
278   check(strrchr(one, 'b') == NULL, 7);  /* Empty string. */
279   check(strrchr(one, '\0') == one, 8);  /* NUL in empty string. */
280   {
281     char buf[4096];
282     int i;
283     char *p;
284     for (i=0; i < 0x100; i++)
285       {
286         p = (char *)((unsigned long int)(buf + 0xff) & ~0xff) + i;
287         strcpy (p, "OK");
288         strcpy (p+3, "BAD/WRONG");
289         check(strrchr(p, '/') == NULL, 9+i);
290       }
291    }
292
293 #if 0
294   /* rindex - just like strrchr.  */
295   it = "rindex";
296   check(rindex("abcd", 'z') == NULL, 1);        /* Not found. */
297   (void) strcpy(one, "abcd");
298   check(rindex(one, 'c') == one+2, 2);  /* Basic test. */
299   check(rindex(one, 'd') == one+3, 3);  /* End of string. */
300   check(rindex(one, 'a') == one, 4);    /* Beginning. */
301   check(rindex(one, '\0') == one+4, 5); /* Finding NUL. */
302   (void) strcpy(one, "ababa");
303   check(rindex(one, 'b') == one+3, 6);  /* Finding last. */
304   (void) strcpy(one, "");
305   check(rindex(one, 'b') == NULL, 7);   /* Empty string. */
306   check(rindex(one, '\0') == one, 8);   /* NUL in empty string. */
307 #endif
308
309   /* strpbrk - somewhat like strchr.  */
310   it = "strpbrk";
311   check(strpbrk("abcd", "z") == NULL, 1);       /* Not found. */
312   (void) strcpy(one, "abcd");
313   check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
314   check(strpbrk(one, "d") == one+3, 3); /* End of string. */
315   check(strpbrk(one, "a") == one, 4);   /* Beginning. */
316   check(strpbrk(one, "") == NULL, 5);   /* Empty search list. */
317   check(strpbrk(one, "cb") == one+1, 6);        /* Multiple search. */
318   (void) strcpy(one, "abcabdea");
319   check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
320   check(strpbrk(one, "cb") == one+1, 8);        /* With multiple search. */
321   check(strpbrk(one, "db") == one+1, 9);        /* Another variant. */
322   (void) strcpy(one, "");
323   check(strpbrk(one, "bc") == NULL, 10);        /* Empty string. */
324   check(strpbrk(one, "") == NULL, 11);  /* Both strings empty. */
325
326   /* strstr - somewhat like strchr.  */
327   it = "strstr";
328   check(strstr("abcd", "z") == NULL, 1);        /* Not found. */
329   check(strstr("abcd", "abx") == NULL, 2);      /* Dead end. */
330   (void) strcpy(one, "abcd");
331   check(strstr(one, "c") == one+2, 3);  /* Basic test. */
332   check(strstr(one, "bc") == one+1, 4); /* Multichar. */
333   check(strstr(one, "d") == one+3, 5);  /* End of string. */
334   check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
335   check(strstr(one, "abc") == one, 7);  /* Beginning. */
336   check(strstr(one, "abcd") == one, 8); /* Exact match. */
337   check(strstr(one, "abcde") == NULL, 9);       /* Too long. */
338   check(strstr(one, "de") == NULL, 10); /* Past end. */
339   check(strstr(one, "") == one, 11);    /* Finding empty. */
340   (void) strcpy(one, "ababa");
341   check(strstr(one, "ba") == one+1, 12);        /* Finding first. */
342   (void) strcpy(one, "");
343   check(strstr(one, "b") == NULL, 13);  /* Empty string. */
344   check(strstr(one, "") == one, 14);    /* Empty in empty string. */
345   (void) strcpy(one, "bcbca");
346   check(strstr(one, "bca") == one+2, 15);       /* False start. */
347   (void) strcpy(one, "bbbcabbca");
348   check(strstr(one, "bbca") == one+1, 16);      /* With overlap. */
349
350   /* strspn.  */
351   it = "strspn";
352   check(strspn("abcba", "abc") == 5, 1);        /* Whole string. */
353   check(strspn("abcba", "ab") == 2, 2); /* Partial. */
354   check(strspn("abc", "qx") == 0, 3);   /* None. */
355   check(strspn("", "ab") == 0, 4);      /* Null string. */
356   check(strspn("abc", "") == 0, 5);     /* Null search list. */
357
358   /* strcspn.  */
359   it = "strcspn";
360   check(strcspn("abcba", "qx") == 5, 1);        /* Whole string. */
361   check(strcspn("abcba", "cx") == 2, 2);        /* Partial. */
362   check(strcspn("abc", "abc") == 0, 3); /* None. */
363   check(strcspn("", "ab") == 0, 4);     /* Null string. */
364   check(strcspn("abc", "") == 3, 5);    /* Null search list. */
365
366   /* strtok - the hard one.  */
367   it = "strtok";
368   (void) strcpy(one, "first, second, third");
369   equal(strtok(one, ", "), "first", 1); /* Basic test. */
370   equal(one, "first", 2);
371   equal(strtok((char *)NULL, ", "), "second", 3);
372   equal(strtok((char *)NULL, ", "), "third", 4);
373   check(strtok((char *)NULL, ", ") == NULL, 5);
374   (void) strcpy(one, ", first, ");
375   equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
376   check(strtok((char *)NULL, ", ") == NULL, 7);
377   (void) strcpy(one, "1a, 1b; 2a, 2b");
378   equal(strtok(one, ", "), "1a", 8);    /* Changing delim lists. */
379   equal(strtok((char *)NULL, "; "), "1b", 9);
380   equal(strtok((char *)NULL, ", "), "2a", 10);
381   (void) strcpy(two, "x-y");
382   equal(strtok(two, "-"), "x", 11);     /* New string before done. */
383   equal(strtok((char *)NULL, "-"), "y", 12);
384   check(strtok((char *)NULL, "-") == NULL, 13);
385   (void) strcpy(one, "a,b, c,, ,d");
386   equal(strtok(one, ", "), "a", 14);    /* Different separators. */
387   equal(strtok((char *)NULL, ", "), "b", 15);
388   equal(strtok((char *)NULL, " ,"), "c", 16);   /* Permute list too. */
389   equal(strtok((char *)NULL, " ,"), "d", 17);
390   check(strtok((char *)NULL, ", ") == NULL, 18);
391   check(strtok((char *)NULL, ", ") == NULL, 19);        /* Persistence. */
392   (void) strcpy(one, ", ");
393   check(strtok(one, ", ") == NULL, 20); /* No tokens. */
394   (void) strcpy(one, "");
395   check(strtok(one, ", ") == NULL, 21); /* Empty string. */
396   (void) strcpy(one, "abc");
397   equal(strtok(one, ", "), "abc", 22);  /* No delimiters. */
398   check(strtok((char *)NULL, ", ") == NULL, 23);
399   (void) strcpy(one, "abc");
400   equal(strtok(one, ""), "abc", 24);    /* Empty delimiter list. */
401   check(strtok((char *)NULL, "") == NULL, 25);
402   (void) strcpy(one, "abcdefgh");
403   (void) strcpy(one, "a,b,c");
404   equal(strtok(one, ","), "a", 26);     /* Basics again... */
405   equal(strtok((char *)NULL, ","), "b", 27);
406   equal(strtok((char *)NULL, ","), "c", 28);
407   check(strtok((char *)NULL, ",") == NULL, 29);
408   equal(one+6, "gh", 30);                       /* Stomped past end? */
409   equal(one, "a", 31);                  /* Stomped old tokens? */
410   equal(one+2, "b", 32);
411   equal(one+4, "c", 33);
412
413   /* strtok_r.  */
414   it = "strtok_r";
415   (void) strcpy(one, "first, second, third");
416   equal(strtok_r(one, ", ", &cp), "first", 1);  /* Basic test. */
417   equal(one, "first", 2);
418   equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
419   equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
420   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
421   (void) strcpy(one, ", first, ");
422   equal(strtok_r(one, ", ", &cp), "first", 6);  /* Extra delims, 1 tok. */
423   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
424   (void) strcpy(one, "1a, 1b; 2a, 2b");
425   equal(strtok_r(one, ", ", &cp), "1a", 8);     /* Changing delim lists. */
426   equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
427   equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
428   (void) strcpy(two, "x-y");
429   equal(strtok_r(two, "-", &cp), "x", 11);      /* New string before done. */
430   equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
431   check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
432   (void) strcpy(one, "a,b, c,, ,d");
433   equal(strtok_r(one, ", ", &cp), "a", 14);     /* Different separators. */
434   equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
435   equal(strtok_r((char *)NULL, " ,", &cp), "c", 16);    /* Permute list too. */
436   equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
437   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
438   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
439   (void) strcpy(one, ", ");
440   check(strtok_r(one, ", ", &cp) == NULL, 20);  /* No tokens. */
441   (void) strcpy(one, "");
442   check(strtok_r(one, ", ", &cp) == NULL, 21);  /* Empty string. */
443   (void) strcpy(one, "abc");
444   equal(strtok_r(one, ", ", &cp), "abc", 22);   /* No delimiters. */
445   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23);
446   (void) strcpy(one, "abc");
447   equal(strtok_r(one, "", &cp), "abc", 24);     /* Empty delimiter list. */
448   check(strtok_r((char *)NULL, "", &cp) == NULL, 25);
449   (void) strcpy(one, "abcdefgh");
450   (void) strcpy(one, "a,b,c");
451   equal(strtok_r(one, ",", &cp), "a", 26);      /* Basics again... */
452   equal(strtok_r((char *)NULL, ",", &cp), "b", 27);
453   equal(strtok_r((char *)NULL, ",", &cp), "c", 28);
454   check(strtok_r((char *)NULL, ",", &cp) == NULL, 29);
455   equal(one+6, "gh", 30);                       /* Stomped past end? */
456   equal(one, "a", 31);                  /* Stomped old tokens? */
457   equal(one+2, "b", 32);
458   equal(one+4, "c", 33);
459
460   /* strsep.  */
461   it = "strsep";
462   cp = strcpy(one, "first, second, third");
463   equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
464   equal(one, "first", 2);
465   equal(strsep(&cp, ", "), "", 3);
466   equal(strsep(&cp, ", "), "second", 4);
467   equal(strsep(&cp, ", "), "", 5);
468   equal(strsep(&cp, ", "), "third", 6);
469   check(strsep(&cp, ", ") == NULL, 7);
470   cp = strcpy(one, ", first, ");
471   equal(strsep(&cp, ", "), "", 8);
472   equal(strsep(&cp, ", "), "", 9);
473   equal(strsep(&cp, ", "), "first", 10);        /* Extra delims, 1 tok. */
474   equal(strsep(&cp, ", "), "", 11);
475   check(strsep(&cp, ", ") == NULL, 12);
476   cp = strcpy(one, "1a, 1b; 2a, 2b");
477   equal(strsep(&cp, ", "), "1a", 13);   /* Changing delim lists. */
478   equal(strsep(&cp, ", "), "", 14);
479   equal(strsep(&cp, "; "), "1b", 15);
480   equal(strsep(&cp, ", "), "", 16);
481   equal(strsep(&cp, ", "), "2a", 17);
482   cp = strcpy(two, "x-y");
483   equal(strsep(&cp, "-"), "x", 18);     /* New string before done. */
484   equal(strsep(&cp, "-"), "y", 19);
485   check(strsep(&cp, "-") == NULL, 20);
486   cp = strcpy(one, "a,b, c,, ,d");
487   equal(strsep(&cp, ", "), "a", 21);    /* Different separators. */
488   equal(strsep(&cp, ", "), "b", 22);
489   equal(strsep(&cp, " ,"), "", 23);
490   equal(strsep(&cp, " ,"), "c", 24);    /* Permute list too. */
491   equal(strsep(&cp, " ,"), "", 25);
492   equal(strsep(&cp, " ,"), "", 26);
493   equal(strsep(&cp, " ,"), "", 27);
494   equal(strsep(&cp, " ,"), "d", 28);
495   check(strsep(&cp, ", ") == NULL, 29);
496   check(strsep(&cp, ", ") == NULL, 30); /* Persistence. */
497   cp = strcpy(one, ", ");
498   equal(strsep(&cp, ", "), "", 31);
499   equal(strsep(&cp, ", "), "", 32);
500   check(strsep(&cp, ", ") == NULL, 33); /* No tokens. */
501   cp = strcpy(one, "");
502   check(strsep(&cp, ", ") == NULL, 34); /* Empty string. */
503   cp = strcpy(one, "abc");
504   equal(strsep(&cp, ", "), "abc", 35);  /* No delimiters. */
505   check(strsep(&cp, ", ") == NULL, 36);
506   cp = strcpy(one, "abc");
507   equal(strsep(&cp, ""), "abc", 37);    /* Empty delimiter list. */
508   check(strsep(&cp, "") == NULL, 38);
509   (void) strcpy(one, "abcdefgh");
510   cp = strcpy(one, "a,b,c");
511   equal(strsep(&cp, ","), "a", 39);     /* Basics again... */
512   equal(strsep(&cp, ","), "b", 40);
513   equal(strsep(&cp, ","), "c", 41);
514   check(strsep(&cp, ",") == NULL, 42);
515   equal(one+6, "gh", 43);               /* Stomped past end? */
516   equal(one, "a", 44);                  /* Stomped old tokens? */
517   equal(one+2, "b", 45);
518   equal(one+4, "c", 46);
519
520   /* memcmp.  */
521   it = "memcmp";
522   check(memcmp("a", "a", 1) == 0, 1);           /* Identity. */
523   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
524   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
525   check(memcmp("abce", "abcd", 4) > 0, 4);
526   check(memcmp("alph", "beta", 4) < 0, 5);
527   check(memcmp("a\203", "a\003", 2) > 0, 6);
528   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
529   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
530
531   /* memchr.  */
532   it = "memchr";
533   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
534   (void) strcpy(one, "abcd");
535   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
536   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
537   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
538   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
539   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
540   (void) strcpy(one, "ababa");
541   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
542   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
543   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
544   (void) strcpy(one, "a\203b");
545   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
546
547   /* now test all possible alignment and length combinations to catch
548      bugs due to unrolled loops (assuming unrolling is limited to no
549      more than 128 byte chunks: */
550   {
551     char buf[128 + sizeof(long)];
552     long align, len, i, pos;
553
554     for (align = 0; align < (long) sizeof(long); ++align) {
555       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
556         for (i = 0; i < len; ++i) {
557           buf[align + i] = 'x';         /* don't depend on memset... */
558         }
559         for (pos = 0; pos < len; ++pos) {
560 #if 0
561           printf("align %d, len %d, pos %d\n", align, len, pos);
562 #endif
563           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
564           check(memchr(buf + align, 'x', pos) == NULL, 11);
565           buf[align + pos] = '-';
566         }
567       }
568     }
569   }
570
571   /* memcpy - need not work for overlap.  */
572   it = "memcpy";
573   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
574   equal(one, "abc", 2);                 /* Did the copy go right? */
575
576   (void) strcpy(one, "abcdefgh");
577   (void) memcpy(one+1, "xyz", 2);
578   equal(one, "axydefgh", 3);            /* Basic test. */
579
580   (void) strcpy(one, "abc");
581   (void) memcpy(one, "xyz", 0);
582   equal(one, "abc", 4);                 /* Zero-length copy. */
583
584   (void) strcpy(one, "hi there");
585   (void) strcpy(two, "foo");
586   (void) memcpy(two, one, 9);
587   equal(two, "hi there", 5);            /* Just paranoia. */
588   equal(one, "hi there", 6);            /* Stomped on source? */
589
590   /* memmove - must work on overlap.  */
591   it = "memmove";
592   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
593   equal(one, "abc", 2);                 /* Did the copy go right? */
594
595   (void) strcpy(one, "abcdefgh");
596   (void) memmove(one+1, "xyz", 2);
597   equal(one, "axydefgh", 3);            /* Basic test. */
598
599   (void) strcpy(one, "abc");
600   (void) memmove(one, "xyz", 0);
601   equal(one, "abc", 4);                 /* Zero-length copy. */
602
603   (void) strcpy(one, "hi there");
604   (void) strcpy(two, "foo");
605   (void) memmove(two, one, 9);
606   equal(two, "hi there", 5);            /* Just paranoia. */
607   equal(one, "hi there", 6);            /* Stomped on source? */
608
609   (void) strcpy(one, "abcdefgh");
610   (void) memmove(one+1, one, 9);
611   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
612
613   (void) strcpy(one, "abcdefgh");
614   (void) memmove(one+1, one+2, 7);
615   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
616
617   (void) strcpy(one, "abcdefgh");
618   (void) memmove(one, one, 9);
619   equal(one, "abcdefgh", 9);            /* 100% overlap. */
620
621   /* memccpy - first test like memcpy, then the search part
622      The SVID, the only place where memccpy is mentioned, says
623      overlap might fail, so we don't try it.  Besides, it's hard
624      to see the rationale for a non-left-to-right memccpy.  */
625   it = "memccpy";
626   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
627   equal(one, "abc", 2);                 /* Did the copy go right? */
628
629   (void) strcpy(one, "abcdefgh");
630   (void) memccpy(one+1, "xyz", 'q', 2);
631   equal(one, "axydefgh", 3);            /* Basic test. */
632
633   (void) strcpy(one, "abc");
634   (void) memccpy(one, "xyz", 'q', 0);
635   equal(one, "abc", 4);                 /* Zero-length copy. */
636
637   (void) strcpy(one, "hi there");
638   (void) strcpy(two, "foo");
639   (void) memccpy(two, one, 'q', 9);
640   equal(two, "hi there", 5);            /* Just paranoia. */
641   equal(one, "hi there", 6);            /* Stomped on source? */
642
643   (void) strcpy(one, "abcdefgh");
644   (void) strcpy(two, "horsefeathers");
645   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
646   equal(one, "abcdefgh", 8);            /* Source intact? */
647   equal(two, "abcdefeathers", 9);               /* Copy correct? */
648
649   (void) strcpy(one, "abcd");
650   (void) strcpy(two, "bumblebee");
651   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
652   equal(two, "aumblebee", 11);
653   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
654   equal(two, "abcdlebee", 13);
655   (void) strcpy(one, "xyz");
656   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
657   equal(two, "xbcdlebee", 15);
658
659   /* memset.  */
660   it = "memset";
661   (void) strcpy(one, "abcdefgh");
662   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
663   equal(one, "axxxefgh", 2);            /* Basic test. */
664
665   (void) memset(one+2, 'y', 0);
666   equal(one, "axxxefgh", 3);            /* Zero-length set. */
667
668   (void) memset(one+5, 0, 1);
669   equal(one, "axxxe", 4);                       /* Zero fill. */
670   equal(one+6, "gh", 5);                        /* And the leftover. */
671
672   (void) memset(one+2, 010045, 1);
673   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
674
675   /* bcopy - much like memcpy.
676      Berklix manual is silent about overlap, so don't test it.  */
677   it = "bcopy";
678   (void) bcopy("abc", one, 4);
679   equal(one, "abc", 1);                 /* Simple copy. */
680
681   (void) strcpy(one, "abcdefgh");
682   (void) bcopy("xyz", one+1, 2);
683   equal(one, "axydefgh", 2);            /* Basic test. */
684
685   (void) strcpy(one, "abc");
686   (void) bcopy("xyz", one, 0);
687   equal(one, "abc", 3);                 /* Zero-length copy. */
688
689   (void) strcpy(one, "hi there");
690   (void) strcpy(two, "foo");
691   (void) bcopy(one, two, 9);
692   equal(two, "hi there", 4);            /* Just paranoia. */
693   equal(one, "hi there", 5);            /* Stomped on source? */
694
695   /* bzero.  */
696   it = "bzero";
697   (void) strcpy(one, "abcdef");
698   bzero(one+2, 2);
699   equal(one, "ab", 1);                  /* Basic test. */
700   equal(one+3, "", 2);
701   equal(one+4, "ef", 3);
702
703   (void) strcpy(one, "abcdef");
704   bzero(one+2, 0);
705   equal(one, "abcdef", 4);              /* Zero-length copy. */
706
707 #if 0
708   /* bcmp - somewhat like memcmp.  */
709   it = "bcmp";
710   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
711   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
712   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
713   check(bcmp("abce", "abcd", 4) != 0, 4);
714   check(bcmp("alph", "beta", 4) != 0, 5);
715   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
716   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
717 #endif
718
719   {
720     char text[] = "This,is,a,test";
721     char *list = text;
722     it = "strsep";
723     check (!strcmp ("This", strsep (&list, ",")), 1);
724     check (!strcmp ("is", strsep (&list, ",")), 2);
725     check (!strcmp ("a", strsep (&list, ",")), 3);
726     check (!strcmp ("test", strsep (&list, ",")), 4);
727     check (strsep (&list, ",") == NULL, 5);
728   }
729
730   /* strerror - VERY system-dependent.  */
731   {
732     int f;
733     it = "strerror";
734     f = __open("/", O_WRONLY);  /* Should always fail. */
735     check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
736     equal(strerror(errno), _sys_errlist[errno], 2);
737   }
738
739   {
740     int status;
741     if (errors == 0)
742       {
743         status = EXIT_SUCCESS;
744         puts("No errors.");
745       }
746     else
747       {
748         status = EXIT_FAILURE;
749         printf("%Zd errors.\n", errors);
750       }
751     exit(status);
752   }
753 }