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