Update.
[platform/upstream/glibc.git] / string / tester.c
1 /* Tester for string functions.
2    Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE
22 #endif
23
24 /* Make sure we don't test the optimized inline functions if we want to
25    test the real implementation.  */
26 #if !defined DO_STRING_INLINES
27 #undef __USE_STRING_INLINES
28 #endif
29
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <fcntl.h>
36
37 #ifndef HAVE_GNU_LD
38 #define _sys_nerr       sys_nerr
39 #define _sys_errlist    sys_errlist
40 #endif
41
42 #define STREQ(a, b)     (strcmp((a), (b)) == 0)
43
44 const char *it = "<UNSET>";     /* Routine name for message routines. */
45 size_t errors = 0;
46
47 /* Complain if condition is not true.  */
48 void
49 check (int thing, int number)
50 {
51   if (!thing)
52     {
53       printf("%s flunked test %d\n", it, number);
54       ++errors;
55     }
56 }
57
58 /* Complain if first two args don't strcmp as equal.  */
59 void
60 equal (const char *a, const char *b, int number)
61 {
62   check(a != NULL && b != NULL && STREQ (a, b), number);
63 }
64
65 char one[50];
66 char two[50];
67 char *cp;
68
69 void
70 test_strcmp (void)
71 {
72   it = "strcmp";
73   check (strcmp ("", "") == 0, 1);              /* Trivial case. */
74   check (strcmp ("a", "a") == 0, 2);            /* Identity. */
75   check (strcmp ("abc", "abc") == 0, 3);        /* Multicharacter. */
76   check (strcmp ("abc", "abcd") < 0, 4);        /* Length mismatches. */
77   check (strcmp ("abcd", "abc") > 0, 5);
78   check (strcmp ("abcd", "abce") < 0, 6);       /* Honest miscompares. */
79   check (strcmp ("abce", "abcd") > 0, 7);
80   check (strcmp ("a\203", "a") > 0, 8);         /* Tricky if char signed. */
81   check (strcmp ("a\203", "a\003") > 0, 9);
82
83   {
84     char buf1[0x40], buf2[0x40];
85     int i, j;
86     for (i=0; i < 0x10; i++)
87       for (j = 0; j < 0x10; j++)
88         {
89           int k;
90           for (k = 0; k < 0x3f; k++)
91             {
92               buf1[j] = '0' ^ (k & 4);
93               buf2[j] = '4' ^ (k & 4);
94             }
95           buf1[i] = buf1[0x3f] = 0;
96           buf2[j] = buf2[0x3f] = 0;
97           for (k = 0; k < 0xf; k++)
98             {
99               int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
100               check (strcmp (buf1+i,buf2+j) == 0, cnum);
101               buf1[i+k] = 'A' + i + k;
102               buf1[i+k+1] = 0;
103               check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
104               check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
105               buf2[j+k] = 'B' + i + k;
106               buf2[j+k+1] = 0;
107               check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
108               check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
109               buf2[j+k] = 'A' + i + k;
110               buf1[i] = 'A' + i + 0x80;
111               check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
112               check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
113               buf1[i] = 'A' + i;
114             }
115         }
116   }
117 }
118
119 #define SIMPLE_COPY(fn, n, str, ntest) \
120   do {                                                                        \
121     int __n;                                                                  \
122     char *cp;                                                                 \
123     for (__n = 0; __n < sizeof (one); ++__n)                                  \
124       one[__n] = 'Z';                                                         \
125     fn (one, str);                                                            \
126     for (cp = one, __n = 0; __n < n; ++__n, ++cp)                             \
127       check (*cp == '0' + (n % 10), ntest);                                   \
128     check (*cp == '\0', ntest);                                               \
129   } while (0)
130
131 void
132 test_strcpy (void)
133 {
134   int i;
135   it = "strcpy";
136   check (strcpy (one, "abcd") == one, 1); /* Returned value. */
137   equal (one, "abcd", 2);               /* Basic test. */
138
139   (void) strcpy (one, "x");
140   equal (one, "x", 3);                  /* Writeover. */
141   equal (one+2, "cd", 4);               /* Wrote too much? */
142
143   (void) strcpy (two, "hi there");
144   (void) strcpy (one, two);
145   equal (one, "hi there", 5);           /* Basic test encore. */
146   equal (two, "hi there", 6);           /* Stomped on source? */
147
148   (void) strcpy (one, "");
149   equal (one, "", 7);                   /* Boundary condition. */
150
151   for (i = 0; i < 16; i++)
152     {
153       (void) strcpy (one + i, "hi there");      /* Unaligned destination. */
154       equal (one + i, "hi there", 8 + (i * 2));
155       (void) strcpy (two, one + i);             /* Unaligned source. */
156       equal (two, "hi there", 9 + (i * 2));
157     }
158
159   SIMPLE_COPY(strcpy, 0, "", 41);
160   SIMPLE_COPY(strcpy, 1, "1", 42);
161   SIMPLE_COPY(strcpy, 2, "22", 43);
162   SIMPLE_COPY(strcpy, 3, "333", 44);
163   SIMPLE_COPY(strcpy, 4, "4444", 45);
164   SIMPLE_COPY(strcpy, 5, "55555", 46);
165   SIMPLE_COPY(strcpy, 6, "666666", 47);
166   SIMPLE_COPY(strcpy, 7, "7777777", 48);
167   SIMPLE_COPY(strcpy, 8, "88888888", 49);
168   SIMPLE_COPY(strcpy, 9, "999999999", 50);
169   SIMPLE_COPY(strcpy, 10, "0000000000", 51);
170   SIMPLE_COPY(strcpy, 11, "11111111111", 52);
171   SIMPLE_COPY(strcpy, 12, "222222222222", 53);
172   SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
173   SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
174   SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
175   SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
176 }
177
178 void
179 test_stpcpy (void)
180 {
181   it = "stpcpy";
182   check ((stpcpy (one, "a") - one) == 1, 1);
183   equal (one, "a", 2);
184
185   check ((stpcpy (one, "ab") - one) == 2, 3);
186   equal (one, "ab", 4);
187
188   check ((stpcpy (one, "abc") - one) == 3, 5);
189   equal (one, "abc", 6);
190
191   check ((stpcpy (one, "abcd") - one) == 4, 7);
192   equal (one, "abcd", 8);
193
194   check ((stpcpy (one, "abcde") - one) == 5, 9);
195   equal (one, "abcde", 10);
196
197   check ((stpcpy (one, "abcdef") - one) == 6, 11);
198   equal (one, "abcdef", 12);
199
200   check ((stpcpy (one, "abcdefg") - one) == 7, 13);
201   equal (one, "abcdefg", 14);
202
203   check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
204   equal (one, "abcdefgh", 16);
205
206   check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
207   equal (one, "abcdefghi", 18);
208
209   check ((stpcpy (one, "x") - one) == 1, 19);
210   equal (one, "x", 20);                 /* Writeover. */
211   equal (one+2, "cdefghi", 21);         /* Wrote too much? */
212
213   check ((stpcpy (one, "xx") - one) == 2, 22);
214   equal (one, "xx", 23);                /* Writeover. */
215   equal (one+3, "defghi", 24);          /* Wrote too much? */
216
217   check ((stpcpy (one, "xxx") - one) == 3, 25);
218   equal (one, "xxx", 26);               /* Writeover. */
219   equal (one+4, "efghi", 27);           /* Wrote too much? */
220
221   check ((stpcpy (one, "xxxx") - one) == 4, 28);
222   equal (one, "xxxx", 29);              /* Writeover. */
223   equal (one+5, "fghi", 30);            /* Wrote too much? */
224
225   check ((stpcpy (one, "xxxxx") - one) == 5, 31);
226   equal (one, "xxxxx", 32);             /* Writeover. */
227   equal (one+6, "ghi", 33);             /* Wrote too much? */
228
229   check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
230   equal (one, "xxxxxx", 35);            /* Writeover. */
231   equal (one+7, "hi", 36);              /* Wrote too much? */
232
233   check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
234   equal (one, "xxxxxxx", 38);           /* Writeover. */
235   equal (one+8, "i", 39);               /* Wrote too much? */
236
237   check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
238   equal (one, "abc", 41);
239   equal (one + 4, "xxx", 42);
240
241   SIMPLE_COPY(stpcpy, 0, "", 43);
242   SIMPLE_COPY(stpcpy, 1, "1", 44);
243   SIMPLE_COPY(stpcpy, 2, "22", 45);
244   SIMPLE_COPY(stpcpy, 3, "333", 46);
245   SIMPLE_COPY(stpcpy, 4, "4444", 47);
246   SIMPLE_COPY(stpcpy, 5, "55555", 48);
247   SIMPLE_COPY(stpcpy, 6, "666666", 49);
248   SIMPLE_COPY(stpcpy, 7, "7777777", 50);
249   SIMPLE_COPY(stpcpy, 8, "88888888", 51);
250   SIMPLE_COPY(stpcpy, 9, "999999999", 52);
251   SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
252   SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
253   SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
254   SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
255   SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
256   SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
257   SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
258 }
259
260 void
261 test_stpncpy (void)
262 {
263   it = "stpncpy";
264   memset (one, 'x', sizeof (one));
265   check (stpncpy (one, "abc", 2) == one + 2, 1);
266   check (stpncpy (one, "abc", 3) == one + 3, 2);
267   check (stpncpy (one, "abc", 4) == one + 3, 3);
268   check (one[3] == '\0' && one[4] == 'x', 4);
269   check (stpncpy (one, "abcd", 5) == one + 4, 5);
270   check (one[4] == '\0' && one[5] == 'x', 6);
271   check (stpncpy (one, "abcd", 6) == one + 4, 7);
272   check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
273 }
274
275 void
276 test_strcat (void)
277 {
278   it = "strcat";
279   (void) strcpy (one, "ijk");
280   check (strcat (one, "lmn") == one, 1); /* Returned value. */
281   equal (one, "ijklmn", 2);             /* Basic test. */
282
283   (void) strcpy (one, "x");
284   (void) strcat (one, "yz");
285   equal (one, "xyz", 3);                        /* Writeover. */
286   equal (one+4, "mn", 4);                       /* Wrote too much? */
287
288   (void) strcpy (one, "gh");
289   (void) strcpy (two, "ef");
290   (void) strcat (one, two);
291   equal (one, "ghef", 5);                       /* Basic test encore. */
292   equal (two, "ef", 6);                 /* Stomped on source? */
293
294   (void) strcpy (one, "");
295   (void) strcat (one, "");
296   equal (one, "", 7);                   /* Boundary conditions. */
297   (void) strcpy (one, "ab");
298   (void) strcat (one, "");
299   equal (one, "ab", 8);
300   (void) strcpy (one, "");
301   (void) strcat (one, "cd");
302   equal (one, "cd", 9);
303 }
304
305 void
306 test_strncat (void)
307 {
308   /* First test it as strcat, with big counts, then test the count
309      mechanism.  */
310   it = "strncat";
311   (void) strcpy (one, "ijk");
312   check (strncat (one, "lmn", 99) == one, 1);   /* Returned value. */
313   equal (one, "ijklmn", 2);             /* Basic test. */
314
315   (void) strcpy (one, "x");
316   (void) strncat (one, "yz", 99);
317   equal (one, "xyz", 3);                /* Writeover. */
318   equal (one+4, "mn", 4);               /* Wrote too much? */
319
320   (void) strcpy (one, "gh");
321   (void) strcpy (two, "ef");
322   (void) strncat (one, two, 99);
323   equal (one, "ghef", 5);                       /* Basic test encore. */
324   equal (two, "ef", 6);                 /* Stomped on source? */
325
326   (void) strcpy (one, "");
327   (void) strncat (one, "", 99);
328   equal (one, "", 7);                   /* Boundary conditions. */
329   (void) strcpy (one, "ab");
330   (void) strncat (one, "", 99);
331   equal (one, "ab", 8);
332   (void) strcpy (one, "");
333   (void) strncat (one, "cd", 99);
334   equal (one, "cd", 9);
335
336   (void) strcpy (one, "ab");
337   (void) strncat (one, "cdef", 2);
338   equal (one, "abcd", 10);                      /* Count-limited. */
339
340   (void) strncat (one, "gh", 0);
341   equal (one, "abcd", 11);                      /* Zero count. */
342
343   (void) strncat (one, "gh", 2);
344   equal (one, "abcdgh", 12);            /* Count and length equal. */
345 }
346
347 void
348 test_strncmp (void)
349 {
350   /* First test as strcmp with big counts, then test count code.  */
351   it = "strncmp";
352   check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
353   check (strncmp ("a", "a", 99) == 0, 2);       /* Identity. */
354   check (strncmp ("abc", "abc", 99) == 0, 3);   /* Multicharacter. */
355   check (strncmp ("abc", "abcd", 99) < 0, 4);   /* Length unequal. */
356   check (strncmp ("abcd", "abc", 99) > 0, 5);
357   check (strncmp ("abcd", "abce", 99) < 0, 6);  /* Honestly unequal. */
358   check (strncmp ("abce", "abcd", 99) > 0, 7);
359   check (strncmp ("a\203", "a", 2) > 0, 8);     /* Tricky if '\203' < 0 */
360   check (strncmp ("a\203", "a\003", 2) > 0, 9);
361   check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
362   check (strncmp ("abce", "abc", 3) == 0, 11);  /* Count == length. */
363   check (strncmp ("abcd", "abce", 4) < 0, 12);  /* Nudging limit. */
364   check (strncmp ("abc", "def", 0) == 0, 13);   /* Zero count. */
365 }
366
367 void
368 test_strncpy (void)
369 {
370   /* Testing is a bit different because of odd semantics.  */
371   it = "strncpy";
372   check (strncpy (one, "abc", 4) == one, 1);    /* Returned value. */
373   equal (one, "abc", 2);                        /* Did the copy go right? */
374
375   (void) strcpy (one, "abcdefgh");
376   (void) strncpy (one, "xyz", 2);
377   equal (one, "xycdefgh", 3);                   /* Copy cut by count. */
378
379   (void) strcpy (one, "abcdefgh");
380   (void) strncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
381   equal (one, "xyzdefgh", 4);
382
383   (void) strcpy (one, "abcdefgh");
384   (void) strncpy (one, "xyz", 4);               /* Copy just includes NUL. */
385   equal (one, "xyz", 5);
386   equal (one+4, "efgh", 6);                     /* Wrote too much? */
387
388   (void) strcpy (one, "abcdefgh");
389   (void) strncpy (one, "xyz", 5);               /* Copy includes padding. */
390   equal (one, "xyz", 7);
391   equal (one+4, "", 8);
392   equal (one+5, "fgh", 9);
393
394   (void) strcpy (one, "abc");
395   (void) strncpy (one, "xyz", 0);               /* Zero-length copy. */
396   equal (one, "abc", 10);
397
398   (void) strncpy (one, "", 2);          /* Zero-length source. */
399   equal (one, "", 11);
400   equal (one+1, "", 12);
401   equal (one+2, "c", 13);
402
403   (void) strcpy (one, "hi there");
404   (void) strncpy (two, one, 9);
405   equal (two, "hi there", 14);          /* Just paranoia. */
406   equal (one, "hi there", 15);          /* Stomped on source? */
407 }
408
409 void
410 test_strlen (void)
411 {
412   it = "strlen";
413   check (strlen ("") == 0, 1);          /* Empty. */
414   check (strlen ("a") == 1, 2);         /* Single char. */
415   check (strlen ("abcd") == 4, 3);      /* Multiple chars. */
416   {
417     char buf[4096];
418     int i;
419     char *p;
420     for (i=0; i < 0x100; i++)
421       {
422         p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
423         strcpy (p, "OK");
424         strcpy (p+3, "BAD/WRONG");
425         check (strlen (p) == 2, 4+i);
426       }
427    }
428 }
429
430 void
431 test_strchr (void)
432 {
433   it = "strchr";
434   check (strchr ("abcd", 'z') == NULL, 1);      /* Not found. */
435   (void) strcpy (one, "abcd");
436   check (strchr (one, 'c') == one+2, 2);        /* Basic test. */
437   check (strchr (one, 'd') == one+3, 3);        /* End of string. */
438   check (strchr (one, 'a') == one, 4);          /* Beginning. */
439   check (strchr (one, '\0') == one+4, 5);       /* Finding NUL. */
440   (void) strcpy (one, "ababa");
441   check (strchr (one, 'b') == one+1, 6);        /* Finding first. */
442   (void) strcpy (one, "");
443   check (strchr (one, 'b') == NULL, 7);         /* Empty string. */
444   check (strchr (one, '\0') == one, 8);         /* NUL in empty string. */
445   {
446     char buf[4096];
447     int i;
448     char *p;
449     for (i=0; i < 0x100; i++)
450       {
451         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
452         strcpy (p, "OK");
453         strcpy (p+3, "BAD/WRONG");
454         check (strchr (p, '/') == NULL, 9+i);
455       }
456    }
457 }
458
459 void
460 test_strchrnul (void)
461 {
462   const char *os;
463   it = "strchrnul";
464   cp = strchrnul ((os = "abcd"), 'z');
465   check (*cp == '\0', 1);                       /* Not found. */
466   check (cp == os + 4, 2);
467   (void) strcpy (one, "abcd");
468   check (strchrnul (one, 'c') == one+2, 3);     /* Basic test. */
469   check (strchrnul (one, 'd') == one+3, 4);     /* End of string. */
470   check (strchrnul (one, 'a') == one, 5);       /* Beginning. */
471   check (strchrnul (one, '\0') == one+4, 6);    /* Finding NUL. */
472   (void) strcpy (one, "ababa");
473   check (strchrnul (one, 'b') == one+1, 7);     /* Finding first. */
474   (void) strcpy (one, "");
475   check (strchrnul (one, 'b') == one, 8);       /* Empty string. */
476   check (strchrnul (one, '\0') == one, 9);      /* NUL in empty string. */
477   {
478     char buf[4096];
479     int i;
480     char *p;
481     for (i=0; i < 0x100; i++)
482       {
483         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
484         strcpy (p, "OK");
485         strcpy (p+3, "BAD/WRONG");
486         cp = strchrnul (p, '/');
487         check (*cp == '\0', 9+2*i);
488         check (cp == p+2, 10+2*i);
489       }
490    }
491 }
492
493 void
494 test_rawmemchr (void)
495 {
496   it = "rawmemchr";
497   (void) strcpy (one, "abcd");
498   check (rawmemchr (one, 'c') == one+2, 1);     /* Basic test. */
499   check (rawmemchr (one, 'd') == one+3, 2);     /* End of string. */
500   check (rawmemchr (one, 'a') == one, 3);               /* Beginning. */
501   check (rawmemchr (one, '\0') == one+4, 4);    /* Finding NUL. */
502   (void) strcpy (one, "ababa");
503   check (rawmemchr (one, 'b') == one+1, 5);     /* Finding first. */
504   (void) strcpy (one, "");
505   check (rawmemchr (one, '\0') == one, 6);      /* NUL in empty string. */
506   {
507     char buf[4096];
508     int i;
509     char *p;
510     for (i=0; i < 0x100; i++)
511       {
512         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
513         strcpy (p, "OK");
514         strcpy (p+3, "BAD/WRONG");
515         check (rawmemchr (p, 'R') == p+8, 6+i);
516       }
517    }
518 }
519
520 void
521 test_index (void)
522 {
523   it = "index";
524   check (index ("abcd", 'z') == NULL, 1);       /* Not found. */
525   (void) strcpy (one, "abcd");
526   check (index (one, 'c') == one+2, 2); /* Basic test. */
527   check (index (one, 'd') == one+3, 3); /* End of string. */
528   check (index (one, 'a') == one, 4);   /* Beginning. */
529   check (index (one, '\0') == one+4, 5);        /* Finding NUL. */
530   (void) strcpy (one, "ababa");
531   check (index (one, 'b') == one+1, 6); /* Finding first. */
532   (void) strcpy (one, "");
533   check (index (one, 'b') == NULL, 7);  /* Empty string. */
534   check (index (one, '\0') == one, 8);  /* NUL in empty string. */
535 }
536
537 void
538 test_strrchr (void)
539 {
540   it = "strrchr";
541   check (strrchr ("abcd", 'z') == NULL, 1);     /* Not found. */
542   (void) strcpy (one, "abcd");
543   check (strrchr (one, 'c') == one+2, 2);       /* Basic test. */
544   check (strrchr (one, 'd') == one+3, 3);       /* End of string. */
545   check (strrchr (one, 'a') == one, 4);         /* Beginning. */
546   check (strrchr (one, '\0') == one+4, 5);      /* Finding NUL. */
547   (void) strcpy (one, "ababa");
548   check (strrchr (one, 'b') == one+3, 6);       /* Finding last. */
549   (void) strcpy (one, "");
550   check (strrchr (one, 'b') == NULL, 7);        /* Empty string. */
551   check (strrchr (one, '\0') == one, 8);        /* NUL in empty string. */
552   {
553     char buf[4096];
554     int i;
555     char *p;
556     for (i=0; i < 0x100; i++)
557       {
558         p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
559         strcpy (p, "OK");
560         strcpy (p+3, "BAD/WRONG");
561         check (strrchr (p, '/') == NULL, 9+i);
562       }
563    }
564 }
565
566 void
567 test_memrchr (void)
568 {
569   size_t l;
570   it = "memrchr";
571   check (memrchr ("abcd", 'z', 5) == NULL, 1);  /* Not found. */
572   (void) strcpy (one, "abcd");
573   l = strlen (one) + 1;
574   check (memrchr (one, 'c', l) == one+2, 2);    /* Basic test. */
575   check (memrchr (one, 'd', l) == one+3, 3);    /* End of string. */
576   check (memrchr (one, 'a', l) == one, 4);              /* Beginning. */
577   check (memrchr (one, '\0', l) == one+4, 5);   /* Finding NUL. */
578   (void) strcpy (one, "ababa");
579   l = strlen (one) + 1;
580   check (memrchr (one, 'b', l) == one+3, 6);    /* Finding last. */
581   (void) strcpy (one, "");
582   l = strlen (one) + 1;
583   check (memrchr (one, 'b', l) == NULL, 7);     /* Empty string. */
584   check (memrchr (one, '\0', l) == one, 8);     /* NUL in empty string. */
585
586   /* now test all possible alignment and length combinations to catch
587      bugs due to unrolled loops (assuming unrolling is limited to no
588      more than 128 byte chunks: */
589   {
590     char buf[128 + sizeof(long)];
591     long align, len, i, pos;
592
593     for (align = 0; align < (long) sizeof(long); ++align) {
594       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
595         for (i = 0; i < len; ++i)
596           buf[align + i] = 'x';         /* don't depend on memset... */
597
598         for (pos = len - 1; pos >= 0; --pos) {
599 #if 0
600           printf("align %d, len %d, pos %d\n", align, len, pos);
601 #endif
602           check(memrchr(buf + align, 'x', len) == buf + align + pos, 9);
603           check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
604                 10);
605           buf[align + pos] = '-';
606         }
607       }
608     }
609   }
610 }
611
612 void
613 test_rindex (void)
614 {
615   it = "rindex";
616   check (rindex ("abcd", 'z') == NULL, 1);      /* Not found. */
617   (void) strcpy (one, "abcd");
618   check (rindex (one, 'c') == one+2, 2);        /* Basic test. */
619   check (rindex (one, 'd') == one+3, 3);        /* End of string. */
620   check (rindex (one, 'a') == one, 4);  /* Beginning. */
621   check (rindex (one, '\0') == one+4, 5);       /* Finding NUL. */
622   (void) strcpy (one, "ababa");
623   check (rindex (one, 'b') == one+3, 6);        /* Finding last. */
624   (void) strcpy (one, "");
625   check (rindex (one, 'b') == NULL, 7); /* Empty string. */
626   check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
627 }
628
629 void
630 test_strpbrk (void)
631 {
632   it = "strpbrk";
633   check(strpbrk("abcd", "z") == NULL, 1);       /* Not found. */
634   (void) strcpy(one, "abcd");
635   check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
636   check(strpbrk(one, "d") == one+3, 3); /* End of string. */
637   check(strpbrk(one, "a") == one, 4);   /* Beginning. */
638   check(strpbrk(one, "") == NULL, 5);   /* Empty search list. */
639   check(strpbrk(one, "cb") == one+1, 6);        /* Multiple search. */
640   (void) strcpy(one, "abcabdea");
641   check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
642   check(strpbrk(one, "cb") == one+1, 8);        /* With multiple search. */
643   check(strpbrk(one, "db") == one+1, 9);        /* Another variant. */
644   (void) strcpy(one, "");
645   check(strpbrk(one, "bc") == NULL, 10);        /* Empty string. */
646   (void) strcpy(one, "");
647   check(strpbrk(one, "bcd") == NULL, 11);       /* Empty string. */
648   (void) strcpy(one, "");
649   check(strpbrk(one, "bcde") == NULL, 12);      /* Empty string. */
650   check(strpbrk(one, "") == NULL, 13);  /* Both strings empty. */
651   (void) strcpy(one, "abcabdea");
652   check(strpbrk(one, "befg") == one+1, 14);     /* Finding first. */
653   check(strpbrk(one, "cbr") == one+1, 15);      /* With multiple search. */
654   check(strpbrk(one, "db") == one+1, 16);       /* Another variant. */
655   check(strpbrk(one, "efgh") == one+6, 17);     /* And yet another. */
656 }
657
658 void
659 test_strstr (void)
660 {
661   it = "strstr";
662   check(strstr("abcd", "z") == NULL, 1);        /* Not found. */
663   check(strstr("abcd", "abx") == NULL, 2);      /* Dead end. */
664   (void) strcpy(one, "abcd");
665   check(strstr(one, "c") == one+2, 3);  /* Basic test. */
666   check(strstr(one, "bc") == one+1, 4); /* Multichar. */
667   check(strstr(one, "d") == one+3, 5);  /* End of string. */
668   check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
669   check(strstr(one, "abc") == one, 7);  /* Beginning. */
670   check(strstr(one, "abcd") == one, 8); /* Exact match. */
671   check(strstr(one, "abcde") == NULL, 9);       /* Too long. */
672   check(strstr(one, "de") == NULL, 10); /* Past end. */
673   check(strstr(one, "") == one, 11);    /* Finding empty. */
674   (void) strcpy(one, "ababa");
675   check(strstr(one, "ba") == one+1, 12);        /* Finding first. */
676   (void) strcpy(one, "");
677   check(strstr(one, "b") == NULL, 13);  /* Empty string. */
678   check(strstr(one, "") == one, 14);    /* Empty in empty string. */
679   (void) strcpy(one, "bcbca");
680   check(strstr(one, "bca") == one+2, 15);       /* False start. */
681   (void) strcpy(one, "bbbcabbca");
682   check(strstr(one, "bbca") == one+1, 16);      /* With overlap. */
683 }
684
685 void
686 test_strspn (void)
687 {
688   it = "strspn";
689   check(strspn("abcba", "abc") == 5, 1);        /* Whole string. */
690   check(strspn("abcba", "ab") == 2, 2); /* Partial. */
691   check(strspn("abc", "qx") == 0, 3);   /* None. */
692   check(strspn("", "ab") == 0, 4);      /* Null string. */
693   check(strspn("abc", "") == 0, 5);     /* Null search list. */
694 }
695
696 void
697 test_strcspn (void)
698 {
699   it = "strcspn";
700   check(strcspn("abcba", "qx") == 5, 1);        /* Whole string. */
701   check(strcspn("abcba", "cx") == 2, 2);        /* Partial. */
702   check(strcspn("abc", "abc") == 0, 3); /* None. */
703   check(strcspn("", "ab") == 0, 4);     /* Null string. */
704   check(strcspn("abc", "") == 3, 5);    /* Null search list. */
705 }
706
707 void
708 test_strtok (void)
709 {
710   it = "strtok";
711   (void) strcpy(one, "first, second, third");
712   equal(strtok(one, ", "), "first", 1); /* Basic test. */
713   equal(one, "first", 2);
714   equal(strtok((char *)NULL, ", "), "second", 3);
715   equal(strtok((char *)NULL, ", "), "third", 4);
716   check(strtok((char *)NULL, ", ") == NULL, 5);
717   (void) strcpy(one, ", first, ");
718   equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
719   check(strtok((char *)NULL, ", ") == NULL, 7);
720   (void) strcpy(one, "1a, 1b; 2a, 2b");
721   equal(strtok(one, ", "), "1a", 8);    /* Changing delim lists. */
722   equal(strtok((char *)NULL, "; "), "1b", 9);
723   equal(strtok((char *)NULL, ", "), "2a", 10);
724   (void) strcpy(two, "x-y");
725   equal(strtok(two, "-"), "x", 11);     /* New string before done. */
726   equal(strtok((char *)NULL, "-"), "y", 12);
727   check(strtok((char *)NULL, "-") == NULL, 13);
728   (void) strcpy(one, "a,b, c,, ,d");
729   equal(strtok(one, ", "), "a", 14);    /* Different separators. */
730   equal(strtok((char *)NULL, ", "), "b", 15);
731   equal(strtok((char *)NULL, " ,"), "c", 16);   /* Permute list too. */
732   equal(strtok((char *)NULL, " ,"), "d", 17);
733   check(strtok((char *)NULL, ", ") == NULL, 18);
734   check(strtok((char *)NULL, ", ") == NULL, 19);        /* Persistence. */
735   (void) strcpy(one, ", ");
736   check(strtok(one, ", ") == NULL, 20); /* No tokens. */
737   (void) strcpy(one, "");
738   check(strtok(one, ", ") == NULL, 21); /* Empty string. */
739   (void) strcpy(one, "abc");
740   equal(strtok(one, ", "), "abc", 22);  /* No delimiters. */
741   check(strtok((char *)NULL, ", ") == NULL, 23);
742   (void) strcpy(one, "abc");
743   equal(strtok(one, ""), "abc", 24);    /* Empty delimiter list. */
744   check(strtok((char *)NULL, "") == NULL, 25);
745   (void) strcpy(one, "abcdefgh");
746   (void) strcpy(one, "a,b,c");
747   equal(strtok(one, ","), "a", 26);     /* Basics again... */
748   equal(strtok((char *)NULL, ","), "b", 27);
749   equal(strtok((char *)NULL, ","), "c", 28);
750   check(strtok((char *)NULL, ",") == NULL, 29);
751   equal(one+6, "gh", 30);                       /* Stomped past end? */
752   equal(one, "a", 31);                  /* Stomped old tokens? */
753   equal(one+2, "b", 32);
754   equal(one+4, "c", 33);
755 }
756
757 void
758 test_strtok_r (void)
759 {
760   it = "strtok_r";
761   (void) strcpy(one, "first, second, third");
762   equal(strtok_r(one, ", ", &cp), "first", 1);  /* Basic test. */
763   equal(one, "first", 2);
764   equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
765   equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
766   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
767   (void) strcpy(one, ", first, ");
768   equal(strtok_r(one, ", ", &cp), "first", 6);  /* Extra delims, 1 tok. */
769   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
770   (void) strcpy(one, "1a, 1b; 2a, 2b");
771   equal(strtok_r(one, ", ", &cp), "1a", 8);     /* Changing delim lists. */
772   equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
773   equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
774   (void) strcpy(two, "x-y");
775   equal(strtok_r(two, "-", &cp), "x", 11);      /* New string before done. */
776   equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
777   check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
778   (void) strcpy(one, "a,b, c,, ,d");
779   equal(strtok_r(one, ", ", &cp), "a", 14);     /* Different separators. */
780   equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
781   equal(strtok_r((char *)NULL, " ,", &cp), "c", 16);    /* Permute list too. */
782   equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
783   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
784   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
785   (void) strcpy(one, ", ");
786   check(strtok_r(one, ", ", &cp) == NULL, 20);  /* No tokens. */
787   (void) strcpy(one, "");
788   check(strtok_r(one, ", ", &cp) == NULL, 21);  /* Empty string. */
789   (void) strcpy(one, "abc");
790   equal(strtok_r(one, ", ", &cp), "abc", 22);   /* No delimiters. */
791   check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23);
792   (void) strcpy(one, "abc");
793   equal(strtok_r(one, "", &cp), "abc", 24);     /* Empty delimiter list. */
794   check(strtok_r((char *)NULL, "", &cp) == NULL, 25);
795   (void) strcpy(one, "abcdefgh");
796   (void) strcpy(one, "a,b,c");
797   equal(strtok_r(one, ",", &cp), "a", 26);      /* Basics again... */
798   equal(strtok_r((char *)NULL, ",", &cp), "b", 27);
799   equal(strtok_r((char *)NULL, ",", &cp), "c", 28);
800   check(strtok_r((char *)NULL, ",", &cp) == NULL, 29);
801   equal(one+6, "gh", 30);                       /* Stomped past end? */
802   equal(one, "a", 31);                  /* Stomped old tokens? */
803   equal(one+2, "b", 32);
804   equal(one+4, "c", 33);
805 }
806
807 void
808 test_strsep (void)
809 {
810   it = "strsep";
811   cp = strcpy(one, "first, second, third");
812   equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
813   equal(one, "first", 2);
814   equal(strsep(&cp, ", "), "", 3);
815   equal(strsep(&cp, ", "), "second", 4);
816   equal(strsep(&cp, ", "), "", 5);
817   equal(strsep(&cp, ", "), "third", 6);
818   check(strsep(&cp, ", ") == NULL, 7);
819   cp = strcpy(one, ", first, ");
820   equal(strsep(&cp, ", "), "", 8);
821   equal(strsep(&cp, ", "), "", 9);
822   equal(strsep(&cp, ", "), "first", 10);        /* Extra delims, 1 tok. */
823   equal(strsep(&cp, ", "), "", 11);
824   equal(strsep(&cp, ", "), "", 12);
825   check(strsep(&cp, ", ") == NULL, 13);
826   cp = strcpy(one, "1a, 1b; 2a, 2b");
827   equal(strsep(&cp, ", "), "1a", 14);   /* Changing delim lists. */
828   equal(strsep(&cp, ", "), "", 15);
829   equal(strsep(&cp, "; "), "1b", 16);
830   equal(strsep(&cp, ", "), "", 17);
831   equal(strsep(&cp, ", "), "2a", 18);
832   cp = strcpy(two, "x-y");
833   equal(strsep(&cp, "-"), "x", 19);     /* New string before done. */
834   equal(strsep(&cp, "-"), "y", 20);
835   check(strsep(&cp, "-") == NULL, 21);
836   cp = strcpy(one, "a,b, c,, ,d ");
837   equal(strsep(&cp, ", "), "a", 22);    /* Different separators. */
838   equal(strsep(&cp, ", "), "b", 23);
839   equal(strsep(&cp, " ,"), "", 24);
840   equal(strsep(&cp, " ,"), "c", 25);    /* Permute list too. */
841   equal(strsep(&cp, " ,"), "", 26);
842   equal(strsep(&cp, " ,"), "", 27);
843   equal(strsep(&cp, " ,"), "", 28);
844   equal(strsep(&cp, " ,"), "d", 29);
845   equal(strsep(&cp, " ,"), "", 30);
846   check(strsep(&cp, ", ") == NULL, 31);
847   check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
848   cp = strcpy(one, ", ");
849   equal(strsep(&cp, ", "), "", 33);
850   equal(strsep(&cp, ", "), "", 34);
851   equal(strsep(&cp, ", "), "", 35);
852   check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
853   cp = strcpy(one, "");
854   equal(strsep(&cp, ", "), "", 37);
855   check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
856   cp = strcpy(one, "abc");
857   equal(strsep(&cp, ", "), "abc", 39);  /* No delimiters. */
858   check(strsep(&cp, ", ") == NULL, 40);
859   cp = strcpy(one, "abc");
860   equal(strsep(&cp, ""), "abc", 41);    /* Empty delimiter list. */
861   check(strsep(&cp, "") == NULL, 42);
862   (void) strcpy(one, "abcdefgh");
863   cp = strcpy(one, "a,b,c");
864   equal(strsep(&cp, ","), "a", 43);     /* Basics again... */
865   equal(strsep(&cp, ","), "b", 44);
866   equal(strsep(&cp, ","), "c", 45);
867   check(strsep(&cp, ",") == NULL, 46);
868   equal(one+6, "gh", 47);               /* Stomped past end? */
869   equal(one, "a", 48);                  /* Stomped old tokens? */
870   equal(one+2, "b", 49);
871   equal(one+4, "c", 50);
872
873   {
874     char text[] = "This,is,a,test";
875     char *list = strdupa (text);
876     equal (strsep (&list, ","), "This", 51);
877     equal (strsep (&list, ","), "is", 52);
878     equal (strsep (&list, ","), "a", 53);
879     equal (strsep (&list, ","), "test", 54);
880     check (strsep (&list, ",") == NULL, 55);
881   }
882
883   cp = strcpy(one, "a,b, c,, ,d,");
884   equal(strsep(&cp, ","), "a", 56);     /* Different separators. */
885   equal(strsep(&cp, ","), "b", 57);
886   equal(strsep(&cp, ","), " c", 58);    /* Permute list too. */
887   equal(strsep(&cp, ","), "", 59);
888   equal(strsep(&cp, ","), " ", 60);
889   equal(strsep(&cp, ","), "d", 61);
890   equal(strsep(&cp, ","), "", 62);
891   check(strsep(&cp, ",") == NULL, 63);
892   check(strsep(&cp, ",") == NULL, 64);  /* Persistence. */
893
894   cp = strcpy(one, "a,b, c,, ,d,");
895   equal(strsep(&cp, "xy,"), "a", 65);   /* Different separators. */
896   equal(strsep(&cp, "x,y"), "b", 66);
897   equal(strsep(&cp, ",xy"), " c", 67);  /* Permute list too. */
898   equal(strsep(&cp, "xy,"), "", 68);
899   equal(strsep(&cp, "x,y"), " ", 69);
900   equal(strsep(&cp, ",xy"), "d", 70);
901   equal(strsep(&cp, "xy,"), "", 71);
902   check(strsep(&cp, "x,y") == NULL, 72);
903   check(strsep(&cp, ",xy") == NULL, 73);        /* Persistence. */
904 }
905
906 void
907 test_memcmp (void)
908 {
909   it = "memcmp";
910   check(memcmp("a", "a", 1) == 0, 1);           /* Identity. */
911   check(memcmp("abc", "abc", 3) == 0, 2);       /* Multicharacter. */
912   check(memcmp("abcd", "abce", 4) < 0, 3);      /* Honestly unequal. */
913   check(memcmp("abce", "abcd", 4) > 0, 4);
914   check(memcmp("alph", "beta", 4) < 0, 5);
915   check(memcmp("a\203", "a\003", 2) > 0, 6);
916   check(memcmp("abce", "abcd", 3) == 0, 7);     /* Count limited. */
917   check(memcmp("abc", "def", 0) == 0, 8);       /* Zero count. */
918 }
919
920 void
921 test_memchr (void)
922 {
923   it = "memchr";
924   check(memchr("abcd", 'z', 4) == NULL, 1);     /* Not found. */
925   (void) strcpy(one, "abcd");
926   check(memchr(one, 'c', 4) == one+2, 2);       /* Basic test. */
927   check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
928   check(memchr(one, 'd', 4) == one+3, 3);       /* End of string. */
929   check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
930   check(memchr(one, '\0', 5) == one+4, 5);      /* Finding NUL. */
931   (void) strcpy(one, "ababa");
932   check(memchr(one, 'b', 5) == one+1, 6);       /* Finding first. */
933   check(memchr(one, 'b', 0) == NULL, 7);        /* Zero count. */
934   check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
935   (void) strcpy(one, "a\203b");
936   check(memchr(one, 0203, 3) == one+1, 9);      /* Unsignedness. */
937
938   /* now test all possible alignment and length combinations to catch
939      bugs due to unrolled loops (assuming unrolling is limited to no
940      more than 128 byte chunks: */
941   {
942     char buf[128 + sizeof(long)];
943     long align, len, i, pos;
944
945     for (align = 0; align < (long) sizeof(long); ++align) {
946       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
947         for (i = 0; i < len; ++i) {
948           buf[align + i] = 'x';         /* don't depend on memset... */
949         }
950         for (pos = 0; pos < len; ++pos) {
951 #if 0
952           printf("align %d, len %d, pos %d\n", align, len, pos);
953 #endif
954           check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
955           check(memchr(buf + align, 'x', pos) == NULL, 11);
956           buf[align + pos] = '-';
957         }
958       }
959     }
960   }
961 }
962
963 void
964 test_memcpy (void)
965 {
966   it = "memcpy";
967   check(memcpy(one, "abc", 4) == one, 1);       /* Returned value. */
968   equal(one, "abc", 2);                 /* Did the copy go right? */
969
970   (void) strcpy(one, "abcdefgh");
971   (void) memcpy(one+1, "xyz", 2);
972   equal(one, "axydefgh", 3);            /* Basic test. */
973
974   (void) strcpy(one, "abc");
975   (void) memcpy(one, "xyz", 0);
976   equal(one, "abc", 4);                 /* Zero-length copy. */
977
978   (void) strcpy(one, "hi there");
979   (void) strcpy(two, "foo");
980   (void) memcpy(two, one, 9);
981   equal(two, "hi there", 5);            /* Just paranoia. */
982   equal(one, "hi there", 6);            /* Stomped on source? */
983 }
984
985 void
986 test_memmove (void)
987 {
988   it = "memmove";
989   check(memmove(one, "abc", 4) == one, 1);      /* Returned value. */
990   equal(one, "abc", 2);                 /* Did the copy go right? */
991
992   (void) strcpy(one, "abcdefgh");
993   (void) memmove(one+1, "xyz", 2);
994   equal(one, "axydefgh", 3);            /* Basic test. */
995
996   (void) strcpy(one, "abc");
997   (void) memmove(one, "xyz", 0);
998   equal(one, "abc", 4);                 /* Zero-length copy. */
999
1000   (void) strcpy(one, "hi there");
1001   (void) strcpy(two, "foo");
1002   (void) memmove(two, one, 9);
1003   equal(two, "hi there", 5);            /* Just paranoia. */
1004   equal(one, "hi there", 6);            /* Stomped on source? */
1005
1006   (void) strcpy(one, "abcdefgh");
1007   (void) memmove(one+1, one, 9);
1008   equal(one, "aabcdefgh", 7);           /* Overlap, right-to-left. */
1009
1010   (void) strcpy(one, "abcdefgh");
1011   (void) memmove(one+1, one+2, 7);
1012   equal(one, "acdefgh", 8);             /* Overlap, left-to-right. */
1013
1014   (void) strcpy(one, "abcdefgh");
1015   (void) memmove(one, one, 9);
1016   equal(one, "abcdefgh", 9);            /* 100% overlap. */
1017 }
1018
1019 void
1020 test_memccpy (void)
1021 {
1022   /* First test like memcpy, then the search part The SVID, the only
1023      place where memccpy is mentioned, says overlap might fail, so we
1024      don't try it.  Besides, it's hard to see the rationale for a
1025      non-left-to-right memccpy.  */
1026   it = "memccpy";
1027   check(memccpy(one, "abc", 'q', 4) == NULL, 1);        /* Returned value. */
1028   equal(one, "abc", 2);                 /* Did the copy go right? */
1029
1030   (void) strcpy(one, "abcdefgh");
1031   (void) memccpy(one+1, "xyz", 'q', 2);
1032   equal(one, "axydefgh", 3);            /* Basic test. */
1033
1034   (void) strcpy(one, "abc");
1035   (void) memccpy(one, "xyz", 'q', 0);
1036   equal(one, "abc", 4);                 /* Zero-length copy. */
1037
1038   (void) strcpy(one, "hi there");
1039   (void) strcpy(two, "foo");
1040   (void) memccpy(two, one, 'q', 9);
1041   equal(two, "hi there", 5);            /* Just paranoia. */
1042   equal(one, "hi there", 6);            /* Stomped on source? */
1043
1044   (void) strcpy(one, "abcdefgh");
1045   (void) strcpy(two, "horsefeathers");
1046   check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1047   equal(one, "abcdefgh", 8);            /* Source intact? */
1048   equal(two, "abcdefeathers", 9);               /* Copy correct? */
1049
1050   (void) strcpy(one, "abcd");
1051   (void) strcpy(two, "bumblebee");
1052   check(memccpy(two, one, 'a', 4) == two+1, 10);        /* First char. */
1053   equal(two, "aumblebee", 11);
1054   check(memccpy(two, one, 'd', 4) == two+4, 12);        /* Last char. */
1055   equal(two, "abcdlebee", 13);
1056   (void) strcpy(one, "xyz");
1057   check(memccpy(two, one, 'x', 1) == two+1, 14);        /* Singleton. */
1058   equal(two, "xbcdlebee", 15);
1059 }
1060
1061 void
1062 test_memset (void)
1063 {
1064   int i;
1065
1066   it = "memset";
1067   (void) strcpy(one, "abcdefgh");
1068   check(memset(one+1, 'x', 3) == one+1, 1);     /* Return value. */
1069   equal(one, "axxxefgh", 2);            /* Basic test. */
1070
1071   (void) memset(one+2, 'y', 0);
1072   equal(one, "axxxefgh", 3);            /* Zero-length set. */
1073
1074   (void) memset(one+5, 0, 1);
1075   equal(one, "axxxe", 4);                       /* Zero fill. */
1076   equal(one+6, "gh", 5);                        /* And the leftover. */
1077
1078   (void) memset(one+2, 010045, 1);
1079   equal(one, "ax\045xe", 6);            /* Unsigned char convert. */
1080
1081   /* Non-8bit fill character.  */
1082   memset (one, 0x101, sizeof (one));
1083   for (i = 0; i < sizeof (one); ++i)
1084     check (one[i] == '\01', 7);
1085
1086   /* Test for more complex versions of memset, for all alignments and
1087      lengths up to 256. This test takes a little while, perhaps it should
1088      be made weaker?  */
1089   {
1090     char data[512];
1091     int j;
1092     int k;
1093     int c;
1094
1095     for (i = 0; i < 512; i++)
1096       data[i] = 'x';
1097     for (c = 0; c <= 'y'; c += 'y')  /* check for memset(,0,) and
1098                                         memset(,'y',) */
1099       for (j = 0; j < 256; j++)
1100         for (i = 0; i < 256; i++)
1101           {
1102             memset (data + i, c, j);
1103             for (k = 0; k < i; k++)
1104               if (data[k] != 'x')
1105                 goto fail;
1106             for (k = i; k < i+j; k++)
1107               {
1108                 if (data[k] != c)
1109                   goto fail;
1110                 data[k] = 'x';
1111               }
1112             for (k = i+j; k < 512; k++)
1113               if (data[k] != 'x')
1114                 goto fail;
1115             continue;
1116
1117           fail:
1118             check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1119           }
1120   }
1121 }
1122
1123 void
1124 test_bcopy (void)
1125 {
1126   /* Much like memcpy.  Berklix manual is silent about overlap, so
1127      don't test it.  */
1128   it = "bcopy";
1129   (void) bcopy("abc", one, 4);
1130   equal(one, "abc", 1);                 /* Simple copy. */
1131
1132   (void) strcpy(one, "abcdefgh");
1133   (void) bcopy("xyz", one+1, 2);
1134   equal(one, "axydefgh", 2);            /* Basic test. */
1135
1136   (void) strcpy(one, "abc");
1137   (void) bcopy("xyz", one, 0);
1138   equal(one, "abc", 3);                 /* Zero-length copy. */
1139
1140   (void) strcpy(one, "hi there");
1141   (void) strcpy(two, "foo");
1142   (void) bcopy(one, two, 9);
1143   equal(two, "hi there", 4);            /* Just paranoia. */
1144   equal(one, "hi there", 5);            /* Stomped on source? */
1145 }
1146
1147 void
1148 test_bzero (void)
1149 {
1150   it = "bzero";
1151   (void) strcpy(one, "abcdef");
1152   bzero(one+2, 2);
1153   equal(one, "ab", 1);                  /* Basic test. */
1154   equal(one+3, "", 2);
1155   equal(one+4, "ef", 3);
1156
1157   (void) strcpy(one, "abcdef");
1158   bzero(one+2, 0);
1159   equal(one, "abcdef", 4);              /* Zero-length copy. */
1160 }
1161
1162 void
1163 test_bcmp (void)
1164 {
1165   it = "bcmp";
1166   check(bcmp("a", "a", 1) == 0, 1);     /* Identity. */
1167   check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1168   check(bcmp("abcd", "abce", 4) != 0, 3);       /* Honestly unequal. */
1169   check(bcmp("abce", "abcd", 4) != 0, 4);
1170   check(bcmp("alph", "beta", 4) != 0, 5);
1171   check(bcmp("abce", "abcd", 3) == 0, 6);       /* Count limited. */
1172   check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1173 }
1174
1175 void
1176 test_strerror (void)
1177 {
1178   int f;
1179   it = "strerror";
1180   f = __open("/", O_WRONLY);    /* Should always fail. */
1181   check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
1182   equal(strerror(errno), _sys_errlist[errno], 2);
1183 }
1184
1185 int
1186 main (void)
1187 {
1188   int status;
1189
1190   /* Test strcmp first because we use it to test other things.  */
1191   test_strcmp ();
1192
1193   /* Test strcpy next because we need it to set up other tests.  */
1194   test_strcpy ();
1195
1196   /* A closely related function is stpcpy.  */
1197   test_stpcpy ();
1198
1199   /* stpncpy.  */
1200   test_stpncpy ();
1201
1202   /* strcat.  */
1203   test_strcat ();
1204
1205   /* strncat.  */
1206   test_strncat ();
1207
1208   /* strncmp.  */
1209   test_strncmp ();
1210
1211   /* strncpy.  */
1212   test_strncpy ();
1213
1214   /* strlen.  */
1215   test_strlen ();
1216
1217   /* strchr.  */
1218   test_strchr ();
1219
1220   /* strchrnul.  */
1221   test_strchrnul ();
1222
1223   /* rawmemchr.  */
1224   test_rawmemchr ();
1225
1226   /* index - just like strchr.  */
1227   test_index ();
1228
1229   /* strrchr.  */
1230   test_strrchr ();
1231
1232   /* memrchr.  */
1233   test_memrchr ();
1234
1235   /* rindex - just like strrchr.  */
1236   test_rindex ();
1237
1238   /* strpbrk - somewhat like strchr.  */
1239   test_strpbrk ();
1240
1241   /* strstr - somewhat like strchr.  */
1242   test_strstr ();
1243
1244   /* strspn.  */
1245   test_strspn ();
1246
1247   /* strcspn.  */
1248   test_strcspn ();
1249
1250   /* strtok - the hard one.  */
1251   test_strtok ();
1252
1253   /* strtok_r.  */
1254   test_strtok_r ();
1255
1256   /* strsep.  */
1257   test_strsep ();
1258
1259   /* memcmp.  */
1260   test_memcmp ();
1261
1262   /* memchr.  */
1263   test_memchr ();
1264
1265   /* memcpy - need not work for overlap.  */
1266   test_memcpy ();
1267
1268   /* memmove - must work on overlap.  */
1269   test_memmove ();
1270
1271   /* memccpy.  */
1272   test_memccpy ();
1273
1274   /* memset.  */
1275   test_memset ();
1276
1277   /* bcopy.  */
1278   test_bcopy ();
1279
1280   /* bzero.  */
1281   test_bzero ();
1282
1283   /* bcmp - somewhat like memcmp.  */
1284   test_bcmp ();
1285
1286   /* strerror - VERY system-dependent.  */
1287   test_strerror ();
1288
1289
1290   if (errors == 0)
1291     {
1292       status = EXIT_SUCCESS;
1293       puts("No errors.");
1294     }
1295   else
1296     {
1297       status = EXIT_FAILURE;
1298       printf("%Zd errors.\n", errors);
1299     }
1300   exit(status);
1301 }