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