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