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