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