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