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