]>
Commit | Line | Data |
---|---|---|
28f540f4 RM |
1 | #include <ansidecl.h> |
2 | #include <errno.h> | |
3 | #include <stdio.h> | |
4 | #include <stdlib.h> | |
5 | #include <string.h> | |
6 | #include <strings.h> | |
7 | #include <fcntl.h> | |
8 | ||
9 | #ifndef HAVE_GNU_LD | |
10 | #define _sys_nerr sys_nerr | |
11 | #define _sys_errlist sys_errlist | |
12 | #endif | |
13 | ||
14 | #define STREQ(a, b) (strcmp((a), (b)) == 0) | |
15 | ||
16 | CONST char *it = "<UNSET>"; /* Routine name for message routines. */ | |
17 | size_t errors = 0; | |
18 | ||
19 | /* Complain if condition is not true. */ | |
20 | void | |
21 | DEFUN(check, (thing, number), int thing AND int number) | |
22 | { | |
23 | if (!thing) | |
24 | { | |
25 | printf("%s flunked test %d\n", it, number); | |
26 | ++errors; | |
27 | } | |
28 | } | |
29 | ||
30 | /* Complain if first two args don't strcmp as equal. */ | |
31 | void | |
32 | DEFUN(equal, (a, b, number), CONST char *a AND CONST char *b AND int number) | |
33 | { | |
34 | check(a != NULL && b != NULL && STREQ(a, b), number); | |
35 | } | |
36 | ||
37 | char one[50]; | |
38 | char two[50]; | |
39 | ||
40 | int | |
41 | DEFUN(main, (argc, argv), int argc AND char **argv) | |
42 | { | |
59dd8641 RM |
43 | char *cp; |
44 | ||
28f540f4 RM |
45 | /* Test strcmp first because we use it to test other things. */ |
46 | it = "strcmp"; | |
47 | check(strcmp("", "") == 0, 1); /* Trivial case. */ | |
48 | check(strcmp("a", "a") == 0, 2); /* Identity. */ | |
49 | check(strcmp("abc", "abc") == 0, 3); /* Multicharacter. */ | |
50 | check(strcmp("abc", "abcd") < 0, 4); /* Length mismatches. */ | |
51 | check(strcmp("abcd", "abc") > 0, 5); | |
52 | check(strcmp("abcd", "abce") < 0, 6); /* Honest miscompares. */ | |
53 | check(strcmp("abce", "abcd") > 0, 7); | |
54 | check(strcmp("a\203", "a") > 0, 8); /* Tricky if char signed. */ | |
55 | check(strcmp("a\203", "a\003") > 0, 9); | |
56 | ||
57 | /* Test strcpy next because we need it to set up other tests. */ | |
58 | it = "strcpy"; | |
59 | check(strcpy(one, "abcd") == one, 1); /* Returned value. */ | |
60 | equal(one, "abcd", 2); /* Basic test. */ | |
61 | ||
62 | (void) strcpy(one, "x"); | |
63 | equal(one, "x", 3); /* Writeover. */ | |
64 | equal(one+2, "cd", 4); /* Wrote too much? */ | |
65 | ||
66 | (void) strcpy(two, "hi there"); | |
67 | (void) strcpy(one, two); | |
68 | equal(one, "hi there", 5); /* Basic test encore. */ | |
69 | equal(two, "hi there", 6); /* Stomped on source? */ | |
70 | ||
71 | (void) strcpy(one, ""); | |
72 | equal(one, "", 7); /* Boundary condition. */ | |
73 | ||
a5113b14 UD |
74 | /* stpncpy. */ |
75 | it = "stpncpy"; | |
76 | ||
77 | memset(one, 'x', sizeof(one)); | |
78 | check(stpncpy(one, "abc", 2) == one + 2, 1); | |
79 | check(stpncpy(one, "abc", 3) == one + 3, 2); | |
80 | check(stpncpy(one, "abc", 4) == one + 3, 3); | |
81 | check(one[3] == '\0' && one[4] == 'x', 4); | |
82 | check(stpncpy(one, "abcd", 5) == one + 4, 5); | |
83 | check(one[4] == '\0' && one[5] == 'x', 6); | |
84 | check(stpncpy(one, "abcd", 6) == one + 4, 7); | |
85 | check(one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8); | |
86 | ||
28f540f4 RM |
87 | /* strcat. */ |
88 | it = "strcat"; | |
89 | (void) strcpy(one, "ijk"); | |
90 | check(strcat(one, "lmn") == one, 1); /* Returned value. */ | |
91 | equal(one, "ijklmn", 2); /* Basic test. */ | |
92 | ||
93 | (void) strcpy(one, "x"); | |
94 | (void) strcat(one, "yz"); | |
95 | equal(one, "xyz", 3); /* Writeover. */ | |
96 | equal(one+4, "mn", 4); /* Wrote too much? */ | |
97 | ||
98 | (void) strcpy(one, "gh"); | |
99 | (void) strcpy(two, "ef"); | |
100 | (void) strcat(one, two); | |
101 | equal(one, "ghef", 5); /* Basic test encore. */ | |
102 | equal(two, "ef", 6); /* Stomped on source? */ | |
103 | ||
104 | (void) strcpy(one, ""); | |
105 | (void) strcat(one, ""); | |
106 | equal(one, "", 7); /* Boundary conditions. */ | |
107 | (void) strcpy(one, "ab"); | |
108 | (void) strcat(one, ""); | |
109 | equal(one, "ab", 8); | |
110 | (void) strcpy(one, ""); | |
111 | (void) strcat(one, "cd"); | |
112 | equal(one, "cd", 9); | |
113 | ||
114 | /* strncat - first test it as strcat, with big counts, | |
115 | then test the count mechanism. */ | |
116 | it = "strncat"; | |
117 | (void) strcpy(one, "ijk"); | |
118 | check(strncat(one, "lmn", 99) == one, 1); /* Returned value. */ | |
119 | equal(one, "ijklmn", 2); /* Basic test. */ | |
120 | ||
121 | (void) strcpy(one, "x"); | |
122 | (void) strncat(one, "yz", 99); | |
123 | equal(one, "xyz", 3); /* Writeover. */ | |
124 | equal(one+4, "mn", 4); /* Wrote too much? */ | |
125 | ||
126 | (void) strcpy(one, "gh"); | |
127 | (void) strcpy(two, "ef"); | |
128 | (void) strncat(one, two, 99); | |
129 | equal(one, "ghef", 5); /* Basic test encore. */ | |
130 | equal(two, "ef", 6); /* Stomped on source? */ | |
131 | ||
132 | (void) strcpy(one, ""); | |
133 | (void) strncat(one, "", 99); | |
134 | equal(one, "", 7); /* Boundary conditions. */ | |
135 | (void) strcpy(one, "ab"); | |
136 | (void) strncat(one, "", 99); | |
137 | equal(one, "ab", 8); | |
138 | (void) strcpy(one, ""); | |
139 | (void) strncat(one, "cd", 99); | |
140 | equal(one, "cd", 9); | |
141 | ||
142 | (void) strcpy(one, "ab"); | |
143 | (void) strncat(one, "cdef", 2); | |
144 | equal(one, "abcd", 10); /* Count-limited. */ | |
145 | ||
146 | (void) strncat(one, "gh", 0); | |
147 | equal(one, "abcd", 11); /* Zero count. */ | |
148 | ||
149 | (void) strncat(one, "gh", 2); | |
150 | equal(one, "abcdgh", 12); /* Count and length equal. */ | |
151 | ||
152 | /* strncmp - first test as strcmp with big counts, | |
153 | then test count code. */ | |
154 | it = "strncmp"; | |
155 | check(strncmp("", "", 99) == 0, 1); /* Trivial case. */ | |
156 | check(strncmp("a", "a", 99) == 0, 2); /* Identity. */ | |
157 | check(strncmp("abc", "abc", 99) == 0, 3); /* Multicharacter. */ | |
158 | check(strncmp("abc", "abcd", 99) < 0, 4); /* Length unequal. */ | |
159 | check(strncmp("abcd", "abc", 99) > 0, 5); | |
160 | check(strncmp("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */ | |
161 | check(strncmp("abce", "abcd", 99) > 0, 7); | |
162 | check(strncmp("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */ | |
163 | check(strncmp("a\203", "a\003", 2) > 0, 9); | |
164 | check(strncmp("abce", "abcd", 3) == 0, 10); /* Count limited. */ | |
165 | check(strncmp("abce", "abc", 3) == 0, 11); /* Count == length. */ | |
166 | check(strncmp("abcd", "abce", 4) < 0, 12); /* Nudging limit. */ | |
167 | check(strncmp("abc", "def", 0) == 0, 13); /* Zero count. */ | |
168 | ||
169 | /* strncpy - testing is a bit different because of odd semantics. */ | |
170 | it = "strncpy"; | |
171 | check(strncpy(one, "abc", 4) == one, 1); /* Returned value. */ | |
172 | equal(one, "abc", 2); /* Did the copy go right? */ | |
173 | ||
174 | (void) strcpy(one, "abcdefgh"); | |
175 | (void) strncpy(one, "xyz", 2); | |
176 | equal(one, "xycdefgh", 3); /* Copy cut by count. */ | |
177 | ||
178 | (void) strcpy(one, "abcdefgh"); | |
179 | (void) strncpy(one, "xyz", 3); /* Copy cut just before NUL. */ | |
180 | equal(one, "xyzdefgh", 4); | |
181 | ||
182 | (void) strcpy(one, "abcdefgh"); | |
183 | (void) strncpy(one, "xyz", 4); /* Copy just includes NUL. */ | |
184 | equal(one, "xyz", 5); | |
185 | equal(one+4, "efgh", 6); /* Wrote too much? */ | |
186 | ||
187 | (void) strcpy(one, "abcdefgh"); | |
188 | (void) strncpy(one, "xyz", 5); /* Copy includes padding. */ | |
189 | equal(one, "xyz", 7); | |
190 | equal(one+4, "", 8); | |
191 | equal(one+5, "fgh", 9); | |
192 | ||
193 | (void) strcpy(one, "abc"); | |
194 | (void) strncpy(one, "xyz", 0); /* Zero-length copy. */ | |
3e2ee727 | 195 | equal(one, "abc", 10); |
28f540f4 RM |
196 | |
197 | (void) strncpy(one, "", 2); /* Zero-length source. */ | |
198 | equal(one, "", 11); | |
3e2ee727 | 199 | equal(one+1, "", 12); |
28f540f4 RM |
200 | equal(one+2, "c", 13); |
201 | ||
202 | (void) strcpy(one, "hi there"); | |
203 | (void) strncpy(two, one, 9); | |
204 | equal(two, "hi there", 14); /* Just paranoia. */ | |
205 | equal(one, "hi there", 15); /* Stomped on source? */ | |
206 | ||
207 | /* strlen. */ | |
208 | it = "strlen"; | |
209 | check(strlen("") == 0, 1); /* Empty. */ | |
210 | check(strlen("a") == 1, 2); /* Single char. */ | |
569c558c UD |
211 | check(strlen("abcd") == 4, 3); /* Multiple chars. */ |
212 | { | |
213 | char buf[4096]; | |
214 | int i; | |
215 | char *p; | |
216 | for (i=0; i < 0x100; i++) | |
217 | { | |
a68b0d31 | 218 | p = (char *)((unsigned long int)(buf + 0xff) & ~0xff) + i; |
569c558c UD |
219 | strcpy (p, "OK"); |
220 | strcpy (p+3, "BAD/WRONG"); | |
221 | check(strlen(p) == 2, 4+i); | |
222 | } | |
223 | } | |
28f540f4 RM |
224 | |
225 | /* strchr. */ | |
226 | it = "strchr"; | |
227 | check(strchr("abcd", 'z') == NULL, 1); /* Not found. */ | |
228 | (void) strcpy(one, "abcd"); | |
229 | check(strchr(one, 'c') == one+2, 2); /* Basic test. */ | |
230 | check(strchr(one, 'd') == one+3, 3); /* End of string. */ | |
231 | check(strchr(one, 'a') == one, 4); /* Beginning. */ | |
232 | check(strchr(one, '\0') == one+4, 5); /* Finding NUL. */ | |
233 | (void) strcpy(one, "ababa"); | |
234 | check(strchr(one, 'b') == one+1, 6); /* Finding first. */ | |
235 | (void) strcpy(one, ""); | |
236 | check(strchr(one, 'b') == NULL, 7); /* Empty string. */ | |
237 | check(strchr(one, '\0') == one, 8); /* NUL in empty string. */ | |
569c558c UD |
238 | { |
239 | char buf[4096]; | |
240 | int i; | |
241 | char *p; | |
242 | for (i=0; i < 0x100; i++) | |
243 | { | |
a68b0d31 | 244 | p = (char *)((unsigned long int)(buf + 0xff) & ~0xff) + i; |
569c558c UD |
245 | strcpy (p, "OK"); |
246 | strcpy (p+3, "BAD/WRONG"); | |
247 | check(strchr(p, '/') == NULL, 9+i); | |
248 | } | |
249 | } | |
28f540f4 RM |
250 | |
251 | #if 0 | |
252 | /* index - just like strchr. */ | |
253 | it = "index"; | |
254 | check(index("abcd", 'z') == NULL, 1); /* Not found. */ | |
255 | (void) strcpy(one, "abcd"); | |
256 | check(index(one, 'c') == one+2, 2); /* Basic test. */ | |
257 | check(index(one, 'd') == one+3, 3); /* End of string. */ | |
258 | check(index(one, 'a') == one, 4); /* Beginning. */ | |
259 | check(index(one, '\0') == one+4, 5); /* Finding NUL. */ | |
260 | (void) strcpy(one, "ababa"); | |
261 | check(index(one, 'b') == one+1, 6); /* Finding first. */ | |
262 | (void) strcpy(one, ""); | |
263 | check(index(one, 'b') == NULL, 7); /* Empty string. */ | |
264 | check(index(one, '\0') == one, 8); /* NUL in empty string. */ | |
265 | #endif | |
266 | ||
267 | /* strrchr. */ | |
268 | it = "strrchr"; | |
269 | check(strrchr("abcd", 'z') == NULL, 1); /* Not found. */ | |
270 | (void) strcpy(one, "abcd"); | |
271 | check(strrchr(one, 'c') == one+2, 2); /* Basic test. */ | |
272 | check(strrchr(one, 'd') == one+3, 3); /* End of string. */ | |
273 | check(strrchr(one, 'a') == one, 4); /* Beginning. */ | |
274 | check(strrchr(one, '\0') == one+4, 5); /* Finding NUL. */ | |
275 | (void) strcpy(one, "ababa"); | |
276 | check(strrchr(one, 'b') == one+3, 6); /* Finding last. */ | |
277 | (void) strcpy(one, ""); | |
278 | check(strrchr(one, 'b') == NULL, 7); /* Empty string. */ | |
279 | check(strrchr(one, '\0') == one, 8); /* NUL in empty string. */ | |
569c558c UD |
280 | { |
281 | char buf[4096]; | |
282 | int i; | |
283 | char *p; | |
284 | for (i=0; i < 0x100; i++) | |
285 | { | |
a68b0d31 | 286 | p = (char *)((unsigned long int)(buf + 0xff) & ~0xff) + i; |
569c558c UD |
287 | strcpy (p, "OK"); |
288 | strcpy (p+3, "BAD/WRONG"); | |
289 | check(strrchr(p, '/') == NULL, 9+i); | |
290 | } | |
291 | } | |
28f540f4 RM |
292 | |
293 | #if 0 | |
294 | /* rindex - just like strrchr. */ | |
295 | it = "rindex"; | |
296 | check(rindex("abcd", 'z') == NULL, 1); /* Not found. */ | |
297 | (void) strcpy(one, "abcd"); | |
298 | check(rindex(one, 'c') == one+2, 2); /* Basic test. */ | |
299 | check(rindex(one, 'd') == one+3, 3); /* End of string. */ | |
300 | check(rindex(one, 'a') == one, 4); /* Beginning. */ | |
301 | check(rindex(one, '\0') == one+4, 5); /* Finding NUL. */ | |
302 | (void) strcpy(one, "ababa"); | |
303 | check(rindex(one, 'b') == one+3, 6); /* Finding last. */ | |
304 | (void) strcpy(one, ""); | |
305 | check(rindex(one, 'b') == NULL, 7); /* Empty string. */ | |
306 | check(rindex(one, '\0') == one, 8); /* NUL in empty string. */ | |
307 | #endif | |
308 | ||
309 | /* strpbrk - somewhat like strchr. */ | |
310 | it = "strpbrk"; | |
311 | check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */ | |
312 | (void) strcpy(one, "abcd"); | |
313 | check(strpbrk(one, "c") == one+2, 2); /* Basic test. */ | |
314 | check(strpbrk(one, "d") == one+3, 3); /* End of string. */ | |
315 | check(strpbrk(one, "a") == one, 4); /* Beginning. */ | |
316 | check(strpbrk(one, "") == NULL, 5); /* Empty search list. */ | |
317 | check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */ | |
318 | (void) strcpy(one, "abcabdea"); | |
319 | check(strpbrk(one, "b") == one+1, 7); /* Finding first. */ | |
320 | check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */ | |
321 | check(strpbrk(one, "db") == one+1, 9); /* Another variant. */ | |
322 | (void) strcpy(one, ""); | |
323 | check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */ | |
324 | check(strpbrk(one, "") == NULL, 11); /* Both strings empty. */ | |
325 | ||
326 | /* strstr - somewhat like strchr. */ | |
327 | it = "strstr"; | |
328 | check(strstr("abcd", "z") == NULL, 1); /* Not found. */ | |
329 | check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */ | |
330 | (void) strcpy(one, "abcd"); | |
331 | check(strstr(one, "c") == one+2, 3); /* Basic test. */ | |
332 | check(strstr(one, "bc") == one+1, 4); /* Multichar. */ | |
333 | check(strstr(one, "d") == one+3, 5); /* End of string. */ | |
334 | check(strstr(one, "cd") == one+2, 6); /* Tail of string. */ | |
335 | check(strstr(one, "abc") == one, 7); /* Beginning. */ | |
336 | check(strstr(one, "abcd") == one, 8); /* Exact match. */ | |
337 | check(strstr(one, "abcde") == NULL, 9); /* Too long. */ | |
338 | check(strstr(one, "de") == NULL, 10); /* Past end. */ | |
339 | check(strstr(one, "") == one, 11); /* Finding empty. */ | |
340 | (void) strcpy(one, "ababa"); | |
341 | check(strstr(one, "ba") == one+1, 12); /* Finding first. */ | |
342 | (void) strcpy(one, ""); | |
343 | check(strstr(one, "b") == NULL, 13); /* Empty string. */ | |
344 | check(strstr(one, "") == one, 14); /* Empty in empty string. */ | |
345 | (void) strcpy(one, "bcbca"); | |
346 | check(strstr(one, "bca") == one+2, 15); /* False start. */ | |
347 | (void) strcpy(one, "bbbcabbca"); | |
348 | check(strstr(one, "bbca") == one+1, 16); /* With overlap. */ | |
349 | ||
350 | /* strspn. */ | |
351 | it = "strspn"; | |
352 | check(strspn("abcba", "abc") == 5, 1); /* Whole string. */ | |
353 | check(strspn("abcba", "ab") == 2, 2); /* Partial. */ | |
354 | check(strspn("abc", "qx") == 0, 3); /* None. */ | |
355 | check(strspn("", "ab") == 0, 4); /* Null string. */ | |
356 | check(strspn("abc", "") == 0, 5); /* Null search list. */ | |
357 | ||
358 | /* strcspn. */ | |
359 | it = "strcspn"; | |
360 | check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */ | |
361 | check(strcspn("abcba", "cx") == 2, 2); /* Partial. */ | |
362 | check(strcspn("abc", "abc") == 0, 3); /* None. */ | |
363 | check(strcspn("", "ab") == 0, 4); /* Null string. */ | |
364 | check(strcspn("abc", "") == 3, 5); /* Null search list. */ | |
365 | ||
366 | /* strtok - the hard one. */ | |
367 | it = "strtok"; | |
368 | (void) strcpy(one, "first, second, third"); | |
369 | equal(strtok(one, ", "), "first", 1); /* Basic test. */ | |
370 | equal(one, "first", 2); | |
371 | equal(strtok((char *)NULL, ", "), "second", 3); | |
372 | equal(strtok((char *)NULL, ", "), "third", 4); | |
373 | check(strtok((char *)NULL, ", ") == NULL, 5); | |
374 | (void) strcpy(one, ", first, "); | |
375 | equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */ | |
376 | check(strtok((char *)NULL, ", ") == NULL, 7); | |
377 | (void) strcpy(one, "1a, 1b; 2a, 2b"); | |
378 | equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */ | |
379 | equal(strtok((char *)NULL, "; "), "1b", 9); | |
380 | equal(strtok((char *)NULL, ", "), "2a", 10); | |
381 | (void) strcpy(two, "x-y"); | |
382 | equal(strtok(two, "-"), "x", 11); /* New string before done. */ | |
383 | equal(strtok((char *)NULL, "-"), "y", 12); | |
384 | check(strtok((char *)NULL, "-") == NULL, 13); | |
385 | (void) strcpy(one, "a,b, c,, ,d"); | |
386 | equal(strtok(one, ", "), "a", 14); /* Different separators. */ | |
387 | equal(strtok((char *)NULL, ", "), "b", 15); | |
388 | equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */ | |
389 | equal(strtok((char *)NULL, " ,"), "d", 17); | |
390 | check(strtok((char *)NULL, ", ") == NULL, 18); | |
391 | check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */ | |
392 | (void) strcpy(one, ", "); | |
393 | check(strtok(one, ", ") == NULL, 20); /* No tokens. */ | |
394 | (void) strcpy(one, ""); | |
395 | check(strtok(one, ", ") == NULL, 21); /* Empty string. */ | |
396 | (void) strcpy(one, "abc"); | |
397 | equal(strtok(one, ", "), "abc", 22); /* No delimiters. */ | |
398 | check(strtok((char *)NULL, ", ") == NULL, 23); | |
399 | (void) strcpy(one, "abc"); | |
400 | equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */ | |
401 | check(strtok((char *)NULL, "") == NULL, 25); | |
402 | (void) strcpy(one, "abcdefgh"); | |
403 | (void) strcpy(one, "a,b,c"); | |
404 | equal(strtok(one, ","), "a", 26); /* Basics again... */ | |
405 | equal(strtok((char *)NULL, ","), "b", 27); | |
406 | equal(strtok((char *)NULL, ","), "c", 28); | |
407 | check(strtok((char *)NULL, ",") == NULL, 29); | |
408 | equal(one+6, "gh", 30); /* Stomped past end? */ | |
409 | equal(one, "a", 31); /* Stomped old tokens? */ | |
410 | equal(one+2, "b", 32); | |
411 | equal(one+4, "c", 33); | |
412 | ||
59dd8641 RM |
413 | /* strtok_r. */ |
414 | it = "strtok_r"; | |
415 | (void) strcpy(one, "first, second, third"); | |
416 | equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */ | |
417 | equal(one, "first", 2); | |
418 | equal(strtok_r((char *)NULL, ", ", &cp), "second", 3); | |
419 | equal(strtok_r((char *)NULL, ", ", &cp), "third", 4); | |
420 | check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5); | |
421 | (void) strcpy(one, ", first, "); | |
422 | equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */ | |
423 | check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7); | |
424 | (void) strcpy(one, "1a, 1b; 2a, 2b"); | |
425 | equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */ | |
426 | equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9); | |
427 | equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10); | |
428 | (void) strcpy(two, "x-y"); | |
429 | equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */ | |
430 | equal(strtok_r((char *)NULL, "-", &cp), "y", 12); | |
431 | check(strtok_r((char *)NULL, "-", &cp) == NULL, 13); | |
432 | (void) strcpy(one, "a,b, c,, ,d"); | |
433 | equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */ | |
434 | equal(strtok_r((char *)NULL, ", ", &cp), "b", 15); | |
435 | equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */ | |
436 | equal(strtok_r((char *)NULL, " ,", &cp), "d", 17); | |
437 | check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18); | |
438 | check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */ | |
439 | (void) strcpy(one, ", "); | |
440 | check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */ | |
441 | (void) strcpy(one, ""); | |
442 | check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */ | |
443 | (void) strcpy(one, "abc"); | |
444 | equal(strtok_r(one, ", ", &cp), "abc", 22); /* No delimiters. */ | |
445 | check(strtok_r((char *)NULL, ", ", &cp) == NULL, 23); | |
446 | (void) strcpy(one, "abc"); | |
447 | equal(strtok_r(one, "", &cp), "abc", 24); /* Empty delimiter list. */ | |
448 | check(strtok_r((char *)NULL, "", &cp) == NULL, 25); | |
449 | (void) strcpy(one, "abcdefgh"); | |
450 | (void) strcpy(one, "a,b,c"); | |
451 | equal(strtok_r(one, ",", &cp), "a", 26); /* Basics again... */ | |
452 | equal(strtok_r((char *)NULL, ",", &cp), "b", 27); | |
453 | equal(strtok_r((char *)NULL, ",", &cp), "c", 28); | |
454 | check(strtok_r((char *)NULL, ",", &cp) == NULL, 29); | |
455 | equal(one+6, "gh", 30); /* Stomped past end? */ | |
456 | equal(one, "a", 31); /* Stomped old tokens? */ | |
457 | equal(one+2, "b", 32); | |
458 | equal(one+4, "c", 33); | |
459 | ||
460 | /* strsep. */ | |
461 | it = "strsep"; | |
462 | cp = strcpy(one, "first, second, third"); | |
463 | equal(strsep(&cp, ", "), "first", 1); /* Basic test. */ | |
464 | equal(one, "first", 2); | |
76060ec0 RM |
465 | equal(strsep(&cp, ", "), "", 3); |
466 | equal(strsep(&cp, ", "), "second", 4); | |
467 | equal(strsep(&cp, ", "), "", 5); | |
468 | equal(strsep(&cp, ", "), "third", 6); | |
469 | check(strsep(&cp, ", ") == NULL, 7); | |
59dd8641 | 470 | cp = strcpy(one, ", first, "); |
76060ec0 RM |
471 | equal(strsep(&cp, ", "), "", 8); |
472 | equal(strsep(&cp, ", "), "", 9); | |
473 | equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */ | |
474 | equal(strsep(&cp, ", "), "", 11); | |
475 | check(strsep(&cp, ", ") == NULL, 12); | |
59dd8641 | 476 | cp = strcpy(one, "1a, 1b; 2a, 2b"); |
76060ec0 RM |
477 | equal(strsep(&cp, ", "), "1a", 13); /* Changing delim lists. */ |
478 | equal(strsep(&cp, ", "), "", 14); | |
479 | equal(strsep(&cp, "; "), "1b", 15); | |
480 | equal(strsep(&cp, ", "), "", 16); | |
481 | equal(strsep(&cp, ", "), "2a", 17); | |
59dd8641 | 482 | cp = strcpy(two, "x-y"); |
76060ec0 RM |
483 | equal(strsep(&cp, "-"), "x", 18); /* New string before done. */ |
484 | equal(strsep(&cp, "-"), "y", 19); | |
485 | check(strsep(&cp, "-") == NULL, 20); | |
59dd8641 | 486 | cp = strcpy(one, "a,b, c,, ,d"); |
76060ec0 RM |
487 | equal(strsep(&cp, ", "), "a", 21); /* Different separators. */ |
488 | equal(strsep(&cp, ", "), "b", 22); | |
489 | equal(strsep(&cp, " ,"), "", 23); | |
490 | equal(strsep(&cp, " ,"), "c", 24); /* Permute list too. */ | |
491 | equal(strsep(&cp, " ,"), "", 25); | |
492 | equal(strsep(&cp, " ,"), "", 26); | |
493 | equal(strsep(&cp, " ,"), "", 27); | |
494 | equal(strsep(&cp, " ,"), "d", 28); | |
495 | check(strsep(&cp, ", ") == NULL, 29); | |
496 | check(strsep(&cp, ", ") == NULL, 30); /* Persistence. */ | |
59dd8641 | 497 | cp = strcpy(one, ", "); |
76060ec0 RM |
498 | equal(strsep(&cp, ", "), "", 31); |
499 | equal(strsep(&cp, ", "), "", 32); | |
500 | check(strsep(&cp, ", ") == NULL, 33); /* No tokens. */ | |
59dd8641 | 501 | cp = strcpy(one, ""); |
76060ec0 | 502 | check(strsep(&cp, ", ") == NULL, 34); /* Empty string. */ |
59dd8641 | 503 | cp = strcpy(one, "abc"); |
76060ec0 RM |
504 | equal(strsep(&cp, ", "), "abc", 35); /* No delimiters. */ |
505 | check(strsep(&cp, ", ") == NULL, 36); | |
59dd8641 | 506 | cp = strcpy(one, "abc"); |
76060ec0 RM |
507 | equal(strsep(&cp, ""), "abc", 37); /* Empty delimiter list. */ |
508 | check(strsep(&cp, "") == NULL, 38); | |
59dd8641 RM |
509 | (void) strcpy(one, "abcdefgh"); |
510 | cp = strcpy(one, "a,b,c"); | |
76060ec0 RM |
511 | equal(strsep(&cp, ","), "a", 39); /* Basics again... */ |
512 | equal(strsep(&cp, ","), "b", 40); | |
513 | equal(strsep(&cp, ","), "c", 41); | |
514 | check(strsep(&cp, ",") == NULL, 42); | |
515 | equal(one+6, "gh", 43); /* Stomped past end? */ | |
516 | equal(one, "a", 44); /* Stomped old tokens? */ | |
517 | equal(one+2, "b", 45); | |
518 | equal(one+4, "c", 46); | |
59dd8641 | 519 | |
28f540f4 RM |
520 | /* memcmp. */ |
521 | it = "memcmp"; | |
76060ec0 | 522 | check(memcmp("a", "a", 1) == 0, 1); /* Identity. */ |
28f540f4 RM |
523 | check(memcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */ |
524 | check(memcmp("abcd", "abce", 4) < 0, 3); /* Honestly unequal. */ | |
525 | check(memcmp("abce", "abcd", 4) > 0, 4); | |
526 | check(memcmp("alph", "beta", 4) < 0, 5); | |
527 | check(memcmp("a\203", "a\003", 2) > 0, 6); | |
528 | check(memcmp("abce", "abcd", 3) == 0, 7); /* Count limited. */ | |
529 | check(memcmp("abc", "def", 0) == 0, 8); /* Zero count. */ | |
530 | ||
531 | /* memchr. */ | |
532 | it = "memchr"; | |
533 | check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */ | |
534 | (void) strcpy(one, "abcd"); | |
535 | check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */ | |
9b431e31 | 536 | check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */ |
28f540f4 RM |
537 | check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */ |
538 | check(memchr(one, 'a', 4) == one, 4); /* Beginning. */ | |
539 | check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */ | |
540 | (void) strcpy(one, "ababa"); | |
541 | check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */ | |
542 | check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */ | |
543 | check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */ | |
544 | (void) strcpy(one, "a\203b"); | |
545 | check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */ | |
546 | ||
9b431e31 RM |
547 | /* now test all possible alignment and length combinations to catch |
548 | bugs due to unrolled loops (assuming unrolling is limited to no | |
549 | more than 128 byte chunks: */ | |
550 | { | |
551 | char buf[128 + sizeof(long)]; | |
552 | long align, len, i, pos; | |
553 | ||
569c558c UD |
554 | for (align = 0; align < (long) sizeof(long); ++align) { |
555 | for (len = 0; len < (long) (sizeof(buf) - align); ++len) { | |
9b431e31 RM |
556 | for (i = 0; i < len; ++i) { |
557 | buf[align + i] = 'x'; /* don't depend on memset... */ | |
558 | } | |
559 | for (pos = 0; pos < len; ++pos) { | |
560 | #if 0 | |
561 | printf("align %d, len %d, pos %d\n", align, len, pos); | |
562 | #endif | |
563 | check(memchr(buf + align, 'x', len) == buf + align + pos, 10); | |
564 | check(memchr(buf + align, 'x', pos) == NULL, 11); | |
565 | buf[align + pos] = '-'; | |
566 | } | |
567 | } | |
568 | } | |
569 | } | |
570 | ||
28f540f4 RM |
571 | /* memcpy - need not work for overlap. */ |
572 | it = "memcpy"; | |
573 | check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */ | |
574 | equal(one, "abc", 2); /* Did the copy go right? */ | |
575 | ||
576 | (void) strcpy(one, "abcdefgh"); | |
577 | (void) memcpy(one+1, "xyz", 2); | |
578 | equal(one, "axydefgh", 3); /* Basic test. */ | |
579 | ||
580 | (void) strcpy(one, "abc"); | |
581 | (void) memcpy(one, "xyz", 0); | |
582 | equal(one, "abc", 4); /* Zero-length copy. */ | |
583 | ||
584 | (void) strcpy(one, "hi there"); | |
585 | (void) strcpy(two, "foo"); | |
586 | (void) memcpy(two, one, 9); | |
587 | equal(two, "hi there", 5); /* Just paranoia. */ | |
588 | equal(one, "hi there", 6); /* Stomped on source? */ | |
589 | ||
590 | /* memmove - must work on overlap. */ | |
591 | it = "memmove"; | |
592 | check(memmove(one, "abc", 4) == one, 1); /* Returned value. */ | |
593 | equal(one, "abc", 2); /* Did the copy go right? */ | |
594 | ||
595 | (void) strcpy(one, "abcdefgh"); | |
596 | (void) memmove(one+1, "xyz", 2); | |
597 | equal(one, "axydefgh", 3); /* Basic test. */ | |
598 | ||
599 | (void) strcpy(one, "abc"); | |
600 | (void) memmove(one, "xyz", 0); | |
601 | equal(one, "abc", 4); /* Zero-length copy. */ | |
602 | ||
603 | (void) strcpy(one, "hi there"); | |
604 | (void) strcpy(two, "foo"); | |
605 | (void) memmove(two, one, 9); | |
606 | equal(two, "hi there", 5); /* Just paranoia. */ | |
607 | equal(one, "hi there", 6); /* Stomped on source? */ | |
608 | ||
609 | (void) strcpy(one, "abcdefgh"); | |
610 | (void) memmove(one+1, one, 9); | |
611 | equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */ | |
612 | ||
613 | (void) strcpy(one, "abcdefgh"); | |
614 | (void) memmove(one+1, one+2, 7); | |
615 | equal(one, "acdefgh", 8); /* Overlap, left-to-right. */ | |
616 | ||
617 | (void) strcpy(one, "abcdefgh"); | |
618 | (void) memmove(one, one, 9); | |
619 | equal(one, "abcdefgh", 9); /* 100% overlap. */ | |
620 | ||
621 | /* memccpy - first test like memcpy, then the search part | |
622 | The SVID, the only place where memccpy is mentioned, says | |
623 | overlap might fail, so we don't try it. Besides, it's hard | |
624 | to see the rationale for a non-left-to-right memccpy. */ | |
625 | it = "memccpy"; | |
626 | check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */ | |
627 | equal(one, "abc", 2); /* Did the copy go right? */ | |
628 | ||
629 | (void) strcpy(one, "abcdefgh"); | |
630 | (void) memccpy(one+1, "xyz", 'q', 2); | |
631 | equal(one, "axydefgh", 3); /* Basic test. */ | |
632 | ||
633 | (void) strcpy(one, "abc"); | |
634 | (void) memccpy(one, "xyz", 'q', 0); | |
635 | equal(one, "abc", 4); /* Zero-length copy. */ | |
636 | ||
637 | (void) strcpy(one, "hi there"); | |
638 | (void) strcpy(two, "foo"); | |
639 | (void) memccpy(two, one, 'q', 9); | |
640 | equal(two, "hi there", 5); /* Just paranoia. */ | |
641 | equal(one, "hi there", 6); /* Stomped on source? */ | |
642 | ||
643 | (void) strcpy(one, "abcdefgh"); | |
644 | (void) strcpy(two, "horsefeathers"); | |
645 | check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */ | |
646 | equal(one, "abcdefgh", 8); /* Source intact? */ | |
647 | equal(two, "abcdefeathers", 9); /* Copy correct? */ | |
648 | ||
649 | (void) strcpy(one, "abcd"); | |
650 | (void) strcpy(two, "bumblebee"); | |
651 | check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */ | |
652 | equal(two, "aumblebee", 11); | |
653 | check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */ | |
654 | equal(two, "abcdlebee", 13); | |
655 | (void) strcpy(one, "xyz"); | |
656 | check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */ | |
657 | equal(two, "xbcdlebee", 15); | |
658 | ||
659 | /* memset. */ | |
660 | it = "memset"; | |
661 | (void) strcpy(one, "abcdefgh"); | |
662 | check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */ | |
663 | equal(one, "axxxefgh", 2); /* Basic test. */ | |
664 | ||
665 | (void) memset(one+2, 'y', 0); | |
666 | equal(one, "axxxefgh", 3); /* Zero-length set. */ | |
667 | ||
668 | (void) memset(one+5, 0, 1); | |
669 | equal(one, "axxxe", 4); /* Zero fill. */ | |
670 | equal(one+6, "gh", 5); /* And the leftover. */ | |
671 | ||
672 | (void) memset(one+2, 010045, 1); | |
673 | equal(one, "ax\045xe", 6); /* Unsigned char convert. */ | |
674 | ||
675 | /* bcopy - much like memcpy. | |
676 | Berklix manual is silent about overlap, so don't test it. */ | |
677 | it = "bcopy"; | |
678 | (void) bcopy("abc", one, 4); | |
679 | equal(one, "abc", 1); /* Simple copy. */ | |
680 | ||
681 | (void) strcpy(one, "abcdefgh"); | |
682 | (void) bcopy("xyz", one+1, 2); | |
683 | equal(one, "axydefgh", 2); /* Basic test. */ | |
684 | ||
685 | (void) strcpy(one, "abc"); | |
686 | (void) bcopy("xyz", one, 0); | |
687 | equal(one, "abc", 3); /* Zero-length copy. */ | |
688 | ||
689 | (void) strcpy(one, "hi there"); | |
690 | (void) strcpy(two, "foo"); | |
691 | (void) bcopy(one, two, 9); | |
692 | equal(two, "hi there", 4); /* Just paranoia. */ | |
693 | equal(one, "hi there", 5); /* Stomped on source? */ | |
694 | ||
695 | /* bzero. */ | |
696 | it = "bzero"; | |
697 | (void) strcpy(one, "abcdef"); | |
698 | bzero(one+2, 2); | |
699 | equal(one, "ab", 1); /* Basic test. */ | |
700 | equal(one+3, "", 2); | |
701 | equal(one+4, "ef", 3); | |
702 | ||
703 | (void) strcpy(one, "abcdef"); | |
704 | bzero(one+2, 0); | |
705 | equal(one, "abcdef", 4); /* Zero-length copy. */ | |
706 | ||
707 | #if 0 | |
708 | /* bcmp - somewhat like memcmp. */ | |
709 | it = "bcmp"; | |
710 | check(bcmp("a", "a", 1) == 0, 1); /* Identity. */ | |
711 | check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */ | |
712 | check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */ | |
713 | check(bcmp("abce", "abcd", 4) != 0, 4); | |
714 | check(bcmp("alph", "beta", 4) != 0, 5); | |
715 | check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */ | |
716 | check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */ | |
717 | #endif | |
718 | ||
719 | { | |
720 | char text[] = "This,is,a,test"; | |
721 | char *list = text; | |
722 | it = "strsep"; | |
723 | check (!strcmp ("This", strsep (&list, ",")), 1); | |
724 | check (!strcmp ("is", strsep (&list, ",")), 2); | |
725 | check (!strcmp ("a", strsep (&list, ",")), 3); | |
726 | check (!strcmp ("test", strsep (&list, ",")), 4); | |
727 | check (strsep (&list, ",") == NULL, 5); | |
728 | } | |
729 | ||
730 | /* strerror - VERY system-dependent. */ | |
731 | { | |
732 | int f; | |
733 | it = "strerror"; | |
734 | f = __open("/", O_WRONLY); /* Should always fail. */ | |
735 | check(f < 0 && errno > 0 && errno < _sys_nerr, 1); | |
736 | equal(strerror(errno), _sys_errlist[errno], 2); | |
737 | } | |
738 | ||
739 | { | |
740 | int status; | |
741 | if (errors == 0) | |
742 | { | |
743 | status = EXIT_SUCCESS; | |
744 | puts("No errors."); | |
745 | } | |
746 | else | |
747 | { | |
748 | status = EXIT_FAILURE; | |
3e2ee727 | 749 | printf("%Zd errors.\n", errors); |
28f540f4 RM |
750 | } |
751 | exit(status); | |
752 | } | |
753 | } |