1 #include "test.h"
2 #include <string.h>
3 #include <errno.h>
4
5
6 _CONST char *it = "<UNSET>"; /* Routine name for message routines. */
7 int errors = 0;
8
9 /* Complain if condition is not true. */
10 #define check(thing) checkit(thing, __LINE__)
11
12 void
13 _DEFUN(checkit,(ok,l),
14 int ok _AND
15 int l )
16
17 {
18 newfunc(it);
19 line(l);
20
21 if (!ok)
22 {
23 printf("string.c:%d %s\n", l, it);
24 ++errors;
25 }
26 }
27
28
29
30 /* Complain if first two args don't strcmp as equal. */
31 #define equal(a, b) funcqual(a,b,__LINE__);
32
33 void
34 _DEFUN(funcqual,(a,b,l),
35 char *a _AND
36 char *b _AND
37 int l)
38 {
39 newfunc(it);
40
41 line(l);
42 if (a == NULL && b == NULL) return;
43 if (strcmp(a,b)) {
44 printf("string.c:%d (%s)\n", l, it);
45 }
46 }
47
48
49
50 static char one[50];
51 static char two[50];
52
53
test_string()54 void test_string()
55 {
56 /* Test strcmp first because we use it to test other things. */
57 it = "strcmp";
58 check(strcmp("", "") == 0); /* Trivial case. */
59 check(strcmp("a", "a") == 0); /* Identity. */
60 check(strcmp("abc", "abc") == 0); /* Multicharacter. */
61 check(strcmp("abc", "abcd") < 0); /* Length mismatches. */
62 check(strcmp("abcd", "abc") > 0);
63 check(strcmp("abcd", "abce") < 0); /* Honest miscompares. */
64 check(strcmp("abce", "abcd") > 0);
65 check(strcmp("a\103", "a") > 0); /* Tricky if char signed. */
66 check(strcmp("a\103", "a\003") > 0);
67
68 /* Test strcpy next because we need it to set up other tests. */
69 it = "strcpy";
70 check(strcpy(one, "abcd") == one); /* Returned value. */
71 equal(one, "abcd"); /* Basic test. */
72
73 (void) strcpy(one, "x");
74 equal(one, "x"); /* Writeover. */
75 equal(one+2, "cd"); /* Wrote too much? */
76
77 (void) strcpy(two, "hi there");
78 (void) strcpy(one, two);
79 equal(one, "hi there"); /* Basic test encore. */
80 equal(two, "hi there"); /* Stomped on source? */
81
82 (void) strcpy(one, "");
83 equal(one, ""); /* Boundary condition. */
84
85 /* strcat. */
86 it = "strcat";
87 (void) strcpy(one, "ijk");
88 check(strcat(one, "lmn") == one); /* Returned value. */
89 equal(one, "ijklmn"); /* Basic test. */
90
91 (void) strcpy(one, "x");
92 (void) strcat(one, "yz");
93 equal(one, "xyz"); /* Writeover. */
94 equal(one+4, "mn"); /* Wrote too much? */
95
96 (void) strcpy(one, "gh");
97 (void) strcpy(two, "ef");
98 (void) strcat(one, two);
99 equal(one, "ghef"); /* Basic test encore. */
100 equal(two, "ef"); /* Stomped on source? */
101
102 (void) strcpy(one, "");
103 (void) strcat(one, "");
104 equal(one, ""); /* Boundary conditions. */
105 (void) strcpy(one, "ab");
106 (void) strcat(one, "");
107 equal(one, "ab");
108 (void) strcpy(one, "");
109 (void) strcat(one, "cd");
110 equal(one, "cd");
111
112 /* strncat - first test it as strcat, with big counts,
113 then test the count mechanism. */
114 it = "strncat";
115 (void) strcpy(one, "ijk");
116 check(strncat(one, "lmn", 99) == one); /* Returned value. */
117 equal(one, "ijklmn"); /* Basic test. */
118
119 (void) strcpy(one, "x");
120 (void) strncat(one, "yz", 99);
121 equal(one, "xyz"); /* Writeover. */
122 equal(one+4, "mn"); /* Wrote too much? */
123
124 (void) strcpy(one, "gh");
125 (void) strcpy(two, "ef");
126 (void) strncat(one, two, 99);
127 equal(one, "ghef"); /* Basic test encore. */
128 equal(two, "ef"); /* Stomped on source? */
129
130 (void) strcpy(one, "");
131 (void) strncat(one, "", 99);
132 equal(one, ""); /* Boundary conditions. */
133 (void) strcpy(one, "ab");
134 (void) strncat(one, "", 99);
135 equal(one, "ab");
136 (void) strcpy(one, "");
137 (void) strncat(one, "cd", 99);
138 equal(one, "cd");
139
140 (void) strcpy(one, "ab");
141 (void) strncat(one, "cdef", 2);
142 equal(one, "abcd"); /* Count-limited. */
143
144 (void) strncat(one, "gh", 0);
145 equal(one, "abcd"); /* Zero count. */
146
147 (void) strncat(one, "gh", 2);
148 equal(one, "abcdgh"); /* Count _AND length equal. */
149 it = "strncmp";
150 /* strncmp - first test as strcmp with big counts";*/
151 check(strncmp("", "", 99) == 0); /* Trivial case. */
152 check(strncmp("a", "a", 99) == 0); /* Identity. */
153 check(strncmp("abc", "abc", 99) == 0); /* Multicharacter. */
154 check(strncmp("abc", "abcd", 99) < 0); /* Length unequal. */
155 check(strncmp("abcd", "abc",99) > 0);
156 check(strncmp("abcd", "abce", 99) < 0); /* Honestly unequal. */
157 check(strncmp("abce", "abcd",99)>0);
158 check(strncmp("abce", "abcd", 3) == 0); /* Count limited. */
159 check(strncmp("abce", "abc", 3) == 0); /* Count == length. */
160 check(strncmp("abcd", "abce", 4) < 0); /* Nudging limit. */
161 check(strncmp("abc", "def", 0) == 0); /* Zero count. */
162
163 /* strncpy - testing is a bit different because of odd semantics. */
164 it = "strncpy";
165 check(strncpy(one, "abc", 4) == one); /* Returned value. */
166 equal(one, "abc"); /* Did the copy go right? */
167
168 (void) strcpy(one, "abcdefgh");
169 (void) strncpy(one, "xyz", 2);
170 equal(one, "xycdefgh"); /* Copy cut by count. */
171
172 (void) strcpy(one, "abcdefgh");
173 (void) strncpy(one, "xyz", 3); /* Copy cut just before NUL. */
174 equal(one, "xyzdefgh");
175
176 (void) strcpy(one, "abcdefgh");
177 (void) strncpy(one, "xyz", 4); /* Copy just includes NUL. */
178 equal(one, "xyz");
179 equal(one+4, "efgh"); /* Wrote too much? */
180
181 (void) strcpy(one, "abcdefgh");
182 (void) strncpy(one, "xyz", 5); /* Copy includes padding. */
183 equal(one, "xyz");
184 equal(one+4, "");
185 equal(one+5, "fgh");
186
187 (void) strcpy(one, "abc");
188 (void) strncpy(one, "xyz", 0); /* Zero-length copy. */
189 equal(one, "abc");
190
191 (void) strncpy(one, "", 2); /* Zero-length source. */
192 equal(one, "");
193 equal(one+1, "");
194 equal(one+2, "c");
195
196 (void) strcpy(one, "hi there");
197 (void) strncpy(two, one, 9);
198 equal(two, "hi there"); /* Just paranoia. */
199 equal(one, "hi there"); /* Stomped on source? */
200
201 /* strlen. */
202 it = "strlen";
203 check(strlen("") == 0); /* Empty. */
204 check(strlen("a") == 1); /* Single char. */
205 check(strlen("abcd") == 4); /* Multiple chars. */
206
207 /* strchr. */
208 it = "strchr";
209 check(strchr("abcd", 'z') == NULL); /* Not found. */
210 (void) strcpy(one, "abcd");
211 check(strchr(one, 'c') == one+2); /* Basic test. */
212 check(strchr(one, 'd') == one+3); /* End of string. */
213 check(strchr(one, 'a') == one); /* Beginning. */
214 check(strchr(one, '\0') == one+4); /* Finding NUL. */
215 (void) strcpy(one, "ababa");
216 check(strchr(one, 'b') == one+1); /* Finding first. */
217 (void) strcpy(one, "");
218 check(strchr(one, 'b') == NULL); /* Empty string. */
219 check(strchr(one, '\0') == one); /* NUL in empty string. */
220
221 /* index - just like strchr. */
222 it = "index";
223 check(index("abcd", 'z') == NULL); /* Not found. */
224 (void) strcpy(one, "abcd");
225 check(index(one, 'c') == one+2); /* Basic test. */
226 check(index(one, 'd') == one+3); /* End of string. */
227 check(index(one, 'a') == one); /* Beginning. */
228 check(index(one, '\0') == one+4); /* Finding NUL. */
229 (void) strcpy(one, "ababa");
230 check(index(one, 'b') == one+1); /* Finding first. */
231 (void) strcpy(one, "");
232 check(index(one, 'b') == NULL); /* Empty string. */
233 check(index(one, '\0') == one); /* NUL in empty string. */
234
235 /* strrchr. */
236 it = "strrchr";
237 check(strrchr("abcd", 'z') == NULL); /* Not found. */
238 (void) strcpy(one, "abcd");
239 check(strrchr(one, 'c') == one+2); /* Basic test. */
240 check(strrchr(one, 'd') == one+3); /* End of string. */
241 check(strrchr(one, 'a') == one); /* Beginning. */
242 check(strrchr(one, '\0') == one+4); /* Finding NUL. */
243 (void) strcpy(one, "ababa");
244 check(strrchr(one, 'b') == one+3); /* Finding last. */
245 (void) strcpy(one, "");
246 check(strrchr(one, 'b') == NULL); /* Empty string. */
247 check(strrchr(one, '\0') == one); /* NUL in empty string. */
248
249 /* rindex - just like strrchr. */
250 it = "rindex";
251 check(rindex("abcd", 'z') == NULL); /* Not found. */
252 (void) strcpy(one, "abcd");
253 check(rindex(one, 'c') == one+2); /* Basic test. */
254 check(rindex(one, 'd') == one+3); /* End of string. */
255 check(rindex(one, 'a') == one); /* Beginning. */
256 check(rindex(one, '\0') == one+4); /* Finding NUL. */
257 (void) strcpy(one, "ababa");
258 check(rindex(one, 'b') == one+3); /* Finding last. */
259 (void) strcpy(one, "");
260 check(rindex(one, 'b') == NULL); /* Empty string. */
261 check(rindex(one, '\0') == one); /* NUL in empty string. */
262
263 /* strpbrk - somewhat like strchr. */
264 it = "strpbrk";
265 check(strpbrk("abcd", "z") == NULL); /* Not found. */
266 (void) strcpy(one, "abcd");
267 check(strpbrk(one, "c") == one+2); /* Basic test. */
268 check(strpbrk(one, "d") == one+3); /* End of string. */
269 check(strpbrk(one, "a") == one); /* Beginning. */
270 check(strpbrk(one, "") == NULL); /* Empty search list. */
271 check(strpbrk(one, "cb") == one+1); /* Multiple search. */
272 (void) strcpy(one, "abcabdea");
273 check(strpbrk(one, "b") == one+1); /* Finding first. */
274 check(strpbrk(one, "cb") == one+1); /* With multiple search. */
275 check(strpbrk(one, "db") == one+1); /* Another variant. */
276 (void) strcpy(one, "");
277 check(strpbrk(one, "bc") == NULL); /* Empty string. */
278 check(strpbrk(one, "") == NULL); /* Both strings empty. */
279
280 /* strstr - somewhat like strchr. */
281 it = "strstr";
282 check(strstr("z", "abcd") == NULL); /* Not found. */
283 check(strstr("abx", "abcd") == NULL); /* Dead end. */
284 (void) strcpy(one, "abcd");
285 check(strstr(one,"c") == one+2); /* Basic test. */
286 check(strstr(one, "bc") == one+1); /* Multichar. */
287 check(strstr(one,"d") == one+3); /* End of string. */
288 check(strstr(one,"cd") == one+2); /* Tail of string. */
289 check(strstr(one,"abc") == one); /* Beginning. */
290 check(strstr(one,"abcd") == one); /* Exact match. */
291 check(strstr(one,"de") == NULL); /* Past end. */
292 check(strstr(one,"") == one); /* Finding empty. */
293 (void) strcpy(one, "ababa");
294 check(strstr(one,"ba") == one+1); /* Finding first. */
295 (void) strcpy(one, "");
296 check(strstr(one, "b") == NULL); /* Empty string. */
297 check(strstr(one,"") == one); /* Empty in empty string. */
298 (void) strcpy(one, "bcbca");
299 check(strstr(one,"bca") == one+2); /* False start. */
300 (void) strcpy(one, "bbbcabbca");
301 check(strstr(one,"bbca") == one+1); /* With overlap. */
302
303 /* strspn. */
304 it = "strspn";
305 check(strspn("abcba", "abc") == 5); /* Whole string. */
306 check(strspn("abcba", "ab") == 2); /* Partial. */
307 check(strspn("abc", "qx") == 0); /* None. */
308 check(strspn("", "ab") == 0); /* Null string. */
309 check(strspn("abc", "") == 0); /* Null search list. */
310
311 /* strcspn. */
312 it = "strcspn";
313 check(strcspn("abcba", "qx") == 5); /* Whole string. */
314 check(strcspn("abcba", "cx") == 2); /* Partial. */
315 check(strcspn("abc", "abc") == 0); /* None. */
316 check(strcspn("", "ab") == 0); /* Null string. */
317 check(strcspn("abc", "") == 3); /* Null search list. */
318
319 /* strtok - the hard one. */
320 it = "strtok";
321 (void) strcpy(one, "first, second, third");
322 equal(strtok(one, ", "), "first"); /* Basic test. */
323 equal(one, "first");
324 equal(strtok((char *)NULL, ", "), "second");
325 equal(strtok((char *)NULL, ", "), "third");
326 check(strtok((char *)NULL, ", ") == NULL);
327 (void) strcpy(one, ", first, ");
328 equal(strtok(one, ", "), "first"); /* Extra delims, 1 tok. */
329 check(strtok((char *)NULL, ", ") == NULL);
330 (void) strcpy(one, "1a, 1b; 2a, 2b");
331 equal(strtok(one, ", "), "1a"); /* Changing delim lists. */
332 equal(strtok((char *)NULL, "; "), "1b");
333 equal(strtok((char *)NULL, ", "), "2a");
334 (void) strcpy(two, "x-y");
335 equal(strtok(two, "-"), "x"); /* New string before done. */
336 equal(strtok((char *)NULL, "-"), "y");
337 check(strtok((char *)NULL, "-") == NULL);
338 (void) strcpy(one, "a,b, c,, ,d");
339 equal(strtok(one, ", "), "a"); /* Different separators. */
340 equal(strtok((char *)NULL, ", "), "b");
341 equal(strtok((char *)NULL, " ,"), "c"); /* Permute list too. */
342 equal(strtok((char *)NULL, " ,"), "d");
343 check(strtok((char *)NULL, ", ") == NULL);
344 check(strtok((char *)NULL, ", ") == NULL); /* Persistence. */
345 (void) strcpy(one, ", ");
346 check(strtok(one, ", ") == NULL); /* No tokens. */
347 (void) strcpy(one, "");
348 check(strtok(one, ", ") == NULL); /* Empty string. */
349 (void) strcpy(one, "abc");
350 equal(strtok(one, ", "), "abc"); /* No delimiters. */
351 check(strtok((char *)NULL, ", ") == NULL);
352 (void) strcpy(one, "abc");
353 equal(strtok(one, ""), "abc"); /* Empty delimiter list. */
354 check(strtok((char *)NULL, "") == NULL);
355 (void) strcpy(one, "abcdefgh");
356 (void) strcpy(one, "a,b,c");
357 equal(strtok(one, ","), "a"); /* Basics again... */
358 equal(strtok((char *)NULL, ","), "b");
359 equal(strtok((char *)NULL, ","), "c");
360 check(strtok((char *)NULL, ",") == NULL);
361 equal(one+6, "gh"); /* Stomped past end? */
362 equal(one, "a"); /* Stomped old tokens? */
363 equal(one+2, "b");
364 equal(one+4, "c");
365
366 /* memcmp. */
367 it = "memcmp";
368 check(memcmp("a", "a", 1) == 0); /* Identity. */
369 check(memcmp("abc", "abc", 3) == 0); /* Multicharacter. */
370 check(memcmp("abcd", "abce", 4) < 0); /* Honestly unequal. */
371 check(memcmp("abce", "abcd",4));
372 check(memcmp("alph", "beta", 4) < 0);
373 check(memcmp("abce", "abcd", 3) == 0); /* Count limited. */
374 check(memcmp("abc", "def", 0) == 0); /* Zero count. */
375
376 /* memcmp should test strings as unsigned */
377 one[0] = 0xfe;
378 two[0] = 0x03;
379 check(memcmp(one, two,1) > 0);
380
381
382 /* memchr. */
383 it = "memchr";
384 check(memchr("abcd", 'z', 4) == NULL); /* Not found. */
385 (void) strcpy(one, "abcd");
386 check(memchr(one, 'c', 4) == one+2); /* Basic test. */
387 check(memchr(one, 'd', 4) == one+3); /* End of string. */
388 check(memchr(one, 'a', 4) == one); /* Beginning. */
389 check(memchr(one, '\0', 5) == one+4); /* Finding NUL. */
390 (void) strcpy(one, "ababa");
391 check(memchr(one, 'b', 5) == one+1); /* Finding first. */
392 check(memchr(one, 'b', 0) == NULL); /* Zero count. */
393 check(memchr(one, 'a', 1) == one); /* Singleton case. */
394 (void) strcpy(one, "a\203b");
395 check(memchr(one, 0203, 3) == one+1); /* Unsignedness. */
396
397 /* memcpy - need not work for overlap. */
398 it = "memcpy";
399 check(memcpy(one, "abc", 4) == one); /* Returned value. */
400 equal(one, "abc"); /* Did the copy go right? */
401
402 (void) strcpy(one, "abcdefgh");
403 (void) memcpy(one+1, "xyz", 2);
404 equal(one, "axydefgh"); /* Basic test. */
405
406 (void) strcpy(one, "abc");
407 (void) memcpy(one, "xyz", 0);
408 equal(one, "abc"); /* Zero-length copy. */
409
410 (void) strcpy(one, "hi there");
411 (void) strcpy(two, "foo");
412 (void) memcpy(two, one, 9);
413 equal(two, "hi there"); /* Just paranoia. */
414 equal(one, "hi there"); /* Stomped on source? */
415 #if 0
416 /* memmove - must work on overlap. */
417 it = "memmove";
418 check(memmove(one, "abc", 4) == one); /* Returned value. */
419 equal(one, "abc"); /* Did the copy go right? */
420
421 (void) strcpy(one, "abcdefgh");
422 (void) memmove(one+1, "xyz", 2);
423 equal(one, "axydefgh"); /* Basic test. */
424
425 (void) strcpy(one, "abc");
426 (void) memmove(one, "xyz", 0);
427 equal(one, "abc"); /* Zero-length copy. */
428
429 (void) strcpy(one, "hi there");
430 (void) strcpy(two, "foo");
431 (void) memmove(two, one, 9);
432 equal(two, "hi there"); /* Just paranoia. */
433 equal(one, "hi there"); /* Stomped on source? */
434
435 (void) strcpy(one, "abcdefgh");
436 (void) memmove(one+1, one, 9);
437 equal(one, "aabcdefgh"); /* Overlap, right-to-left. */
438
439 (void) strcpy(one, "abcdefgh");
440 (void) memmove(one+1, one+2, 7);
441 equal(one, "acdefgh"); /* Overlap, left-to-right. */
442
443 (void) strcpy(one, "abcdefgh");
444 (void) memmove(one, one, 9);
445 equal(one, "abcdefgh"); /* 100% overlap. */
446 #endif
447 #if 0
448 /* memccpy - first test like memcpy, then the search part
449 The SVID, the only place where memccpy is mentioned, says
450 overlap might fail, so we don't try it. Besides, it's hard
451 to see the rationale for a non-left-to-right memccpy. */
452 it = "memccpy";
453 check(memccpy(one, "abc", 'q', 4) == NULL); /* Returned value. */
454 equal(one, "abc"); /* Did the copy go right? */
455
456 (void) strcpy(one, "abcdefgh");
457 (void) memccpy(one+1, "xyz", 'q', 2);
458 equal(one, "axydefgh"); /* Basic test. */
459
460 (void) strcpy(one, "abc");
461 (void) memccpy(one, "xyz", 'q', 0);
462 equal(one, "abc"); /* Zero-length copy. */
463
464 (void) strcpy(one, "hi there");
465 (void) strcpy(two, "foo");
466 (void) memccpy(two, one, 'q', 9);
467 equal(two, "hi there"); /* Just paranoia. */
468 equal(one, "hi there"); /* Stomped on source? */
469
470 (void) strcpy(one, "abcdefgh");
471 (void) strcpy(two, "horsefeathers");
472 check(memccpy(two, one, 'f', 9) == two+6); /* Returned value. */
473 equal(one, "abcdefgh"); /* Source intact? */
474 equal(two, "abcdefeathers"); /* Copy correct? */
475
476 (void) strcpy(one, "abcd");
477 (void) strcpy(two, "bumblebee");
478 check(memccpy(two, one, 'a', 4) == two+1); /* First char. */
479 equal(two, "aumblebee");
480 check(memccpy(two, one, 'd', 4) == two+4); /* Last char. */
481 equal(two, "abcdlebee");
482 (void) strcpy(one, "xyz");
483 check(memccpy(two, one, 'x', 1) == two+1); /* Singleton. */
484 equal(two, "xbcdlebee");
485 #endif
486 /* memset. */
487 it = "memset";
488 (void) strcpy(one, "abcdefgh");
489 check(memset(one+1, 'x', 3) == one+1); /* Return value. */
490 equal(one, "axxxefgh"); /* Basic test. */
491
492 (void) memset(one+2, 'y', 0);
493 equal(one, "axxxefgh"); /* Zero-length set. */
494
495 (void) memset(one+5, 0, 1);
496 equal(one, "axxxe"); /* Zero fill. */
497 equal(one+6, "gh"); /* _AND the leftover. */
498
499 (void) memset(one+2, 010045, 1);
500 equal(one, "ax\045xe"); /* Unsigned char convert. */
501
502 /* bcopy - much like memcpy.
503 Berklix manual is silent about overlap, so don't test it. */
504 it = "bcopy";
505 (void) bcopy("abc", one, 4);
506 equal(one, "abc"); /* Simple copy. */
507
508 (void) strcpy(one, "abcdefgh");
509 (void) bcopy("xyz", one+1, 2);
510 equal(one, "axydefgh"); /* Basic test. */
511
512 (void) strcpy(one, "abc");
513 (void) bcopy("xyz", one, 0);
514 equal(one, "abc"); /* Zero-length copy. */
515
516 (void) strcpy(one, "hi there");
517 (void) strcpy(two, "foo");
518 (void) bcopy(one, two, 9);
519 equal(two, "hi there"); /* Just paranoia. */
520 equal(one, "hi there"); /* Stomped on source? */
521
522 /* bzero. */
523 it = "bzero";
524 (void) strcpy(one, "abcdef");
525 bzero(one+2, 2);
526 equal(one, "ab"); /* Basic test. */
527 equal(one+3, "");
528 equal(one+4, "ef");
529
530 (void) strcpy(one, "abcdef");
531 bzero(one+2, 0);
532 equal(one, "abcdef"); /* Zero-length copy. */
533
534 /* bcmp - somewhat like memcmp. */
535 it = "bcmp";
536 check(bcmp("a", "a", 1) == 0); /* Identity. */
537 check(bcmp("abc", "abc", 3) == 0); /* Multicharacter. */
538 check(bcmp("abcd", "abce", 4) != 0); /* Honestly unequal. */
539 check(bcmp("abce", "abcd",4));
540 check(bcmp("alph", "beta", 4) != 0);
541 check(bcmp("abce", "abcd", 3) == 0); /* Count limited. */
542 check(bcmp("abc", "def", 0) == 0); /* Zero count. */
543
544 #if 0 /* strerror - VERY system-dependent. */
545 {
546 extern CONST unsigned int _sys_nerr;
547 extern CONST char *CONST _sys_errlist[];
548 int f;
549 it = "strerror";
550 f = open("/", O_WRONLY); /* Should always fail. */
551 check(f < 0 && errno > 0 && errno < _sys_nerr);
552 equal(strerror(errno), _sys_errlist[errno]);
553 }
554 #endif
555 }
556
557