Update IA64 libm-test-ulps
[glibc.git] / string / tester.c
blob66b11515b05d99278a95b3bfaf0c7b740d5b53f4
1 /* Tester for string functions.
2 Copyright (C) 1995-2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU 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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
23 /* Make sure we don't test the optimized inline functions if we want to
24 test the real implementation. */
25 #if !defined DO_STRING_INLINES
26 #undef __USE_STRING_INLINES
27 #endif
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <fcntl.h>
35 #include <libc-diag.h>
38 #define STREQ(a, b) (strcmp((a), (b)) == 0)
40 const char *it = "<UNSET>"; /* Routine name for message routines. */
41 size_t errors = 0;
43 /* Complain if condition is not true. */
44 static void
45 check (int thing, int number)
47 if (!thing)
49 printf ("%s flunked test %d\n", it, number);
50 ++errors;
54 /* Complain if first two args don't strcmp as equal. */
55 static void
56 equal (const char *a, const char *b, int number)
58 check (a != NULL && b != NULL && STREQ (a, b), number);
61 char one[50];
62 char two[50];
63 char *cp;
65 static void
66 test_strcmp (void)
68 it = "strcmp";
69 check (strcmp ("", "") == 0, 1); /* Trivial case. */
70 check (strcmp ("a", "a") == 0, 2); /* Identity. */
71 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
72 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
73 check (strcmp ("abcd", "abc") > 0, 5);
74 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
75 check (strcmp ("abce", "abcd") > 0, 7);
76 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
77 check (strcmp ("a\203", "a\003") > 0, 9);
80 char buf1[0x40], buf2[0x40];
81 int i, j;
82 for (i=0; i < 0x10; i++)
83 for (j = 0; j < 0x10; j++)
85 int k;
86 for (k = 0; k < 0x3f; k++)
88 buf1[k] = '0' ^ (k & 4);
89 buf2[k] = '4' ^ (k & 4);
91 buf1[i] = buf1[0x3f] = 0;
92 buf2[j] = buf2[0x3f] = 0;
93 for (k = 0; k < 0xf; k++)
95 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
96 check (strcmp (buf1+i,buf2+j) == 0, cnum);
97 buf1[i+k] = 'A' + i + k;
98 buf1[i+k+1] = 0;
99 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
100 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
101 buf2[j+k] = 'B' + i + k;
102 buf2[j+k+1] = 0;
103 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
104 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
105 buf2[j+k] = 'A' + i + k;
106 buf1[i] = 'A' + i + 0x80;
107 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
108 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
109 buf1[i] = 'A' + i;
115 #define SIMPLE_COPY(fn, n, str, ntest) \
116 do { \
117 int __n; \
118 char *cp; \
119 for (__n = 0; __n < (int) sizeof (one); ++__n) \
120 one[__n] = 'Z'; \
121 fn (one, str); \
122 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
123 check (*cp == '0' + (n % 10), ntest); \
124 check (*cp == '\0', ntest); \
125 } while (0)
127 static void
128 test_strcpy (void)
130 int i;
131 it = "strcpy";
132 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
133 equal (one, "abcd", 2); /* Basic test. */
135 (void) strcpy (one, "x");
136 equal (one, "x", 3); /* Writeover. */
137 equal (one+2, "cd", 4); /* Wrote too much? */
139 (void) strcpy (two, "hi there");
140 (void) strcpy (one, two);
141 equal (one, "hi there", 5); /* Basic test encore. */
142 equal (two, "hi there", 6); /* Stomped on source? */
144 (void) strcpy (one, "");
145 equal (one, "", 7); /* Boundary condition. */
147 for (i = 0; i < 16; i++)
149 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
150 equal (one + i, "hi there", 8 + (i * 2));
151 (void) strcpy (two, one + i); /* Unaligned source. */
152 equal (two, "hi there", 9 + (i * 2));
155 SIMPLE_COPY(strcpy, 0, "", 41);
156 SIMPLE_COPY(strcpy, 1, "1", 42);
157 SIMPLE_COPY(strcpy, 2, "22", 43);
158 SIMPLE_COPY(strcpy, 3, "333", 44);
159 SIMPLE_COPY(strcpy, 4, "4444", 45);
160 SIMPLE_COPY(strcpy, 5, "55555", 46);
161 SIMPLE_COPY(strcpy, 6, "666666", 47);
162 SIMPLE_COPY(strcpy, 7, "7777777", 48);
163 SIMPLE_COPY(strcpy, 8, "88888888", 49);
164 SIMPLE_COPY(strcpy, 9, "999999999", 50);
165 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
166 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
167 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
168 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
169 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
170 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
171 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
173 /* Simple test using implicitly coerced `void *' arguments. */
174 const void *src = "frobozz";
175 void *dst = one;
176 check (strcpy (dst, src) == dst, 1);
177 equal (dst, "frobozz", 2);
180 static void
181 test_stpcpy (void)
183 it = "stpcpy";
184 check ((stpcpy (one, "a") - one) == 1, 1);
185 equal (one, "a", 2);
187 check ((stpcpy (one, "ab") - one) == 2, 3);
188 equal (one, "ab", 4);
190 check ((stpcpy (one, "abc") - one) == 3, 5);
191 equal (one, "abc", 6);
193 check ((stpcpy (one, "abcd") - one) == 4, 7);
194 equal (one, "abcd", 8);
196 check ((stpcpy (one, "abcde") - one) == 5, 9);
197 equal (one, "abcde", 10);
199 check ((stpcpy (one, "abcdef") - one) == 6, 11);
200 equal (one, "abcdef", 12);
202 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
203 equal (one, "abcdefg", 14);
205 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
206 equal (one, "abcdefgh", 16);
208 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
209 equal (one, "abcdefghi", 18);
211 check ((stpcpy (one, "x") - one) == 1, 19);
212 equal (one, "x", 20); /* Writeover. */
213 equal (one+2, "cdefghi", 21); /* Wrote too much? */
215 check ((stpcpy (one, "xx") - one) == 2, 22);
216 equal (one, "xx", 23); /* Writeover. */
217 equal (one+3, "defghi", 24); /* Wrote too much? */
219 check ((stpcpy (one, "xxx") - one) == 3, 25);
220 equal (one, "xxx", 26); /* Writeover. */
221 equal (one+4, "efghi", 27); /* Wrote too much? */
223 check ((stpcpy (one, "xxxx") - one) == 4, 28);
224 equal (one, "xxxx", 29); /* Writeover. */
225 equal (one+5, "fghi", 30); /* Wrote too much? */
227 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
228 equal (one, "xxxxx", 32); /* Writeover. */
229 equal (one+6, "ghi", 33); /* Wrote too much? */
231 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
232 equal (one, "xxxxxx", 35); /* Writeover. */
233 equal (one+7, "hi", 36); /* Wrote too much? */
235 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
236 equal (one, "xxxxxxx", 38); /* Writeover. */
237 equal (one+8, "i", 39); /* Wrote too much? */
239 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
240 equal (one, "abc", 41);
241 equal (one + 4, "xxx", 42);
243 SIMPLE_COPY(stpcpy, 0, "", 43);
244 SIMPLE_COPY(stpcpy, 1, "1", 44);
245 SIMPLE_COPY(stpcpy, 2, "22", 45);
246 SIMPLE_COPY(stpcpy, 3, "333", 46);
247 SIMPLE_COPY(stpcpy, 4, "4444", 47);
248 SIMPLE_COPY(stpcpy, 5, "55555", 48);
249 SIMPLE_COPY(stpcpy, 6, "666666", 49);
250 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
251 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
252 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
253 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
254 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
255 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
256 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
257 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
258 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
259 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
262 static void
263 test_stpncpy (void)
265 it = "stpncpy";
266 memset (one, 'x', sizeof (one));
267 DIAG_PUSH_NEEDS_COMMENT;
268 #if __GNUC_PREREQ (8, 0)
269 /* GCC 8 warns about stpncpy truncating output; this is deliberately
270 tested here. */
271 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
272 #endif
273 check (stpncpy (one, "abc", 2) == one + 2, 1);
274 check (stpncpy (one, "abc", 3) == one + 3, 2);
275 DIAG_POP_NEEDS_COMMENT;
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);
284 static void
285 test_strcat (void)
287 it = "strcat";
288 (void) strcpy (one, "ijk");
289 check (strcat (one, "lmn") == one, 1); /* Returned value. */
290 equal (one, "ijklmn", 2); /* Basic test. */
292 (void) strcpy (one, "x");
293 (void) strcat (one, "yz");
294 equal (one, "xyz", 3); /* Writeover. */
295 equal (one+4, "mn", 4); /* Wrote too much? */
297 (void) strcpy (one, "gh");
298 (void) strcpy (two, "ef");
299 (void) strcat (one, two);
300 equal (one, "ghef", 5); /* Basic test encore. */
301 equal (two, "ef", 6); /* Stomped on source? */
303 (void) strcpy (one, "");
304 (void) strcat (one, "");
305 equal (one, "", 7); /* Boundary conditions. */
306 (void) strcpy (one, "ab");
307 (void) strcat (one, "");
308 equal (one, "ab", 8);
309 (void) strcpy (one, "");
310 (void) strcat (one, "cd");
311 equal (one, "cd", 9);
313 int ntest = 10;
314 char buf1[80] __attribute__ ((aligned (16)));
315 char buf2[32] __attribute__ ((aligned (16)));
316 for (size_t n1 = 0; n1 < 16; ++n1)
317 for (size_t n2 = 0; n2 < 16; ++n2)
318 for (size_t n3 = 0; n3 < 32; ++n3)
320 size_t olderrors = errors;
322 memset (buf1, 'b', sizeof (buf1));
324 memset (buf1 + n2, 'a', n3);
325 buf1[n2 + n3] = '\0';
326 strcpy (buf2 + n1, "123");
328 check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
329 if (errors == olderrors)
330 for (size_t i = 0; i < sizeof (buf1); ++i)
332 if (i < n2)
333 check (buf1[i] == 'b', ntest);
334 else if (i < n2 + n3)
335 check (buf1[i] == 'a', ntest);
336 else if (i < n2 + n3 + 3)
337 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
338 else if (i == n2 + n3 + 3)
339 check (buf1[i] == '\0', ntest);
340 else
341 check (buf1[i] == 'b', ntest);
343 if (errors != olderrors)
345 printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
346 n1, n2, n3, buf1[0]);
347 for (size_t j = 1; j < sizeof (buf1); ++j)
348 printf (",%02hhx", buf1[j]);
349 putchar_unlocked ('\n');
350 break;
356 static void
357 test_strncat (void)
359 /* First test it as strcat, with big counts, then test the count
360 mechanism. */
361 it = "strncat";
362 (void) strcpy (one, "ijk");
363 DIAG_PUSH_NEEDS_COMMENT;
364 #if __GNUC_PREREQ (7, 0)
365 /* GCC 7 warns about the size passed to strncat being larger than
366 the size of the buffer; this is deliberately tested here.. */
367 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
368 #endif
369 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
370 DIAG_POP_NEEDS_COMMENT;
371 equal (one, "ijklmn", 2); /* Basic test. */
373 (void) strcpy (one, "x");
374 DIAG_PUSH_NEEDS_COMMENT;
375 #if __GNUC_PREREQ (7, 0)
376 /* GCC 7 warns about the size passed to strncat being larger than
377 the size of the buffer; this is deliberately tested here.. */
378 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
379 #endif
380 (void) strncat (one, "yz", 99);
381 DIAG_POP_NEEDS_COMMENT;
382 equal (one, "xyz", 3); /* Writeover. */
383 equal (one+4, "mn", 4); /* Wrote too much? */
385 (void) strcpy (one, "gh");
386 (void) strcpy (two, "ef");
387 DIAG_PUSH_NEEDS_COMMENT;
388 #if __GNUC_PREREQ (7, 0)
389 /* GCC 7 warns about the size passed to strncat being larger than
390 the size of the buffer; this is deliberately tested here.. */
391 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
392 #endif
393 (void) strncat (one, two, 99);
394 DIAG_POP_NEEDS_COMMENT;
395 equal (one, "ghef", 5); /* Basic test encore. */
396 equal (two, "ef", 6); /* Stomped on source? */
398 (void) strcpy (one, "");
399 DIAG_PUSH_NEEDS_COMMENT;
400 #if __GNUC_PREREQ (7, 0)
401 /* GCC 7 warns about the size passed to strncat being larger than
402 the size of the buffer; this is deliberately tested here.. */
403 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
404 #endif
405 (void) strncat (one, "", 99);
406 DIAG_POP_NEEDS_COMMENT;
407 equal (one, "", 7); /* Boundary conditions. */
408 (void) strcpy (one, "ab");
409 DIAG_PUSH_NEEDS_COMMENT;
410 #if __GNUC_PREREQ (7, 0)
411 /* GCC 7 warns about the size passed to strncat being larger than
412 the size of the buffer; this is deliberately tested here.. */
413 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
414 #endif
415 (void) strncat (one, "", 99);
416 DIAG_POP_NEEDS_COMMENT;
417 equal (one, "ab", 8);
418 (void) strcpy (one, "");
419 DIAG_PUSH_NEEDS_COMMENT;
420 #if __GNUC_PREREQ (7, 0)
421 /* GCC 7 warns about the size passed to strncat being larger than
422 the size of the buffer; this is deliberately tested here.. */
423 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
424 #endif
425 (void) strncat (one, "cd", 99);
426 DIAG_POP_NEEDS_COMMENT;
427 equal (one, "cd", 9);
429 (void) strcpy (one, "ab");
430 DIAG_PUSH_NEEDS_COMMENT;
431 #if __GNUC_PREREQ (8, 0)
432 /* GCC 8 warns about strncat truncating output; this is deliberately
433 tested here. */
434 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
435 #endif
436 (void) strncat (one, "cdef", 2);
437 DIAG_POP_NEEDS_COMMENT;
438 equal (one, "abcd", 10); /* Count-limited. */
440 (void) strncat (one, "gh", 0);
441 equal (one, "abcd", 11); /* Zero count. */
443 DIAG_PUSH_NEEDS_COMMENT;
444 #if __GNUC_PREREQ (7, 0)
445 /* GCC 8 warns about strncat bound equal to source length; this is
446 deliberately tested here. */
447 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-overflow=");
448 #endif
449 (void) strncat (one, "gh", 2);
450 DIAG_POP_NEEDS_COMMENT;
451 equal (one, "abcdgh", 12); /* Count and length equal. */
453 DIAG_PUSH_NEEDS_COMMENT;
454 #if __GNUC_PREREQ (7, 0)
455 /* GCC 7 warns about the size passed to strncat being larger than
456 the size of the buffer; this is deliberately tested here.. */
457 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
458 #endif
459 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
460 DIAG_POP_NEEDS_COMMENT;
461 equal (one, "abcdghij", 13);
463 int ntest = 14;
464 char buf1[80] __attribute__ ((aligned (16)));
465 char buf2[32] __attribute__ ((aligned (16)));
466 for (size_t n1 = 0; n1 < 16; ++n1)
467 for (size_t n2 = 0; n2 < 16; ++n2)
468 for (size_t n3 = 0; n3 < 32; ++n3)
469 for (size_t n4 = 0; n4 < 16; ++n4)
471 size_t olderrors = errors;
473 memset (buf1, 'b', sizeof (buf1));
475 memset (buf1 + n2, 'a', n3);
476 buf1[n2 + n3] = '\0';
477 strcpy (buf2 + n1, "123");
479 DIAG_PUSH_NEEDS_COMMENT;
480 #if __GNUC_PREREQ (7, 0)
481 /* GCC 7 warns about the size passed to strncat being
482 larger than the size of the buffer; this is
483 deliberately tested here.. */
484 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
485 #endif
486 check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
487 == buf1 + n2, ntest);
488 DIAG_POP_NEEDS_COMMENT;
489 if (errors == olderrors)
490 for (size_t i = 0; i < sizeof (buf1); ++i)
492 if (i < n2)
493 check (buf1[i] == 'b', ntest);
494 else if (i < n2 + n3)
495 check (buf1[i] == 'a', ntest);
496 else if (i < n2 + n3 + 3)
497 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
498 else if (i == n2 + n3 + 3)
499 check (buf1[i] == '\0', ntest);
500 else
501 check (buf1[i] == 'b', ntest);
503 if (errors != olderrors)
505 printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
506 n1, n2, n3, n4, buf1[0]);
507 for (size_t j = 1; j < sizeof (buf1); ++j)
508 printf (",%02hhx", buf1[j]);
509 putchar_unlocked ('\n');
510 break;
516 static void
517 test_strncmp (void)
519 /* First test as strcmp with big counts, then test count code. */
520 it = "strncmp";
521 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
522 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
523 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
524 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
525 check (strncmp ("abcd", "abc", 99) > 0, 5);
526 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
527 check (strncmp ("abce", "abcd", 99) > 0, 7);
528 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
529 check (strncmp ("a\203", "a\003", 2) > 0, 9);
530 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
531 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
532 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
533 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
534 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
535 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
538 static void
539 test_strncpy (void)
541 /* Testing is a bit different because of odd semantics. */
542 it = "strncpy";
543 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
544 equal (one, "abc", 2); /* Did the copy go right? */
546 (void) strcpy (one, "abcdefgh");
547 DIAG_PUSH_NEEDS_COMMENT;
548 #if __GNUC_PREREQ (8, 0)
549 /* GCC 8 warns about strncpy truncating output; this is deliberately
550 tested here. */
551 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
552 #endif
553 (void) strncpy (one, "xyz", 2);
554 DIAG_POP_NEEDS_COMMENT;
555 equal (one, "xycdefgh", 3); /* Copy cut by count. */
557 (void) strcpy (one, "abcdefgh");
558 DIAG_PUSH_NEEDS_COMMENT;
559 #if __GNUC_PREREQ (8, 0)
560 /* GCC 8 warns about strncpy truncating output; this is deliberately
561 tested here. */
562 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
563 #endif
564 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
565 DIAG_POP_NEEDS_COMMENT;
566 equal (one, "xyzdefgh", 4);
568 (void) strcpy (one, "abcdefgh");
569 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
570 equal (one, "xyz", 5);
571 equal (one+4, "efgh", 6); /* Wrote too much? */
573 (void) strcpy (one, "abcdefgh");
574 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
575 equal (one, "xyz", 7);
576 equal (one+4, "", 8);
577 equal (one+5, "fgh", 9);
579 (void) strcpy (one, "abc");
580 DIAG_PUSH_NEEDS_COMMENT;
581 #if __GNUC_PREREQ (8, 0)
582 /* GCC 8 warns about strncpy truncating output; this is deliberately
583 tested here. */
584 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
585 #endif
586 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
587 DIAG_POP_NEEDS_COMMENT;
588 equal (one, "abc", 10);
590 (void) strncpy (one, "", 2); /* Zero-length source. */
591 equal (one, "", 11);
592 equal (one+1, "", 12);
593 equal (one+2, "c", 13);
595 (void) strcpy (one, "hi there");
596 (void) strncpy (two, one, 9);
597 equal (two, "hi there", 14); /* Just paranoia. */
598 equal (one, "hi there", 15); /* Stomped on source? */
601 static void
602 test_strlen (void)
604 it = "strlen";
605 check (strlen ("") == 0, 1); /* Empty. */
606 check (strlen ("a") == 1, 2); /* Single char. */
607 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
609 char buf[4096];
610 int i;
611 char *p;
612 for (i=0; i < 0x100; i++)
614 p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
615 strcpy (p, "OK");
616 strcpy (p+3, "BAD/WRONG");
617 check (strlen (p) == 2, 4+i);
622 static void
623 test_strnlen (void)
625 it = "strnlen";
626 check (strnlen ("", 10) == 0, 1); /* Empty. */
627 check (strnlen ("a", 10) == 1, 2); /* Single char. */
628 check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
629 check (strnlen ("foo", (size_t) -1) == 3, 4); /* limits of n. */
630 check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
631 check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
632 check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
633 check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
634 check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
636 char buf[4096];
637 for (int i = 0; i < 0x100; ++i)
639 char *p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i;
640 strcpy (p, "OK");
641 strcpy (p + 3, "BAD/WRONG");
642 check (strnlen (p, 100) == 2, 10 + i);
646 static void
647 test_strchr (void)
649 it = "strchr";
650 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
651 (void) strcpy (one, "abcd");
652 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
653 check (strchr (one, 'd') == one+3, 3); /* End of string. */
654 check (strchr (one, 'a') == one, 4); /* Beginning. */
655 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
656 (void) strcpy (one, "ababa");
657 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
658 (void) strcpy (one, "");
659 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
660 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
662 char buf[4096];
663 int i;
664 char *p;
665 for (i=0; i < 0x100; i++)
667 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
668 strcpy (p, "OK");
669 strcpy (p+3, "BAD/WRONG");
670 check (strchr (p, '/') == NULL, 9+i);
675 static void
676 test_strchrnul (void)
678 const char *os;
679 it = "strchrnul";
680 cp = strchrnul ((os = "abcd"), 'z');
681 check (*cp == '\0', 1); /* Not found. */
682 check (cp == os + 4, 2);
683 (void) strcpy (one, "abcd");
684 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
685 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
686 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
687 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
688 (void) strcpy (one, "ababa");
689 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
690 (void) strcpy (one, "");
691 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
692 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
694 char buf[4096];
695 int i;
696 char *p;
697 for (i=0; i < 0x100; i++)
699 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
700 strcpy (p, "OK");
701 strcpy (p+3, "BAD/WRONG");
702 cp = strchrnul (p, '/');
703 check (*cp == '\0', 9+2*i);
704 check (cp == p+2, 10+2*i);
709 static void
710 test_rawmemchr (void)
712 it = "rawmemchr";
713 (void) strcpy (one, "abcd");
714 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
715 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
716 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
717 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
718 (void) strcpy (one, "ababa");
719 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
720 (void) strcpy (one, "");
721 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
723 char buf[4096];
724 int i;
725 char *p;
726 for (i=0; i < 0x100; i++)
728 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
729 strcpy (p, "OK");
730 strcpy (p+3, "BAD/WRONG");
731 check (rawmemchr (p, 'R') == p+8, 6+i);
736 static void
737 test_index (void)
739 it = "index";
740 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
741 (void) strcpy (one, "abcd");
742 check (index (one, 'c') == one+2, 2); /* Basic test. */
743 check (index (one, 'd') == one+3, 3); /* End of string. */
744 check (index (one, 'a') == one, 4); /* Beginning. */
745 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
746 (void) strcpy (one, "ababa");
747 check (index (one, 'b') == one+1, 6); /* Finding first. */
748 (void) strcpy (one, "");
749 check (index (one, 'b') == NULL, 7); /* Empty string. */
750 check (index (one, '\0') == one, 8); /* NUL in empty string. */
753 static void
754 test_strrchr (void)
756 it = "strrchr";
757 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
758 (void) strcpy (one, "abcd");
759 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
760 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
761 check (strrchr (one, 'a') == one, 4); /* Beginning. */
762 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
763 (void) strcpy (one, "ababa");
764 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
765 (void) strcpy (one, "");
766 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
767 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
769 char buf[4096];
770 int i;
771 char *p;
772 for (i=0; i < 0x100; i++)
774 p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i;
775 strcpy (p, "OK");
776 strcpy (p+3, "BAD/WRONG");
777 check (strrchr (p, '/') == NULL, 9+i);
782 static void
783 test_memrchr (void)
785 size_t l;
786 it = "memrchr";
787 check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
788 (void) strcpy (one, "abcd");
789 l = strlen (one) + 1;
790 check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
791 check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
792 check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
793 check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
794 (void) strcpy (one, "ababa");
795 l = strlen (one) + 1;
796 check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
797 (void) strcpy (one, "");
798 l = strlen (one) + 1;
799 check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
800 check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
802 /* now test all possible alignment and length combinations to catch
803 bugs due to unrolled loops (assuming unrolling is limited to no
804 more than 128 byte chunks: */
806 char buf[128 + sizeof(long)];
807 long align, len, i, pos, n = 9;
809 for (align = 0; align < (long) sizeof(long); ++align) {
810 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
811 for (i = 0; i < len; ++i)
812 buf[align + i] = 'x'; /* don't depend on memset... */
814 for (pos = len - 1; pos >= 0; --pos) {
815 #if 0
816 printf("align %d, len %d, pos %d\n", align, len, pos);
817 #endif
818 check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
819 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
820 n++);
821 buf[align + pos] = '-';
828 static void
829 test_rindex (void)
831 it = "rindex";
832 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
833 (void) strcpy (one, "abcd");
834 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
835 check (rindex (one, 'd') == one+3, 3); /* End of string. */
836 check (rindex (one, 'a') == one, 4); /* Beginning. */
837 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
838 (void) strcpy (one, "ababa");
839 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
840 (void) strcpy (one, "");
841 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
842 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
845 static void
846 test_strpbrk (void)
848 it = "strpbrk";
849 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
850 (void) strcpy(one, "abcd");
851 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
852 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
853 check(strpbrk(one, "a") == one, 4); /* Beginning. */
854 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
855 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
856 (void) strcpy(one, "abcabdea");
857 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
858 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
859 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
860 (void) strcpy(one, "");
861 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
862 (void) strcpy(one, "");
863 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
864 (void) strcpy(one, "");
865 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
866 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
867 (void) strcpy(one, "abcabdea");
868 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
869 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
870 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
871 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
874 static void
875 test_strstr (void)
877 it = "strstr";
878 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
879 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
880 (void) strcpy(one, "abcd");
881 check(strstr(one, "c") == one+2, 3); /* Basic test. */
882 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
883 check(strstr(one, "d") == one+3, 5); /* End of string. */
884 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
885 check(strstr(one, "abc") == one, 7); /* Beginning. */
886 check(strstr(one, "abcd") == one, 8); /* Exact match. */
887 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
888 check(strstr(one, "de") == NULL, 10); /* Past end. */
889 check(strstr(one, "") == one, 11); /* Finding empty. */
890 (void) strcpy(one, "ababa");
891 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
892 (void) strcpy(one, "");
893 check(strstr(one, "b") == NULL, 13); /* Empty string. */
894 check(strstr(one, "") == one, 14); /* Empty in empty string. */
895 (void) strcpy(one, "bcbca");
896 check(strstr(one, "bca") == one+2, 15); /* False start. */
897 (void) strcpy(one, "bbbcabbca");
898 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
901 static void
902 test_strspn (void)
904 it = "strspn";
905 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
906 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
907 check(strspn("abc", "qx") == 0, 3); /* None. */
908 check(strspn("", "ab") == 0, 4); /* Null string. */
909 check(strspn("abc", "") == 0, 5); /* Null search list. */
912 static void
913 test_strcspn (void)
915 it = "strcspn";
916 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
917 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
918 check(strcspn("abc", "abc") == 0, 3); /* None. */
919 check(strcspn("", "ab") == 0, 4); /* Null string. */
920 check(strcspn("abc", "") == 3, 5); /* Null search list. */
923 static void
924 test_strtok (void)
926 it = "strtok";
927 (void) strcpy(one, "first, second, third");
928 equal(strtok(one, ", "), "first", 1); /* Basic test. */
929 equal(one, "first", 2);
930 equal(strtok((char *)NULL, ", "), "second", 3);
931 equal(strtok((char *)NULL, ", "), "third", 4);
932 check(strtok((char *)NULL, ", ") == NULL, 5);
933 (void) strcpy(one, ", first, ");
934 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
935 check(strtok((char *)NULL, ", ") == NULL, 7);
936 (void) strcpy(one, "1a, 1b; 2a, 2b");
937 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
938 equal(strtok((char *)NULL, "; "), "1b", 9);
939 equal(strtok((char *)NULL, ", "), "2a", 10);
940 (void) strcpy(two, "x-y");
941 equal(strtok(two, "-"), "x", 11); /* New string before done. */
942 equal(strtok((char *)NULL, "-"), "y", 12);
943 check(strtok((char *)NULL, "-") == NULL, 13);
944 (void) strcpy(one, "a,b, c,, ,d");
945 equal(strtok(one, ", "), "a", 14); /* Different separators. */
946 equal(strtok((char *)NULL, ", "), "b", 15);
947 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
948 equal(strtok((char *)NULL, " ,"), "d", 17);
949 check(strtok((char *)NULL, ", ") == NULL, 18);
950 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
951 (void) strcpy(one, ", ");
952 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
953 (void) strcpy(one, "");
954 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
955 (void) strcpy(one, "abc");
956 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
957 check(strtok((char *)NULL, ", ") == NULL, 23);
958 (void) strcpy(one, "abc");
959 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
960 check(strtok((char *)NULL, "") == NULL, 25);
961 (void) strcpy(one, "abcdefgh");
962 (void) strcpy(one, "a,b,c");
963 equal(strtok(one, ","), "a", 26); /* Basics again... */
964 equal(strtok((char *)NULL, ","), "b", 27);
965 equal(strtok((char *)NULL, ","), "c", 28);
966 check(strtok((char *)NULL, ",") == NULL, 29);
967 equal(one+6, "gh", 30); /* Stomped past end? */
968 equal(one, "a", 31); /* Stomped old tokens? */
969 equal(one+2, "b", 32);
970 equal(one+4, "c", 33);
973 static void
974 test_strtok_r (void)
976 it = "strtok_r";
977 (void) strcpy(one, "first, second, third");
978 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
979 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
980 equal(one, "first", 2);
981 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
982 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
983 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
984 (void) strcpy(one, ", first, ");
985 cp = NULL;
986 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
987 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
988 (void) strcpy(one, "1a, 1b; 2a, 2b");
989 cp = NULL;
990 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
991 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
992 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
993 (void) strcpy(two, "x-y");
994 cp = NULL;
995 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
996 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
997 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
998 (void) strcpy(one, "a,b, c,, ,d");
999 cp = NULL;
1000 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
1001 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
1002 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
1003 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
1004 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
1005 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
1006 (void) strcpy(one, ", ");
1007 cp = NULL;
1008 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
1009 (void) strcpy(one, "");
1010 cp = NULL;
1011 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
1012 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
1013 (void) strcpy(one, "abc");
1014 cp = NULL;
1015 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
1016 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
1017 (void) strcpy(one, "abc");
1018 cp = NULL;
1019 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
1020 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
1021 (void) strcpy(one, "abcdefgh");
1022 (void) strcpy(one, "a,b,c");
1023 cp = NULL;
1024 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
1025 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
1026 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
1027 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
1028 equal(one+6, "gh", 31); /* Stomped past end? */
1029 equal(one, "a", 32); /* Stomped old tokens? */
1030 equal(one+2, "b", 33);
1031 equal(one+4, "c", 34);
1032 strcpy (one, ":::");
1033 cp = NULL;
1034 check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
1035 check (strtok_r (NULL, ":", &cp) == NULL, 36);
1038 static void
1039 test_strsep (void)
1041 char *ptr;
1042 it = "strsep";
1043 cp = strcpy(one, "first, second, third");
1044 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
1045 equal(one, "first", 2);
1046 equal(strsep(&cp, ", "), "", 3);
1047 equal(strsep(&cp, ", "), "second", 4);
1048 equal(strsep(&cp, ", "), "", 5);
1049 equal(strsep(&cp, ", "), "third", 6);
1050 check(strsep(&cp, ", ") == NULL, 7);
1051 cp = strcpy(one, ", first, ");
1052 equal(strsep(&cp, ", "), "", 8);
1053 equal(strsep(&cp, ", "), "", 9);
1054 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
1055 equal(strsep(&cp, ", "), "", 11);
1056 equal(strsep(&cp, ", "), "", 12);
1057 check(strsep(&cp, ", ") == NULL, 13);
1058 cp = strcpy(one, "1a, 1b; 2a, 2b");
1059 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
1060 equal(strsep(&cp, ", "), "", 15);
1061 equal(strsep(&cp, "; "), "1b", 16);
1062 equal(strsep(&cp, ", "), "", 17);
1063 equal(strsep(&cp, ", "), "2a", 18);
1064 cp = strcpy(two, "x-y");
1065 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
1066 equal(strsep(&cp, "-"), "y", 20);
1067 check(strsep(&cp, "-") == NULL, 21);
1068 cp = strcpy(one, "a,b, c,, ,d ");
1069 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
1070 equal(strsep(&cp, ", "), "b", 23);
1071 equal(strsep(&cp, " ,"), "", 24);
1072 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
1073 equal(strsep(&cp, " ,"), "", 26);
1074 equal(strsep(&cp, " ,"), "", 27);
1075 equal(strsep(&cp, " ,"), "", 28);
1076 equal(strsep(&cp, " ,"), "d", 29);
1077 equal(strsep(&cp, " ,"), "", 30);
1078 check(strsep(&cp, ", ") == NULL, 31);
1079 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
1080 cp = strcpy(one, ", ");
1081 equal(strsep(&cp, ", "), "", 33);
1082 equal(strsep(&cp, ", "), "", 34);
1083 equal(strsep(&cp, ", "), "", 35);
1084 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
1085 cp = strcpy(one, "");
1086 equal(strsep(&cp, ", "), "", 37);
1087 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
1088 cp = strcpy(one, "abc");
1089 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
1090 check(strsep(&cp, ", ") == NULL, 40);
1091 cp = strcpy(one, "abc");
1092 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
1093 check(strsep(&cp, "") == NULL, 42);
1094 (void) strcpy(one, "abcdefgh");
1095 cp = strcpy(one, "a,b,c");
1096 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
1097 equal(strsep(&cp, ","), "b", 44);
1098 equal(strsep(&cp, ","), "c", 45);
1099 check(strsep(&cp, ",") == NULL, 46);
1100 equal(one+6, "gh", 47); /* Stomped past end? */
1101 equal(one, "a", 48); /* Stomped old tokens? */
1102 equal(one+2, "b", 49);
1103 equal(one+4, "c", 50);
1106 char text[] = "This,is,a,test";
1107 char *list = strdupa (text);
1108 equal (strsep (&list, ","), "This", 51);
1109 equal (strsep (&list, ","), "is", 52);
1110 equal (strsep (&list, ","), "a", 53);
1111 equal (strsep (&list, ","), "test", 54);
1112 check (strsep (&list, ",") == NULL, 55);
1115 cp = strcpy(one, "a,b, c,, ,d,");
1116 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1117 equal(strsep(&cp, ","), "b", 57);
1118 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1119 equal(strsep(&cp, ","), "", 59);
1120 equal(strsep(&cp, ","), " ", 60);
1121 equal(strsep(&cp, ","), "d", 61);
1122 equal(strsep(&cp, ","), "", 62);
1123 check(strsep(&cp, ",") == NULL, 63);
1124 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1126 cp = strcpy(one, "a,b, c,, ,d,");
1127 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1128 equal(strsep(&cp, "x,y"), "b", 66);
1129 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1130 equal(strsep(&cp, "xy,"), "", 68);
1131 equal(strsep(&cp, "x,y"), " ", 69);
1132 equal(strsep(&cp, ",xy"), "d", 70);
1133 equal(strsep(&cp, "xy,"), "", 71);
1134 check(strsep(&cp, "x,y") == NULL, 72);
1135 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1137 cp = strcpy(one, "ABC");
1138 one[4] = ':';
1139 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1140 ptr = strsep(&cp, ":");
1141 equal(ptr, "", 75);
1142 check(ptr == one + 3, 76);
1143 check(cp == NULL, 77);
1145 cp = strcpy(one, "ABC");
1146 one[4] = ':';
1147 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1148 ptr = strsep(&cp, ":.");
1149 equal(ptr, "", 79);
1150 check(ptr == one + 3, 80);
1152 cp = strcpy(one, "ABC"); /* No token in string. */
1153 equal(strsep(&cp, ","), "ABC", 81);
1154 check(cp == NULL, 82);
1156 *one = '\0'; /* Empty string. */
1157 cp = one;
1158 ptr = strsep(&cp, ",");
1159 equal(ptr, "", 83);
1160 check(ptr == one, 84);
1161 check(cp == NULL, 85);
1163 *one = '\0'; /* Empty string and no token. */
1164 cp = one;
1165 ptr = strsep(&cp, "");
1166 equal(ptr, "", 86);
1167 check(ptr == one , 87);
1168 check(cp == NULL, 88);
1171 static void
1172 test_memcmp (void)
1174 int cnt = 1;
1175 char one[21];
1176 char two[21];
1178 it = "memcmp";
1179 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1180 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1181 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1182 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1183 check(memcmp("alph", "cold", 4) < 0, cnt++);
1184 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1185 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1186 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1187 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1188 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1189 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1190 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1191 /* Comparisons with shifting 4-byte boundaries. */
1192 for (int i = 0; i < 4; ++i)
1194 char *a = one + i;
1195 char *b = two + i;
1196 memcpy(a, "--------11112222", 16);
1197 memcpy(b, "--------33334444", 16);
1198 check(memcmp(b, a, 16) > 0, cnt++);
1199 check(memcmp(a, b, 16) < 0, cnt++);
1203 static void
1204 test_memchr (void)
1206 it = "memchr";
1207 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1208 (void) strcpy(one, "abcd");
1209 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1210 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1211 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1212 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1213 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1214 (void) strcpy(one, "ababa");
1215 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1216 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1217 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1218 (void) strcpy(one, "a\203b");
1219 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1221 /* now test all possible alignment and length combinations to catch
1222 bugs due to unrolled loops (assuming unrolling is limited to no
1223 more than 128 byte chunks: */
1225 char buf[128 + sizeof(long)];
1226 long align, len, i, pos;
1228 for (align = 0; align < (long) sizeof(long); ++align) {
1229 for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
1230 for (i = 0; i < len; ++i) {
1231 buf[align + i] = 'x'; /* don't depend on memset... */
1233 for (pos = 0; pos < len; ++pos) {
1234 #if 0
1235 printf("align %d, len %d, pos %d\n", align, len, pos);
1236 #endif
1237 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1238 check(memchr(buf + align, 'x', pos) == NULL, 11);
1239 buf[align + pos] = '-';
1246 static void
1247 test_memcpy (void)
1249 int i;
1250 it = "memcpy";
1251 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1252 equal(one, "abc", 2); /* Did the copy go right? */
1254 (void) strcpy(one, "abcdefgh");
1255 (void) memcpy(one+1, "xyz", 2);
1256 equal(one, "axydefgh", 3); /* Basic test. */
1258 (void) strcpy(one, "abc");
1259 (void) memcpy(one, "xyz", 0);
1260 equal(one, "abc", 4); /* Zero-length copy. */
1262 (void) strcpy(one, "hi there");
1263 (void) strcpy(two, "foo");
1264 (void) memcpy(two, one, 9);
1265 equal(two, "hi there", 5); /* Just paranoia. */
1266 equal(one, "hi there", 6); /* Stomped on source? */
1268 for (i = 0; i < 16; i++)
1270 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1271 strcpy (one, x);
1272 check (memcpy (one + i, "hi there", 9) == one + i,
1273 7 + (i * 6)); /* Unaligned destination. */
1274 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1275 equal (one + i, "hi there", 9 + (i * 6));
1276 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1277 check (memcpy (two, one + i, 9) == two,
1278 11 + (i * 6)); /* Unaligned source. */
1279 equal (two, "hi there", 12 + (i * 6));
1283 static void
1284 test_mempcpy (void)
1286 int i;
1287 it = "mempcpy";
1288 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1289 equal(one, "abc", 2); /* Did the copy go right? */
1291 (void) strcpy(one, "abcdefgh");
1292 (void) mempcpy(one+1, "xyz", 2);
1293 equal(one, "axydefgh", 3); /* Basic test. */
1295 (void) strcpy(one, "abc");
1296 (void) mempcpy(one, "xyz", 0);
1297 equal(one, "abc", 4); /* Zero-length copy. */
1299 (void) strcpy(one, "hi there");
1300 (void) strcpy(two, "foo");
1301 (void) mempcpy(two, one, 9);
1302 equal(two, "hi there", 5); /* Just paranoia. */
1303 equal(one, "hi there", 6); /* Stomped on source? */
1305 for (i = 0; i < 16; i++)
1307 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1308 strcpy (one, x);
1309 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1310 7 + (i * 6)); /* Unaligned destination. */
1311 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1312 equal (one + i, "hi there", 9 + (i * 6));
1313 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1314 check (mempcpy (two, one + i, 9) == two + 9,
1315 11 + (i * 6)); /* Unaligned source. */
1316 equal (two, "hi there", 12 + (i * 6));
1320 static void
1321 test_memmove (void)
1323 it = "memmove";
1324 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1325 equal(one, "abc", 2); /* Did the copy go right? */
1327 (void) strcpy(one, "abcdefgh");
1328 (void) memmove(one+1, "xyz", 2);
1329 equal(one, "axydefgh", 3); /* Basic test. */
1331 (void) strcpy(one, "abc");
1332 (void) memmove(one, "xyz", 0);
1333 equal(one, "abc", 4); /* Zero-length copy. */
1335 (void) strcpy(one, "hi there");
1336 (void) strcpy(two, "foo");
1337 (void) memmove(two, one, 9);
1338 equal(two, "hi there", 5); /* Just paranoia. */
1339 equal(one, "hi there", 6); /* Stomped on source? */
1341 (void) strcpy(one, "abcdefgh");
1342 (void) memmove(one+1, one, 9);
1343 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1345 (void) strcpy(one, "abcdefgh");
1346 (void) memmove(one+1, one+2, 7);
1347 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1349 (void) strcpy(one, "abcdefgh");
1350 (void) memmove(one, one, 9);
1351 equal(one, "abcdefgh", 9); /* 100% overlap. */
1354 static void
1355 test_memccpy (void)
1357 /* First test like memcpy, then the search part The SVID, the only
1358 place where memccpy is mentioned, says overlap might fail, so we
1359 don't try it. Besides, it's hard to see the rationale for a
1360 non-left-to-right memccpy. */
1361 it = "memccpy";
1362 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1363 equal(one, "abc", 2); /* Did the copy go right? */
1365 (void) strcpy(one, "abcdefgh");
1366 (void) memccpy(one+1, "xyz", 'q', 2);
1367 equal(one, "axydefgh", 3); /* Basic test. */
1369 (void) strcpy(one, "abc");
1370 (void) memccpy(one, "xyz", 'q', 0);
1371 equal(one, "abc", 4); /* Zero-length copy. */
1373 (void) strcpy(one, "hi there");
1374 (void) strcpy(two, "foo");
1375 (void) memccpy(two, one, 'q', 9);
1376 equal(two, "hi there", 5); /* Just paranoia. */
1377 equal(one, "hi there", 6); /* Stomped on source? */
1379 (void) strcpy(one, "abcdefgh");
1380 (void) strcpy(two, "horsefeathers");
1381 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1382 equal(one, "abcdefgh", 8); /* Source intact? */
1383 equal(two, "abcdefeathers", 9); /* Copy correct? */
1385 (void) strcpy(one, "abcd");
1386 (void) strcpy(two, "bumblebee");
1387 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1388 equal(two, "aumblebee", 11);
1389 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1390 equal(two, "abcdlebee", 13);
1391 (void) strcpy(one, "xyz");
1392 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1393 equal(two, "xbcdlebee", 15);
1396 static void
1397 test_memset (void)
1399 int i;
1401 it = "memset";
1402 (void) strcpy(one, "abcdefgh");
1403 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1404 equal(one, "axxxefgh", 2); /* Basic test. */
1406 DIAG_PUSH_NEEDS_COMMENT;
1407 #if __GNUC_PREREQ (5, 0)
1408 /* GCC 5.0 warns about a zero-length memset because the arguments to memset
1409 may be in the wrong order. But we really want to test this. */
1410 DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args")
1411 #endif
1412 (void) memset(one+2, 'y', 0);
1413 equal(one, "axxxefgh", 3); /* Zero-length set. */
1414 DIAG_POP_NEEDS_COMMENT;
1416 (void) memset(one+5, 0, 1);
1417 equal(one, "axxxe", 4); /* Zero fill. */
1418 equal(one+6, "gh", 5); /* And the leftover. */
1420 (void) memset(one+2, 010045, 1);
1421 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1423 /* Non-8bit fill character. */
1424 memset (one, 0x101, sizeof (one));
1425 for (i = 0; i < (int) sizeof (one); ++i)
1426 check (one[i] == '\01', 7);
1428 /* Test for more complex versions of memset, for all alignments and
1429 lengths up to 256. This test takes a little while, perhaps it should
1430 be made weaker? */
1432 char data[512];
1433 int j;
1434 int k;
1435 int c;
1437 for (i = 0; i < 512; i++)
1438 data[i] = 'x';
1439 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1440 memset(,'y',) */
1441 for (j = 0; j < 256; j++)
1442 for (i = 0; i < 256; i++)
1444 memset (data + i, c, j);
1445 for (k = 0; k < i; k++)
1446 if (data[k] != 'x')
1447 goto fail;
1448 for (k = i; k < i+j; k++)
1450 if (data[k] != c)
1451 goto fail;
1452 data[k] = 'x';
1454 for (k = i+j; k < 512; k++)
1455 if (data[k] != 'x')
1456 goto fail;
1457 continue;
1459 fail:
1460 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1465 static void
1466 test_bcopy (void)
1468 /* Much like memcpy. Berklix manual is silent about overlap, so
1469 don't test it. */
1470 it = "bcopy";
1471 (void) bcopy("abc", one, 4);
1472 equal(one, "abc", 1); /* Simple copy. */
1474 (void) strcpy(one, "abcdefgh");
1475 (void) bcopy("xyz", one+1, 2);
1476 equal(one, "axydefgh", 2); /* Basic test. */
1478 (void) strcpy(one, "abc");
1479 (void) bcopy("xyz", one, 0);
1480 equal(one, "abc", 3); /* Zero-length copy. */
1482 (void) strcpy(one, "hi there");
1483 (void) strcpy(two, "foo");
1484 (void) bcopy(one, two, 9);
1485 equal(two, "hi there", 4); /* Just paranoia. */
1486 equal(one, "hi there", 5); /* Stomped on source? */
1489 static void
1490 test_bzero (void)
1492 it = "bzero";
1493 (void) strcpy(one, "abcdef");
1494 bzero(one+2, 2);
1495 equal(one, "ab", 1); /* Basic test. */
1496 equal(one+3, "", 2);
1497 equal(one+4, "ef", 3);
1499 (void) strcpy(one, "abcdef");
1500 bzero(one+2, 0);
1501 equal(one, "abcdef", 4); /* Zero-length copy. */
1504 static void
1505 test_strndup (void)
1507 char *p, *q;
1508 it = "strndup";
1509 p = strndup("abcdef", 12);
1510 check(p != NULL, 1);
1511 if (p != NULL)
1513 equal(p, "abcdef", 2);
1514 q = strndup(p + 1, 2);
1515 check(q != NULL, 3);
1516 if (q != NULL)
1517 equal(q, "bc", 4);
1518 free (q);
1520 free (p);
1521 p = strndup("abc def", 3);
1522 check(p != NULL, 5);
1523 if (p != NULL)
1524 equal(p, "abc", 6);
1525 free (p);
1528 static void
1529 test_bcmp (void)
1531 it = "bcmp";
1532 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1533 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1534 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1535 check(bcmp("abce", "abcd", 4) != 0, 4);
1536 check(bcmp("alph", "beta", 4) != 0, 5);
1537 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1538 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1541 static void
1542 test_strerror (void)
1544 it = "strerror";
1545 check(strerror(EDOM) != 0, 1);
1546 check(strerror(ERANGE) != 0, 2);
1547 check(strerror(ENOENT) != 0, 3);
1550 static void
1551 test_strcasecmp (void)
1553 it = "strcasecmp";
1554 /* Note that the locale is "C". */
1555 check(strcasecmp("a", "a") == 0, 1);
1556 check(strcasecmp("a", "A") == 0, 2);
1557 check(strcasecmp("A", "a") == 0, 3);
1558 check(strcasecmp("a", "b") < 0, 4);
1559 check(strcasecmp("c", "b") > 0, 5);
1560 check(strcasecmp("abc", "AbC") == 0, 6);
1561 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1562 check(strcasecmp("", "0123456789") < 0, 8);
1563 check(strcasecmp("AbC", "") > 0, 9);
1564 check(strcasecmp("AbC", "A") > 0, 10);
1565 check(strcasecmp("AbC", "Ab") > 0, 11);
1566 check(strcasecmp("AbC", "ab") > 0, 12);
1569 static void
1570 test_strncasecmp (void)
1572 it = "strncasecmp";
1573 /* Note that the locale is "C". */
1574 check(strncasecmp("a", "a", 5) == 0, 1);
1575 check(strncasecmp("a", "A", 5) == 0, 2);
1576 check(strncasecmp("A", "a", 5) == 0, 3);
1577 check(strncasecmp("a", "b", 5) < 0, 4);
1578 check(strncasecmp("c", "b", 5) > 0, 5);
1579 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1580 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1581 check(strncasecmp("", "0123456789", 10) < 0, 8);
1582 check(strncasecmp("AbC", "", 5) > 0, 9);
1583 check(strncasecmp("AbC", "A", 5) > 0, 10);
1584 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1585 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1586 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1587 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1588 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1589 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1590 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1591 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1592 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1593 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1597 main (void)
1599 int status;
1601 /* Test strcmp first because we use it to test other things. */
1602 test_strcmp ();
1604 /* Test strcpy next because we need it to set up other tests. */
1605 test_strcpy ();
1607 /* A closely related function is stpcpy. */
1608 test_stpcpy ();
1610 /* stpncpy. */
1611 test_stpncpy ();
1613 /* strcat. */
1614 test_strcat ();
1616 /* strncat. */
1617 test_strncat ();
1619 /* strncmp. */
1620 test_strncmp ();
1622 /* strncpy. */
1623 test_strncpy ();
1625 /* strlen. */
1626 test_strlen ();
1628 /* strnlen. */
1629 test_strnlen ();
1631 /* strchr. */
1632 test_strchr ();
1634 /* strchrnul. */
1635 test_strchrnul ();
1637 /* rawmemchr. */
1638 test_rawmemchr ();
1640 /* index - just like strchr. */
1641 test_index ();
1643 /* strrchr. */
1644 test_strrchr ();
1646 /* memrchr. */
1647 test_memrchr ();
1649 /* rindex - just like strrchr. */
1650 test_rindex ();
1652 /* strpbrk - somewhat like strchr. */
1653 test_strpbrk ();
1655 /* strstr - somewhat like strchr. */
1656 test_strstr ();
1658 /* strspn. */
1659 test_strspn ();
1661 /* strcspn. */
1662 test_strcspn ();
1664 /* strtok - the hard one. */
1665 test_strtok ();
1667 /* strtok_r. */
1668 test_strtok_r ();
1670 /* strsep. */
1671 test_strsep ();
1673 /* memcmp. */
1674 test_memcmp ();
1676 /* memchr. */
1677 test_memchr ();
1679 /* memcpy - need not work for overlap. */
1680 test_memcpy ();
1682 /* memmove - must work on overlap. */
1683 test_memmove ();
1685 /* mempcpy */
1686 test_mempcpy ();
1688 /* memccpy. */
1689 test_memccpy ();
1691 /* memset. */
1692 test_memset ();
1694 /* bcopy. */
1695 test_bcopy ();
1697 /* bzero. */
1698 test_bzero ();
1700 /* bcmp - somewhat like memcmp. */
1701 test_bcmp ();
1703 /* strndup. */
1704 test_strndup ();
1706 /* strerror - VERY system-dependent. */
1707 test_strerror ();
1709 /* strcasecmp. Without locale dependencies. */
1710 test_strcasecmp ();
1712 /* strncasecmp. Without locale dependencies. */
1713 test_strncasecmp ();
1715 if (errors == 0)
1717 status = EXIT_SUCCESS;
1718 puts("No errors.");
1720 else
1722 status = EXIT_FAILURE;
1723 printf("%Zd errors.\n", errors);
1726 return status;