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