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