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