Update.
[glibc.git] / string / tester.c
blobd74ab72852b69a957fe62f0807eafae7e88d1659
1 /* Tester for string functions.
2 Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE
22 #endif
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
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <fcntl.h>
37 #ifndef HAVE_GNU_LD
38 #define _sys_nerr sys_nerr
39 #define _sys_errlist sys_errlist
40 #endif
42 #define STREQ(a, b) (strcmp((a), (b)) == 0)
44 const char *it = "<UNSET>"; /* Routine name for message routines. */
45 size_t errors = 0;
47 /* Complain if condition is not true. */
48 void
49 check (int thing, int number)
51 if (!thing)
53 printf("%s flunked test %d\n", it, number);
54 ++errors;
58 /* Complain if first two args don't strcmp as equal. */
59 void
60 equal (const char *a, const char *b, int number)
62 check(a != NULL && b != NULL && STREQ (a, b), number);
65 char one[50];
66 char two[50];
67 char *cp;
69 void
70 test_strcmp (void)
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);
84 char buf1[0x40], buf2[0x40];
85 int i, j;
86 for (i=0; i < 0x10; i++)
87 for (j = 0; j < 0x10; j++)
89 int k;
90 for (k = 0; k < 0x3f; k++)
92 buf1[j] = '0' ^ (k & 4);
93 buf2[j] = '4' ^ (k & 4);
95 buf1[i] = buf1[0x3f] = 0;
96 buf2[j] = buf2[0x3f] = 0;
97 for (k = 0; k < 0xf; k++)
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;
119 void
120 test_strcpy (void)
122 it = "strcpy";
123 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
124 equal (one, "abcd", 2); /* Basic test. */
126 (void) strcpy (one, "x");
127 equal (one, "x", 3); /* Writeover. */
128 equal (one+2, "cd", 4); /* Wrote too much? */
130 (void) strcpy (two, "hi there");
131 (void) strcpy (one, two);
132 equal (one, "hi there", 5); /* Basic test encore. */
133 equal (two, "hi there", 6); /* Stomped on source? */
135 (void) strcpy (one, "");
136 equal (one, "", 7); /* Boundary condition. */
139 void
140 test_stpcpy (void)
142 it = "stpcpy";
143 check ((stpcpy (one, "a") - one) == 1, 1);
144 equal (one, "a", 2);
146 check ((stpcpy (one, "ab") - one) == 2, 3);
147 equal (one, "ab", 4);
149 check ((stpcpy (one, "abc") - one) == 3, 5);
150 equal (one, "abc", 6);
152 check ((stpcpy (one, "abcd") - one) == 4, 7);
153 equal (one, "abcd", 8);
155 check ((stpcpy (one, "abcde") - one) == 5, 9);
156 equal (one, "abcde", 10);
158 check ((stpcpy (one, "abcdef") - one) == 6, 11);
159 equal (one, "abcdef", 12);
161 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
162 equal (one, "abcdefg", 14);
164 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
165 equal (one, "abcdefgh", 16);
167 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
168 equal (one, "abcdefghi", 18);
170 check ((stpcpy (one, "x") - one) == 1, 19);
171 equal (one, "x", 20); /* Writeover. */
172 equal (one+2, "cdefghi", 21); /* Wrote too much? */
174 check ((stpcpy (one, "xx") - one) == 2, 22);
175 equal (one, "xx", 23); /* Writeover. */
176 equal (one+3, "defghi", 24); /* Wrote too much? */
178 check ((stpcpy (one, "xxx") - one) == 3, 25);
179 equal (one, "xxx", 26); /* Writeover. */
180 equal (one+4, "efghi", 27); /* Wrote too much? */
182 check ((stpcpy (one, "xxxx") - one) == 4, 28);
183 equal (one, "xxxx", 29); /* Writeover. */
184 equal (one+5, "fghi", 30); /* Wrote too much? */
186 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
187 equal (one, "xxxxx", 32); /* Writeover. */
188 equal (one+6, "ghi", 33); /* Wrote too much? */
190 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
191 equal (one, "xxxxxx", 35); /* Writeover. */
192 equal (one+7, "hi", 36); /* Wrote too much? */
194 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
195 equal (one, "xxxxxxx", 38); /* Writeover. */
196 equal (one+8, "i", 39); /* Wrote too much? */
198 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
199 equal (one, "abc", 41);
200 equal (one + 4, "xxx", 42);
203 void
204 test_stpncpy (void)
206 it = "stpncpy";
207 memset (one, 'x', sizeof (one));
208 check (stpncpy (one, "abc", 2) == one + 2, 1);
209 check (stpncpy (one, "abc", 3) == one + 3, 2);
210 check (stpncpy (one, "abc", 4) == one + 3, 3);
211 check (one[3] == '\0' && one[4] == 'x', 4);
212 check (stpncpy (one, "abcd", 5) == one + 4, 5);
213 check (one[4] == '\0' && one[5] == 'x', 6);
214 check (stpncpy (one, "abcd", 6) == one + 4, 7);
215 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
218 void
219 test_strcat (void)
221 it = "strcat";
222 (void) strcpy (one, "ijk");
223 check (strcat (one, "lmn") == one, 1); /* Returned value. */
224 equal (one, "ijklmn", 2); /* Basic test. */
226 (void) strcpy (one, "x");
227 (void) strcat (one, "yz");
228 equal (one, "xyz", 3); /* Writeover. */
229 equal (one+4, "mn", 4); /* Wrote too much? */
231 (void) strcpy (one, "gh");
232 (void) strcpy (two, "ef");
233 (void) strcat (one, two);
234 equal (one, "ghef", 5); /* Basic test encore. */
235 equal (two, "ef", 6); /* Stomped on source? */
237 (void) strcpy (one, "");
238 (void) strcat (one, "");
239 equal (one, "", 7); /* Boundary conditions. */
240 (void) strcpy (one, "ab");
241 (void) strcat (one, "");
242 equal (one, "ab", 8);
243 (void) strcpy (one, "");
244 (void) strcat (one, "cd");
245 equal (one, "cd", 9);
248 void
249 test_strncat (void)
251 /* First test it as strcat, with big counts, then test the count
252 mechanism. */
253 it = "strncat";
254 (void) strcpy (one, "ijk");
255 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
256 equal (one, "ijklmn", 2); /* Basic test. */
258 (void) strcpy (one, "x");
259 (void) strncat (one, "yz", 99);
260 equal (one, "xyz", 3); /* Writeover. */
261 equal (one+4, "mn", 4); /* Wrote too much? */
263 (void) strcpy (one, "gh");
264 (void) strcpy (two, "ef");
265 (void) strncat (one, two, 99);
266 equal (one, "ghef", 5); /* Basic test encore. */
267 equal (two, "ef", 6); /* Stomped on source? */
269 (void) strcpy (one, "");
270 (void) strncat (one, "", 99);
271 equal (one, "", 7); /* Boundary conditions. */
272 (void) strcpy (one, "ab");
273 (void) strncat (one, "", 99);
274 equal (one, "ab", 8);
275 (void) strcpy (one, "");
276 (void) strncat (one, "cd", 99);
277 equal (one, "cd", 9);
279 (void) strcpy (one, "ab");
280 (void) strncat (one, "cdef", 2);
281 equal (one, "abcd", 10); /* Count-limited. */
283 (void) strncat (one, "gh", 0);
284 equal (one, "abcd", 11); /* Zero count. */
286 (void) strncat (one, "gh", 2);
287 equal (one, "abcdgh", 12); /* Count and length equal. */
290 void
291 test_strncmp (void)
293 /* First test as strcmp with big counts, then test count code. */
294 it = "strncmp";
295 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
296 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
297 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
298 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
299 check (strncmp ("abcd", "abc", 99) > 0, 5);
300 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
301 check (strncmp ("abce", "abcd", 99) > 0, 7);
302 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
303 check (strncmp ("a\203", "a\003", 2) > 0, 9);
304 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
305 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
306 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
307 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
310 void
311 test_strncpy (void)
313 /* Testing is a bit different because of odd semantics. */
314 it = "strncpy";
315 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
316 equal (one, "abc", 2); /* Did the copy go right? */
318 (void) strcpy (one, "abcdefgh");
319 (void) strncpy (one, "xyz", 2);
320 equal (one, "xycdefgh", 3); /* Copy cut by count. */
322 (void) strcpy (one, "abcdefgh");
323 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
324 equal (one, "xyzdefgh", 4);
326 (void) strcpy (one, "abcdefgh");
327 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
328 equal (one, "xyz", 5);
329 equal (one+4, "efgh", 6); /* Wrote too much? */
331 (void) strcpy (one, "abcdefgh");
332 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
333 equal (one, "xyz", 7);
334 equal (one+4, "", 8);
335 equal (one+5, "fgh", 9);
337 (void) strcpy (one, "abc");
338 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
339 equal (one, "abc", 10);
341 (void) strncpy (one, "", 2); /* Zero-length source. */
342 equal (one, "", 11);
343 equal (one+1, "", 12);
344 equal (one+2, "c", 13);
346 (void) strcpy (one, "hi there");
347 (void) strncpy (two, one, 9);
348 equal (two, "hi there", 14); /* Just paranoia. */
349 equal (one, "hi there", 15); /* Stomped on source? */
352 void
353 test_strlen (void)
355 it = "strlen";
356 check (strlen ("") == 0, 1); /* Empty. */
357 check (strlen ("a") == 1, 2); /* Single char. */
358 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
360 char buf[4096];
361 int i;
362 char *p;
363 for (i=0; i < 0x100; i++)
365 p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
366 strcpy (p, "OK");
367 strcpy (p+3, "BAD/WRONG");
368 check (strlen (p) == 2, 4+i);
373 void
374 test_strchr (void)
376 it = "strchr";
377 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
378 (void) strcpy (one, "abcd");
379 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
380 check (strchr (one, 'd') == one+3, 3); /* End of string. */
381 check (strchr (one, 'a') == one, 4); /* Beginning. */
382 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
383 (void) strcpy (one, "ababa");
384 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
385 (void) strcpy (one, "");
386 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
387 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
389 char buf[4096];
390 int i;
391 char *p;
392 for (i=0; i < 0x100; i++)
394 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
395 strcpy (p, "OK");
396 strcpy (p+3, "BAD/WRONG");
397 check (strchr (p, '/') == NULL, 9+i);
402 void
403 test_index (void)
405 it = "index";
406 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
407 (void) strcpy (one, "abcd");
408 check (index (one, 'c') == one+2, 2); /* Basic test. */
409 check (index (one, 'd') == one+3, 3); /* End of string. */
410 check (index (one, 'a') == one, 4); /* Beginning. */
411 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
412 (void) strcpy (one, "ababa");
413 check (index (one, 'b') == one+1, 6); /* Finding first. */
414 (void) strcpy (one, "");
415 check (index (one, 'b') == NULL, 7); /* Empty string. */
416 check (index (one, '\0') == one, 8); /* NUL in empty string. */
419 void
420 test_strrchr (void)
422 it = "strrchr";
423 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
424 (void) strcpy (one, "abcd");
425 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
426 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
427 check (strrchr (one, 'a') == one, 4); /* Beginning. */
428 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
429 (void) strcpy (one, "ababa");
430 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
431 (void) strcpy (one, "");
432 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
433 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
435 char buf[4096];
436 int i;
437 char *p;
438 for (i=0; i < 0x100; i++)
440 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
441 strcpy (p, "OK");
442 strcpy (p+3, "BAD/WRONG");
443 check (strrchr (p, '/') == NULL, 9+i);
448 void
449 test_rindex (void)
451 it = "rindex";
452 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
453 (void) strcpy (one, "abcd");
454 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
455 check (rindex (one, 'd') == one+3, 3); /* End of string. */
456 check (rindex (one, 'a') == one, 4); /* Beginning. */
457 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
458 (void) strcpy (one, "ababa");
459 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
460 (void) strcpy (one, "");
461 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
462 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
465 void
466 test_strpbrk (void)
468 it = "strpbrk";
469 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
470 (void) strcpy(one, "abcd");
471 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
472 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
473 check(strpbrk(one, "a") == one, 4); /* Beginning. */
474 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
475 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
476 (void) strcpy(one, "abcabdea");
477 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
478 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
479 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
480 (void) strcpy(one, "");
481 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
482 check(strpbrk(one, "") == NULL, 11); /* Both strings empty. */
485 void
486 test_strstr (void)
488 it = "strstr";
489 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
490 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
491 (void) strcpy(one, "abcd");
492 check(strstr(one, "c") == one+2, 3); /* Basic test. */
493 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
494 check(strstr(one, "d") == one+3, 5); /* End of string. */
495 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
496 check(strstr(one, "abc") == one, 7); /* Beginning. */
497 check(strstr(one, "abcd") == one, 8); /* Exact match. */
498 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
499 check(strstr(one, "de") == NULL, 10); /* Past end. */
500 check(strstr(one, "") == one, 11); /* Finding empty. */
501 (void) strcpy(one, "ababa");
502 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
503 (void) strcpy(one, "");
504 check(strstr(one, "b") == NULL, 13); /* Empty string. */
505 check(strstr(one, "") == one, 14); /* Empty in empty string. */
506 (void) strcpy(one, "bcbca");
507 check(strstr(one, "bca") == one+2, 15); /* False start. */
508 (void) strcpy(one, "bbbcabbca");
509 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
512 void
513 test_strspn (void)
515 it = "strspn";
516 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
517 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
518 check(strspn("abc", "qx") == 0, 3); /* None. */
519 check(strspn("", "ab") == 0, 4); /* Null string. */
520 check(strspn("abc", "") == 0, 5); /* Null search list. */
523 void
524 test_strcspn (void)
526 it = "strcspn";
527 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
528 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
529 check(strcspn("abc", "abc") == 0, 3); /* None. */
530 check(strcspn("", "ab") == 0, 4); /* Null string. */
531 check(strcspn("abc", "") == 3, 5); /* Null search list. */
534 void
535 test_strtok (void)
537 it = "strtok";
538 (void) strcpy(one, "first, second, third");
539 equal(strtok(one, ", "), "first", 1); /* Basic test. */
540 equal(one, "first", 2);
541 equal(strtok((char *)NULL, ", "), "second", 3);
542 equal(strtok((char *)NULL, ", "), "third", 4);
543 check(strtok((char *)NULL, ", ") == NULL, 5);
544 (void) strcpy(one, ", first, ");
545 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
546 check(strtok((char *)NULL, ", ") == NULL, 7);
547 (void) strcpy(one, "1a, 1b; 2a, 2b");
548 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
549 equal(strtok((char *)NULL, "; "), "1b", 9);
550 equal(strtok((char *)NULL, ", "), "2a", 10);
551 (void) strcpy(two, "x-y");
552 equal(strtok(two, "-"), "x", 11); /* New string before done. */
553 equal(strtok((char *)NULL, "-"), "y", 12);
554 check(strtok((char *)NULL, "-") == NULL, 13);
555 (void) strcpy(one, "a,b, c,, ,d");
556 equal(strtok(one, ", "), "a", 14); /* Different separators. */
557 equal(strtok((char *)NULL, ", "), "b", 15);
558 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
559 equal(strtok((char *)NULL, " ,"), "d", 17);
560 check(strtok((char *)NULL, ", ") == NULL, 18);
561 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
562 (void) strcpy(one, ", ");
563 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
564 (void) strcpy(one, "");
565 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
566 (void) strcpy(one, "abc");
567 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
568 check(strtok((char *)NULL, ", ") == NULL, 23);
569 (void) strcpy(one, "abc");
570 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
571 check(strtok((char *)NULL, "") == NULL, 25);
572 (void) strcpy(one, "abcdefgh");
573 (void) strcpy(one, "a,b,c");
574 equal(strtok(one, ","), "a", 26); /* Basics again... */
575 equal(strtok((char *)NULL, ","), "b", 27);
576 equal(strtok((char *)NULL, ","), "c", 28);
577 check(strtok((char *)NULL, ",") == NULL, 29);
578 equal(one+6, "gh", 30); /* Stomped past end? */
579 equal(one, "a", 31); /* Stomped old tokens? */
580 equal(one+2, "b", 32);
581 equal(one+4, "c", 33);
584 void
585 test_strtok_r (void)
587 it = "strtok_r";
588 (void) strcpy(one, "first, second, third");
589 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
590 equal(one, "first", 2);
591 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
592 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
593 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
594 (void) strcpy(one, ", first, ");
595 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
596 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
597 (void) strcpy(one, "1a, 1b; 2a, 2b");
598 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
599 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
600 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
601 (void) strcpy(two, "x-y");
602 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
603 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
604 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
605 (void) strcpy(one, "a,b, c,, ,d");
606 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
607 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
608 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
609 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
610 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
611 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
612 (void) strcpy(one, ", ");
613 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
614 (void) strcpy(one, "");
615 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
616 (void) strcpy(one, "abc");
617 equal(strtok_r(one, ", ", &cp), "abc", 22); /* No delimiters. */
618 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23);
619 (void) strcpy(one, "abc");
620 equal(strtok_r(one, "", &cp), "abc", 24); /* Empty delimiter list. */
621 check(strtok_r((char *)NULL, "", &cp) == NULL, 25);
622 (void) strcpy(one, "abcdefgh");
623 (void) strcpy(one, "a,b,c");
624 equal(strtok_r(one, ",", &cp), "a", 26); /* Basics again... */
625 equal(strtok_r((char *)NULL, ",", &cp), "b", 27);
626 equal(strtok_r((char *)NULL, ",", &cp), "c", 28);
627 check(strtok_r((char *)NULL, ",", &cp) == NULL, 29);
628 equal(one+6, "gh", 30); /* Stomped past end? */
629 equal(one, "a", 31); /* Stomped old tokens? */
630 equal(one+2, "b", 32);
631 equal(one+4, "c", 33);
634 void
635 test_strsep (void)
637 it = "strsep";
638 cp = strcpy(one, "first, second, third");
639 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
640 equal(one, "first", 2);
641 equal(strsep(&cp, ", "), "", 3);
642 equal(strsep(&cp, ", "), "second", 4);
643 equal(strsep(&cp, ", "), "", 5);
644 equal(strsep(&cp, ", "), "third", 6);
645 check(strsep(&cp, ", ") == NULL, 7);
646 cp = strcpy(one, ", first, ");
647 equal(strsep(&cp, ", "), "", 8);
648 equal(strsep(&cp, ", "), "", 9);
649 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
650 equal(strsep(&cp, ", "), "", 11);
651 check(strsep(&cp, ", ") == NULL, 12);
652 cp = strcpy(one, "1a, 1b; 2a, 2b");
653 equal(strsep(&cp, ", "), "1a", 13); /* Changing delim lists. */
654 equal(strsep(&cp, ", "), "", 14);
655 equal(strsep(&cp, "; "), "1b", 15);
656 equal(strsep(&cp, ", "), "", 16);
657 equal(strsep(&cp, ", "), "2a", 17);
658 cp = strcpy(two, "x-y");
659 equal(strsep(&cp, "-"), "x", 18); /* New string before done. */
660 equal(strsep(&cp, "-"), "y", 19);
661 check(strsep(&cp, "-") == NULL, 20);
662 cp = strcpy(one, "a,b, c,, ,d");
663 equal(strsep(&cp, ", "), "a", 21); /* Different separators. */
664 equal(strsep(&cp, ", "), "b", 22);
665 equal(strsep(&cp, " ,"), "", 23);
666 equal(strsep(&cp, " ,"), "c", 24); /* Permute list too. */
667 equal(strsep(&cp, " ,"), "", 25);
668 equal(strsep(&cp, " ,"), "", 26);
669 equal(strsep(&cp, " ,"), "", 27);
670 equal(strsep(&cp, " ,"), "d", 28);
671 check(strsep(&cp, ", ") == NULL, 29);
672 check(strsep(&cp, ", ") == NULL, 30); /* Persistence. */
673 cp = strcpy(one, ", ");
674 equal(strsep(&cp, ", "), "", 31);
675 equal(strsep(&cp, ", "), "", 32);
676 check(strsep(&cp, ", ") == NULL, 33); /* No tokens. */
677 cp = strcpy(one, "");
678 check(strsep(&cp, ", ") == NULL, 34); /* Empty string. */
679 cp = strcpy(one, "abc");
680 equal(strsep(&cp, ", "), "abc", 35); /* No delimiters. */
681 check(strsep(&cp, ", ") == NULL, 36);
682 cp = strcpy(one, "abc");
683 equal(strsep(&cp, ""), "abc", 37); /* Empty delimiter list. */
684 check(strsep(&cp, "") == NULL, 38);
685 (void) strcpy(one, "abcdefgh");
686 cp = strcpy(one, "a,b,c");
687 equal(strsep(&cp, ","), "a", 39); /* Basics again... */
688 equal(strsep(&cp, ","), "b", 40);
689 equal(strsep(&cp, ","), "c", 41);
690 check(strsep(&cp, ",") == NULL, 42);
691 equal(one+6, "gh", 43); /* Stomped past end? */
692 equal(one, "a", 44); /* Stomped old tokens? */
693 equal(one+2, "b", 45);
694 equal(one+4, "c", 46);
697 char text[] = "This,is,a,test";
698 char *list = strdupa (text);
699 equal (strsep (&list, ","), "This", 47);
700 equal (strsep (&list, ","), "is", 48);
701 equal (strsep (&list, ","), "a", 49);
702 equal (strsep (&list, ","), "test", 50);
703 check (strsep (&list, ",") == NULL, 51);
707 void
708 test_memcmp (void)
710 it = "memcmp";
711 check(memcmp("a", "a", 1) == 0, 1); /* Identity. */
712 check(memcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
713 check(memcmp("abcd", "abce", 4) < 0, 3); /* Honestly unequal. */
714 check(memcmp("abce", "abcd", 4) > 0, 4);
715 check(memcmp("alph", "beta", 4) < 0, 5);
716 check(memcmp("a\203", "a\003", 2) > 0, 6);
717 check(memcmp("abce", "abcd", 3) == 0, 7); /* Count limited. */
718 check(memcmp("abc", "def", 0) == 0, 8); /* Zero count. */
721 void
722 test_memchr (void)
724 it = "memchr";
725 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
726 (void) strcpy(one, "abcd");
727 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
728 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
729 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
730 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
731 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
732 (void) strcpy(one, "ababa");
733 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
734 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
735 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
736 (void) strcpy(one, "a\203b");
737 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
739 /* now test all possible alignment and length combinations to catch
740 bugs due to unrolled loops (assuming unrolling is limited to no
741 more than 128 byte chunks: */
743 char buf[128 + sizeof(long)];
744 long align, len, i, pos;
746 for (align = 0; align < (long) sizeof(long); ++align) {
747 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
748 for (i = 0; i < len; ++i) {
749 buf[align + i] = 'x'; /* don't depend on memset... */
751 for (pos = 0; pos < len; ++pos) {
752 #if 0
753 printf("align %d, len %d, pos %d\n", align, len, pos);
754 #endif
755 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
756 check(memchr(buf + align, 'x', pos) == NULL, 11);
757 buf[align + pos] = '-';
764 void
765 test_memcpy (void)
767 it = "memcpy";
768 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
769 equal(one, "abc", 2); /* Did the copy go right? */
771 (void) strcpy(one, "abcdefgh");
772 (void) memcpy(one+1, "xyz", 2);
773 equal(one, "axydefgh", 3); /* Basic test. */
775 (void) strcpy(one, "abc");
776 (void) memcpy(one, "xyz", 0);
777 equal(one, "abc", 4); /* Zero-length copy. */
779 (void) strcpy(one, "hi there");
780 (void) strcpy(two, "foo");
781 (void) memcpy(two, one, 9);
782 equal(two, "hi there", 5); /* Just paranoia. */
783 equal(one, "hi there", 6); /* Stomped on source? */
786 void
787 test_memmove (void)
789 it = "memmove";
790 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
791 equal(one, "abc", 2); /* Did the copy go right? */
793 (void) strcpy(one, "abcdefgh");
794 (void) memmove(one+1, "xyz", 2);
795 equal(one, "axydefgh", 3); /* Basic test. */
797 (void) strcpy(one, "abc");
798 (void) memmove(one, "xyz", 0);
799 equal(one, "abc", 4); /* Zero-length copy. */
801 (void) strcpy(one, "hi there");
802 (void) strcpy(two, "foo");
803 (void) memmove(two, one, 9);
804 equal(two, "hi there", 5); /* Just paranoia. */
805 equal(one, "hi there", 6); /* Stomped on source? */
807 (void) strcpy(one, "abcdefgh");
808 (void) memmove(one+1, one, 9);
809 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
811 (void) strcpy(one, "abcdefgh");
812 (void) memmove(one+1, one+2, 7);
813 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
815 (void) strcpy(one, "abcdefgh");
816 (void) memmove(one, one, 9);
817 equal(one, "abcdefgh", 9); /* 100% overlap. */
820 void
821 test_memccpy (void)
823 /* First test like memcpy, then the search part The SVID, the only
824 place where memccpy is mentioned, says overlap might fail, so we
825 don't try it. Besides, it's hard to see the rationale for a
826 non-left-to-right memccpy. */
827 it = "memccpy";
828 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
829 equal(one, "abc", 2); /* Did the copy go right? */
831 (void) strcpy(one, "abcdefgh");
832 (void) memccpy(one+1, "xyz", 'q', 2);
833 equal(one, "axydefgh", 3); /* Basic test. */
835 (void) strcpy(one, "abc");
836 (void) memccpy(one, "xyz", 'q', 0);
837 equal(one, "abc", 4); /* Zero-length copy. */
839 (void) strcpy(one, "hi there");
840 (void) strcpy(two, "foo");
841 (void) memccpy(two, one, 'q', 9);
842 equal(two, "hi there", 5); /* Just paranoia. */
843 equal(one, "hi there", 6); /* Stomped on source? */
845 (void) strcpy(one, "abcdefgh");
846 (void) strcpy(two, "horsefeathers");
847 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
848 equal(one, "abcdefgh", 8); /* Source intact? */
849 equal(two, "abcdefeathers", 9); /* Copy correct? */
851 (void) strcpy(one, "abcd");
852 (void) strcpy(two, "bumblebee");
853 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
854 equal(two, "aumblebee", 11);
855 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
856 equal(two, "abcdlebee", 13);
857 (void) strcpy(one, "xyz");
858 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
859 equal(two, "xbcdlebee", 15);
862 void
863 test_memset (void)
865 it = "memset";
866 (void) strcpy(one, "abcdefgh");
867 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
868 equal(one, "axxxefgh", 2); /* Basic test. */
870 (void) memset(one+2, 'y', 0);
871 equal(one, "axxxefgh", 3); /* Zero-length set. */
873 (void) memset(one+5, 0, 1);
874 equal(one, "axxxe", 4); /* Zero fill. */
875 equal(one+6, "gh", 5); /* And the leftover. */
877 (void) memset(one+2, 010045, 1);
878 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
880 /* Test for more complex versions of memset, for all alignments and
881 lengths up to 256. This test takes a little while, perhaps it should
882 be made weaker? */
884 char data[512];
885 int i;
886 int j;
887 int k;
888 int c;
890 for (i = 0; i < 512; i++)
891 data[i] = 'x';
892 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
893 memset(,'y',) */
894 for (j = 0; j < 256; j++)
895 for (i = 0; i < 256; i++)
897 memset(data+i,c,j);
898 for (k = 0; k < i; k++)
899 if (data[k] != 'x')
900 goto fail;
901 for (k = i; k < i+j; k++)
903 if (data[k] != c)
904 goto fail;
905 data[k] = 'x';
907 for (k = i+j; k < 512; k++)
908 if (data[k] != 'x')
909 goto fail;
910 continue;
912 fail:
913 check(0,7+i+j*256+(c != 0)*256*256);
918 void
919 test_bcopy (void)
921 /* Much like memcpy. Berklix manual is silent about overlap, so
922 don't test it. */
923 it = "bcopy";
924 (void) bcopy("abc", one, 4);
925 equal(one, "abc", 1); /* Simple copy. */
927 (void) strcpy(one, "abcdefgh");
928 (void) bcopy("xyz", one+1, 2);
929 equal(one, "axydefgh", 2); /* Basic test. */
931 (void) strcpy(one, "abc");
932 (void) bcopy("xyz", one, 0);
933 equal(one, "abc", 3); /* Zero-length copy. */
935 (void) strcpy(one, "hi there");
936 (void) strcpy(two, "foo");
937 (void) bcopy(one, two, 9);
938 equal(two, "hi there", 4); /* Just paranoia. */
939 equal(one, "hi there", 5); /* Stomped on source? */
942 void
943 test_bzero (void)
945 it = "bzero";
946 (void) strcpy(one, "abcdef");
947 bzero(one+2, 2);
948 equal(one, "ab", 1); /* Basic test. */
949 equal(one+3, "", 2);
950 equal(one+4, "ef", 3);
952 (void) strcpy(one, "abcdef");
953 bzero(one+2, 0);
954 equal(one, "abcdef", 4); /* Zero-length copy. */
957 void
958 test_bcmp (void)
960 it = "bcmp";
961 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
962 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
963 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
964 check(bcmp("abce", "abcd", 4) != 0, 4);
965 check(bcmp("alph", "beta", 4) != 0, 5);
966 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
967 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
970 void
971 test_strerror (void)
973 int f;
974 it = "strerror";
975 f = __open("/", O_WRONLY); /* Should always fail. */
976 check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
977 equal(strerror(errno), _sys_errlist[errno], 2);
981 main (void)
983 int status;
985 /* Test strcmp first because we use it to test other things. */
986 test_strcmp ();
988 /* Test strcpy next because we need it to set up other tests. */
989 test_strcpy ();
991 /* A closely related function is stpcpy. */
992 test_stpcpy ();
994 /* stpncpy. */
995 test_stpncpy ();
997 /* strcat. */
998 test_strcat ();
1000 /* strncat. */
1001 test_strncat ();
1003 /* strncmp. */
1004 test_strncmp ();
1006 /* strncpy. */
1007 test_strncpy ();
1009 /* strlen. */
1010 test_strlen ();
1012 /* strchr. */
1013 test_strchr ();
1015 /* index - just like strchr. */
1016 test_index ();
1018 /* strrchr. */
1019 test_strrchr ();
1021 /* rindex - just like strrchr. */
1022 test_rindex ();
1024 /* strpbrk - somewhat like strchr. */
1025 test_strpbrk ();
1027 /* strstr - somewhat like strchr. */
1028 test_strstr ();
1030 /* strspn. */
1031 test_strspn ();
1033 /* strcspn. */
1034 test_strcspn ();
1036 /* strtok - the hard one. */
1037 test_strtok ();
1039 /* strtok_r. */
1040 test_strtok_r ();
1042 /* strsep. */
1043 test_strsep ();
1045 /* memcmp. */
1046 test_memcmp ();
1048 /* memchr. */
1049 test_memchr ();
1051 /* memcpy - need not work for overlap. */
1052 test_memcpy ();
1054 /* memmove - must work on overlap. */
1055 test_memmove ();
1057 /* memccpy. */
1058 test_memccpy ();
1060 /* memset. */
1061 test_memset ();
1063 /* bcopy. */
1064 test_bcopy ();
1066 /* bzero. */
1067 test_bzero ();
1069 /* bcmp - somewhat like memcmp. */
1070 test_bcmp ();
1072 /* strerror - VERY system-dependent. */
1073 test_strerror ();
1076 if (errors == 0)
1078 status = EXIT_SUCCESS;
1079 puts("No errors.");
1081 else
1083 status = EXIT_FAILURE;
1084 printf("%Zd errors.\n", errors);
1086 exit(status);