Update.
[glibc.git] / string / tester.c
blob9545c28080f23afe8c30f8e99c40e30213d6dda6
1 /* Tester for string functions.
2 Copyright (C) 1995, 1996, 1997, 1998 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 (void) strcpy(one, "");
483 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
484 (void) strcpy(one, "");
485 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
486 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
487 (void) strcpy(one, "abcabdea");
488 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
489 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
490 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
491 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
494 void
495 test_strstr (void)
497 it = "strstr";
498 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
499 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
500 (void) strcpy(one, "abcd");
501 check(strstr(one, "c") == one+2, 3); /* Basic test. */
502 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
503 check(strstr(one, "d") == one+3, 5); /* End of string. */
504 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
505 check(strstr(one, "abc") == one, 7); /* Beginning. */
506 check(strstr(one, "abcd") == one, 8); /* Exact match. */
507 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
508 check(strstr(one, "de") == NULL, 10); /* Past end. */
509 check(strstr(one, "") == one, 11); /* Finding empty. */
510 (void) strcpy(one, "ababa");
511 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
512 (void) strcpy(one, "");
513 check(strstr(one, "b") == NULL, 13); /* Empty string. */
514 check(strstr(one, "") == one, 14); /* Empty in empty string. */
515 (void) strcpy(one, "bcbca");
516 check(strstr(one, "bca") == one+2, 15); /* False start. */
517 (void) strcpy(one, "bbbcabbca");
518 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
521 void
522 test_strspn (void)
524 it = "strspn";
525 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
526 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
527 check(strspn("abc", "qx") == 0, 3); /* None. */
528 check(strspn("", "ab") == 0, 4); /* Null string. */
529 check(strspn("abc", "") == 0, 5); /* Null search list. */
532 void
533 test_strcspn (void)
535 it = "strcspn";
536 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
537 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
538 check(strcspn("abc", "abc") == 0, 3); /* None. */
539 check(strcspn("", "ab") == 0, 4); /* Null string. */
540 check(strcspn("abc", "") == 3, 5); /* Null search list. */
543 void
544 test_strtok (void)
546 it = "strtok";
547 (void) strcpy(one, "first, second, third");
548 equal(strtok(one, ", "), "first", 1); /* Basic test. */
549 equal(one, "first", 2);
550 equal(strtok((char *)NULL, ", "), "second", 3);
551 equal(strtok((char *)NULL, ", "), "third", 4);
552 check(strtok((char *)NULL, ", ") == NULL, 5);
553 (void) strcpy(one, ", first, ");
554 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
555 check(strtok((char *)NULL, ", ") == NULL, 7);
556 (void) strcpy(one, "1a, 1b; 2a, 2b");
557 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
558 equal(strtok((char *)NULL, "; "), "1b", 9);
559 equal(strtok((char *)NULL, ", "), "2a", 10);
560 (void) strcpy(two, "x-y");
561 equal(strtok(two, "-"), "x", 11); /* New string before done. */
562 equal(strtok((char *)NULL, "-"), "y", 12);
563 check(strtok((char *)NULL, "-") == NULL, 13);
564 (void) strcpy(one, "a,b, c,, ,d");
565 equal(strtok(one, ", "), "a", 14); /* Different separators. */
566 equal(strtok((char *)NULL, ", "), "b", 15);
567 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
568 equal(strtok((char *)NULL, " ,"), "d", 17);
569 check(strtok((char *)NULL, ", ") == NULL, 18);
570 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
571 (void) strcpy(one, ", ");
572 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
573 (void) strcpy(one, "");
574 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
575 (void) strcpy(one, "abc");
576 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
577 check(strtok((char *)NULL, ", ") == NULL, 23);
578 (void) strcpy(one, "abc");
579 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
580 check(strtok((char *)NULL, "") == NULL, 25);
581 (void) strcpy(one, "abcdefgh");
582 (void) strcpy(one, "a,b,c");
583 equal(strtok(one, ","), "a", 26); /* Basics again... */
584 equal(strtok((char *)NULL, ","), "b", 27);
585 equal(strtok((char *)NULL, ","), "c", 28);
586 check(strtok((char *)NULL, ",") == NULL, 29);
587 equal(one+6, "gh", 30); /* Stomped past end? */
588 equal(one, "a", 31); /* Stomped old tokens? */
589 equal(one+2, "b", 32);
590 equal(one+4, "c", 33);
593 void
594 test_strtok_r (void)
596 it = "strtok_r";
597 (void) strcpy(one, "first, second, third");
598 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
599 equal(one, "first", 2);
600 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
601 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
602 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
603 (void) strcpy(one, ", first, ");
604 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
605 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
606 (void) strcpy(one, "1a, 1b; 2a, 2b");
607 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
608 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
609 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
610 (void) strcpy(two, "x-y");
611 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
612 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
613 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
614 (void) strcpy(one, "a,b, c,, ,d");
615 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
616 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
617 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
618 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
619 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
620 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
621 (void) strcpy(one, ", ");
622 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
623 (void) strcpy(one, "");
624 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
625 (void) strcpy(one, "abc");
626 equal(strtok_r(one, ", ", &cp), "abc", 22); /* No delimiters. */
627 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23);
628 (void) strcpy(one, "abc");
629 equal(strtok_r(one, "", &cp), "abc", 24); /* Empty delimiter list. */
630 check(strtok_r((char *)NULL, "", &cp) == NULL, 25);
631 (void) strcpy(one, "abcdefgh");
632 (void) strcpy(one, "a,b,c");
633 equal(strtok_r(one, ",", &cp), "a", 26); /* Basics again... */
634 equal(strtok_r((char *)NULL, ",", &cp), "b", 27);
635 equal(strtok_r((char *)NULL, ",", &cp), "c", 28);
636 check(strtok_r((char *)NULL, ",", &cp) == NULL, 29);
637 equal(one+6, "gh", 30); /* Stomped past end? */
638 equal(one, "a", 31); /* Stomped old tokens? */
639 equal(one+2, "b", 32);
640 equal(one+4, "c", 33);
643 void
644 test_strsep (void)
646 it = "strsep";
647 cp = strcpy(one, "first, second, third");
648 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
649 equal(one, "first", 2);
650 equal(strsep(&cp, ", "), "", 3);
651 equal(strsep(&cp, ", "), "second", 4);
652 equal(strsep(&cp, ", "), "", 5);
653 equal(strsep(&cp, ", "), "third", 6);
654 check(strsep(&cp, ", ") == NULL, 7);
655 cp = strcpy(one, ", first, ");
656 equal(strsep(&cp, ", "), "", 8);
657 equal(strsep(&cp, ", "), "", 9);
658 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
659 equal(strsep(&cp, ", "), "", 11);
660 equal(strsep(&cp, ", "), "", 12);
661 check(strsep(&cp, ", ") == NULL, 13);
662 cp = strcpy(one, "1a, 1b; 2a, 2b");
663 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
664 equal(strsep(&cp, ", "), "", 15);
665 equal(strsep(&cp, "; "), "1b", 16);
666 equal(strsep(&cp, ", "), "", 17);
667 equal(strsep(&cp, ", "), "2a", 18);
668 cp = strcpy(two, "x-y");
669 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
670 equal(strsep(&cp, "-"), "y", 20);
671 check(strsep(&cp, "-") == NULL, 21);
672 cp = strcpy(one, "a,b, c,, ,d ");
673 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
674 equal(strsep(&cp, ", "), "b", 23);
675 equal(strsep(&cp, " ,"), "", 24);
676 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
677 equal(strsep(&cp, " ,"), "", 26);
678 equal(strsep(&cp, " ,"), "", 27);
679 equal(strsep(&cp, " ,"), "", 28);
680 equal(strsep(&cp, " ,"), "d", 29);
681 equal(strsep(&cp, " ,"), "", 30);
682 check(strsep(&cp, ", ") == NULL, 31);
683 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
684 cp = strcpy(one, ", ");
685 equal(strsep(&cp, ", "), "", 33);
686 equal(strsep(&cp, ", "), "", 34);
687 equal(strsep(&cp, ", "), "", 35);
688 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
689 cp = strcpy(one, "");
690 equal(strsep(&cp, ", "), "", 37);
691 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
692 cp = strcpy(one, "abc");
693 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
694 check(strsep(&cp, ", ") == NULL, 40);
695 cp = strcpy(one, "abc");
696 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
697 check(strsep(&cp, "") == NULL, 42);
698 (void) strcpy(one, "abcdefgh");
699 cp = strcpy(one, "a,b,c");
700 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
701 equal(strsep(&cp, ","), "b", 44);
702 equal(strsep(&cp, ","), "c", 45);
703 check(strsep(&cp, ",") == NULL, 46);
704 equal(one+6, "gh", 47); /* Stomped past end? */
705 equal(one, "a", 48); /* Stomped old tokens? */
706 equal(one+2, "b", 49);
707 equal(one+4, "c", 50);
710 char text[] = "This,is,a,test";
711 char *list = strdupa (text);
712 equal (strsep (&list, ","), "This", 51);
713 equal (strsep (&list, ","), "is", 52);
714 equal (strsep (&list, ","), "a", 53);
715 equal (strsep (&list, ","), "test", 54);
716 check (strsep (&list, ",") == NULL, 55);
719 cp = strcpy(one, "a,b, c,, ,d,");
720 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
721 equal(strsep(&cp, ","), "b", 57);
722 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
723 equal(strsep(&cp, ","), "", 59);
724 equal(strsep(&cp, ","), " ", 60);
725 equal(strsep(&cp, ","), "d", 61);
726 equal(strsep(&cp, ","), "", 62);
727 check(strsep(&cp, ",") == NULL, 63);
728 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
730 cp = strcpy(one, "a,b, c,, ,d,");
731 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
732 equal(strsep(&cp, "x,y"), "b", 66);
733 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
734 equal(strsep(&cp, "xy,"), "", 68);
735 equal(strsep(&cp, "x,y"), " ", 69);
736 equal(strsep(&cp, ",xy"), "d", 70);
737 equal(strsep(&cp, "xy,"), "", 71);
738 check(strsep(&cp, "x,y") == NULL, 72);
739 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
742 void
743 test_memcmp (void)
745 it = "memcmp";
746 check(memcmp("a", "a", 1) == 0, 1); /* Identity. */
747 check(memcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
748 check(memcmp("abcd", "abce", 4) < 0, 3); /* Honestly unequal. */
749 check(memcmp("abce", "abcd", 4) > 0, 4);
750 check(memcmp("alph", "beta", 4) < 0, 5);
751 check(memcmp("a\203", "a\003", 2) > 0, 6);
752 check(memcmp("abce", "abcd", 3) == 0, 7); /* Count limited. */
753 check(memcmp("abc", "def", 0) == 0, 8); /* Zero count. */
756 void
757 test_memchr (void)
759 it = "memchr";
760 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
761 (void) strcpy(one, "abcd");
762 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
763 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
764 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
765 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
766 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
767 (void) strcpy(one, "ababa");
768 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
769 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
770 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
771 (void) strcpy(one, "a\203b");
772 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
774 /* now test all possible alignment and length combinations to catch
775 bugs due to unrolled loops (assuming unrolling is limited to no
776 more than 128 byte chunks: */
778 char buf[128 + sizeof(long)];
779 long align, len, i, pos;
781 for (align = 0; align < (long) sizeof(long); ++align) {
782 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
783 for (i = 0; i < len; ++i) {
784 buf[align + i] = 'x'; /* don't depend on memset... */
786 for (pos = 0; pos < len; ++pos) {
787 #if 0
788 printf("align %d, len %d, pos %d\n", align, len, pos);
789 #endif
790 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
791 check(memchr(buf + align, 'x', pos) == NULL, 11);
792 buf[align + pos] = '-';
799 void
800 test_memcpy (void)
802 it = "memcpy";
803 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
804 equal(one, "abc", 2); /* Did the copy go right? */
806 (void) strcpy(one, "abcdefgh");
807 (void) memcpy(one+1, "xyz", 2);
808 equal(one, "axydefgh", 3); /* Basic test. */
810 (void) strcpy(one, "abc");
811 (void) memcpy(one, "xyz", 0);
812 equal(one, "abc", 4); /* Zero-length copy. */
814 (void) strcpy(one, "hi there");
815 (void) strcpy(two, "foo");
816 (void) memcpy(two, one, 9);
817 equal(two, "hi there", 5); /* Just paranoia. */
818 equal(one, "hi there", 6); /* Stomped on source? */
821 void
822 test_memmove (void)
824 it = "memmove";
825 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
826 equal(one, "abc", 2); /* Did the copy go right? */
828 (void) strcpy(one, "abcdefgh");
829 (void) memmove(one+1, "xyz", 2);
830 equal(one, "axydefgh", 3); /* Basic test. */
832 (void) strcpy(one, "abc");
833 (void) memmove(one, "xyz", 0);
834 equal(one, "abc", 4); /* Zero-length copy. */
836 (void) strcpy(one, "hi there");
837 (void) strcpy(two, "foo");
838 (void) memmove(two, one, 9);
839 equal(two, "hi there", 5); /* Just paranoia. */
840 equal(one, "hi there", 6); /* Stomped on source? */
842 (void) strcpy(one, "abcdefgh");
843 (void) memmove(one+1, one, 9);
844 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
846 (void) strcpy(one, "abcdefgh");
847 (void) memmove(one+1, one+2, 7);
848 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
850 (void) strcpy(one, "abcdefgh");
851 (void) memmove(one, one, 9);
852 equal(one, "abcdefgh", 9); /* 100% overlap. */
855 void
856 test_memccpy (void)
858 /* First test like memcpy, then the search part The SVID, the only
859 place where memccpy is mentioned, says overlap might fail, so we
860 don't try it. Besides, it's hard to see the rationale for a
861 non-left-to-right memccpy. */
862 it = "memccpy";
863 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
864 equal(one, "abc", 2); /* Did the copy go right? */
866 (void) strcpy(one, "abcdefgh");
867 (void) memccpy(one+1, "xyz", 'q', 2);
868 equal(one, "axydefgh", 3); /* Basic test. */
870 (void) strcpy(one, "abc");
871 (void) memccpy(one, "xyz", 'q', 0);
872 equal(one, "abc", 4); /* Zero-length copy. */
874 (void) strcpy(one, "hi there");
875 (void) strcpy(two, "foo");
876 (void) memccpy(two, one, 'q', 9);
877 equal(two, "hi there", 5); /* Just paranoia. */
878 equal(one, "hi there", 6); /* Stomped on source? */
880 (void) strcpy(one, "abcdefgh");
881 (void) strcpy(two, "horsefeathers");
882 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
883 equal(one, "abcdefgh", 8); /* Source intact? */
884 equal(two, "abcdefeathers", 9); /* Copy correct? */
886 (void) strcpy(one, "abcd");
887 (void) strcpy(two, "bumblebee");
888 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
889 equal(two, "aumblebee", 11);
890 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
891 equal(two, "abcdlebee", 13);
892 (void) strcpy(one, "xyz");
893 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
894 equal(two, "xbcdlebee", 15);
897 void
898 test_memset (void)
900 it = "memset";
901 (void) strcpy(one, "abcdefgh");
902 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
903 equal(one, "axxxefgh", 2); /* Basic test. */
905 (void) memset(one+2, 'y', 0);
906 equal(one, "axxxefgh", 3); /* Zero-length set. */
908 (void) memset(one+5, 0, 1);
909 equal(one, "axxxe", 4); /* Zero fill. */
910 equal(one+6, "gh", 5); /* And the leftover. */
912 (void) memset(one+2, 010045, 1);
913 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
915 /* Test for more complex versions of memset, for all alignments and
916 lengths up to 256. This test takes a little while, perhaps it should
917 be made weaker? */
919 char data[512];
920 int i;
921 int j;
922 int k;
923 int c;
925 for (i = 0; i < 512; i++)
926 data[i] = 'x';
927 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
928 memset(,'y',) */
929 for (j = 0; j < 256; j++)
930 for (i = 0; i < 256; i++)
932 memset(data+i,c,j);
933 for (k = 0; k < i; k++)
934 if (data[k] != 'x')
935 goto fail;
936 for (k = i; k < i+j; k++)
938 if (data[k] != c)
939 goto fail;
940 data[k] = 'x';
942 for (k = i+j; k < 512; k++)
943 if (data[k] != 'x')
944 goto fail;
945 continue;
947 fail:
948 check(0,7+i+j*256+(c != 0)*256*256);
953 void
954 test_bcopy (void)
956 /* Much like memcpy. Berklix manual is silent about overlap, so
957 don't test it. */
958 it = "bcopy";
959 (void) bcopy("abc", one, 4);
960 equal(one, "abc", 1); /* Simple copy. */
962 (void) strcpy(one, "abcdefgh");
963 (void) bcopy("xyz", one+1, 2);
964 equal(one, "axydefgh", 2); /* Basic test. */
966 (void) strcpy(one, "abc");
967 (void) bcopy("xyz", one, 0);
968 equal(one, "abc", 3); /* Zero-length copy. */
970 (void) strcpy(one, "hi there");
971 (void) strcpy(two, "foo");
972 (void) bcopy(one, two, 9);
973 equal(two, "hi there", 4); /* Just paranoia. */
974 equal(one, "hi there", 5); /* Stomped on source? */
977 void
978 test_bzero (void)
980 it = "bzero";
981 (void) strcpy(one, "abcdef");
982 bzero(one+2, 2);
983 equal(one, "ab", 1); /* Basic test. */
984 equal(one+3, "", 2);
985 equal(one+4, "ef", 3);
987 (void) strcpy(one, "abcdef");
988 bzero(one+2, 0);
989 equal(one, "abcdef", 4); /* Zero-length copy. */
992 void
993 test_bcmp (void)
995 it = "bcmp";
996 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
997 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
998 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
999 check(bcmp("abce", "abcd", 4) != 0, 4);
1000 check(bcmp("alph", "beta", 4) != 0, 5);
1001 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1002 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1005 void
1006 test_strerror (void)
1008 int f;
1009 it = "strerror";
1010 f = __open("/", O_WRONLY); /* Should always fail. */
1011 check(f < 0 && errno > 0 && errno < _sys_nerr, 1);
1012 equal(strerror(errno), _sys_errlist[errno], 2);
1016 main (void)
1018 int status;
1020 /* Test strcmp first because we use it to test other things. */
1021 test_strcmp ();
1023 /* Test strcpy next because we need it to set up other tests. */
1024 test_strcpy ();
1026 /* A closely related function is stpcpy. */
1027 test_stpcpy ();
1029 /* stpncpy. */
1030 test_stpncpy ();
1032 /* strcat. */
1033 test_strcat ();
1035 /* strncat. */
1036 test_strncat ();
1038 /* strncmp. */
1039 test_strncmp ();
1041 /* strncpy. */
1042 test_strncpy ();
1044 /* strlen. */
1045 test_strlen ();
1047 /* strchr. */
1048 test_strchr ();
1050 /* index - just like strchr. */
1051 test_index ();
1053 /* strrchr. */
1054 test_strrchr ();
1056 /* rindex - just like strrchr. */
1057 test_rindex ();
1059 /* strpbrk - somewhat like strchr. */
1060 test_strpbrk ();
1062 /* strstr - somewhat like strchr. */
1063 test_strstr ();
1065 /* strspn. */
1066 test_strspn ();
1068 /* strcspn. */
1069 test_strcspn ();
1071 /* strtok - the hard one. */
1072 test_strtok ();
1074 /* strtok_r. */
1075 test_strtok_r ();
1077 /* strsep. */
1078 test_strsep ();
1080 /* memcmp. */
1081 test_memcmp ();
1083 /* memchr. */
1084 test_memchr ();
1086 /* memcpy - need not work for overlap. */
1087 test_memcpy ();
1089 /* memmove - must work on overlap. */
1090 test_memmove ();
1092 /* memccpy. */
1093 test_memccpy ();
1095 /* memset. */
1096 test_memset ();
1098 /* bcopy. */
1099 test_bcopy ();
1101 /* bzero. */
1102 test_bzero ();
1104 /* bcmp - somewhat like memcmp. */
1105 test_bcmp ();
1107 /* strerror - VERY system-dependent. */
1108 test_strerror ();
1111 if (errors == 0)
1113 status = EXIT_SUCCESS;
1114 puts("No errors.");
1116 else
1118 status = EXIT_FAILURE;
1119 printf("%Zd errors.\n", errors);
1121 exit(status);