1 /*
2  * str_test.c
3  *
4  * test str functions
5  */
6 
7 /* Need to add tests for...
8 
9 const char *str_addutf8    ( str *s, const char *p );
10 void str_fprintf     ( FILE *fp, str *s );
11 int  str_fget        ( FILE *fp, char *buf, int bufsize, int *pbufpos,
12                           str *outs );
13 int  str_fgetline    ( str *s, FILE *fp );
14 */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "str.h"
20 
21 char progname[] = "str_test";
22 char version[] = "0.3";
23 
24 int
_inconsistent_len(str * s,unsigned long numchars,const char * fn,unsigned long line)25 _inconsistent_len( str *s, unsigned long numchars, const char *fn, unsigned long line )
26 {
27 	if ( s->len > s->dim ) {
28 		fprintf(stdout,"%s line %lu: failed consistency check found s->len=%lu, s->max=%lu\n",fn,line,
29 			s->len, s->dim );
30 	}
31 	if ( s->data ) {
32 		if ( s->len != strlen( s->data ) ) {
33 			fprintf(stdout,"%s line %lu: failed consistency check found strlen=%d, s->len=%ld\n",fn,line,(int)strlen(s->data),s->len);
34 			return 1;
35 		}
36 	} else {
37 		if ( s->len != 0 ) {
38 			fprintf(stdout,"%s line %lu: failed consistency check found for unallocated string, s->len=%ld\n",fn,line,s->len);
39 			return 1;
40 		}
41 	}
42 	if ( s->len != numchars ) {
43 		fprintf(stdout,"%s line %lu: failed consistency check found %d, expected %lu\n",fn,line,(int)strlen(s->data),numchars);
44 		return 1;
45 	}
46 	return 0;
47 }
48 
49 #define inconsistent_len( a, b ) _inconsistent_len( (a), (b), __FUNCTION__, __LINE__ )
50 
51 int
_test_identity(str * s,const char * expected,const char * fn,unsigned long line)52 _test_identity( str *s, const char *expected, const char *fn, unsigned long line )
53 {
54 	/* Unallocated strings are considered identical to empty strings */
55 	if ( expected[0]=='\0' ) {
56 		if ( s->data==NULL || s->data[0]=='\0' ) return 0;
57 		fprintf(stdout,"%s line %lu: failed identity check found '%s', expected ''\n",fn,line,s->data);
58 		return 1;
59 	}
60 	/* expected!="", so s->data must exist */
61 	if ( !s->data ) {
62 		fprintf(stdout,"%s line %lu: failed identity check, s->data unallocated, expected '%s'\n",fn,line,expected);
63 		return 1;
64 	}
65 	if ( strcmp( s->data, expected ) == 0 ) return 0;
66 	fprintf(stdout,"%s line %lu: failed identity check, found '%s', expected '%s'\n",fn,line,s->data,expected);
67 	return 1;
68 }
69 
70 #define test_identity( a, b ) _test_identity( (a), (b), __FUNCTION__, __LINE__ )
71 
72 #define string_mismatch( a, b, c ) ( test_identity( (a), (c) ) || inconsistent_len( (a), (b) ) )
73 
74 static int
test_empty(str * s)75 test_empty( str *s )
76 {
77 	int failed = 0;
78 	int numchars = 1000, i, j;
79 
80 	str_empty( s );
81 	if ( string_mismatch( s, 0, "" ) ) failed++;
82 
83 	for ( i=0; i<numchars; ++i ) {
84 		for ( j=0; j<i; ++j )
85 			str_addchar( s, 'x' );
86 		str_empty( s );
87 		if ( string_mismatch( s, 0, "" ) ) failed++;
88 	}
89 
90 	return failed;
91 }
92 
93 static int
test_addchar(str * s)94 test_addchar( str *s )
95 {
96 	int failed = 0;
97 	int numshort = 5, numchars = 1000, i;
98 
99 	/* ...appending '\0' characters won't increase length */
100 	str_empty( s );
101 	for ( i=0; i<numshort; ++i )
102 		str_addchar( s, '\0' );
103 	if ( string_mismatch( s, 0, "" ) ) failed++;
104 
105 	/* ...build "11111" with str_addchar */
106 	str_empty( s );
107 	for ( i=0; i<numshort; ++i )
108 		str_addchar( s, '1' );
109 	if ( string_mismatch( s, 5, "11111" ) ) failed++;
110 
111 	/* ...build a bunch of random characters */
112 	str_empty( s );
113 	for ( i=0; i<numchars; ++i ) {
114 		str_addchar( s, ( i % 64 ) + 64);
115 	}
116 	if ( inconsistent_len( s, numchars ) ) failed++;
117 
118 	return failed;
119 }
120 
121 static int
test_strcatc(str * s)122 test_strcatc( str *s )
123 {
124 	int failed = 0;
125 	int numshort = 5, numstrings = 1000, i;
126 
127 	/* ...adding empty strings to an empty string shouldn't change length */
128 	str_empty( s );
129 	for ( i=0; i<numstrings; ++i )
130 		str_strcatc( s, "" );
131 	if ( string_mismatch( s, 0, "" ) ) failed++;
132 
133 	/* ...adding empty strings to a defined string shouldn't change string */
134 	str_strcpyc( s, "1" );
135 	for ( i=0; i<numstrings; ++i )
136 		str_strcatc( s, "" );
137 	if ( string_mismatch( s, 1, "1" ) ) failed++;
138 
139 	/* ...build "1111" with str_strcatc */
140 	str_empty( s );
141 	for ( i=0; i<numshort; ++i )
142 		str_strcatc( s, "1" );
143 	if ( string_mismatch( s, numshort, "11111" ) ) failed++;
144 
145 	/* ...build "xoxoxoxoxo" with str_strcatc */
146 	str_empty( s );
147 	for ( i=0; i<numshort; ++i )
148 		str_strcatc( s, "xo" );
149 	if ( string_mismatch( s, numshort*2, "xoxoxoxoxo" ) ) failed++;
150 
151 	str_empty( s );
152 	for ( i=0; i<numstrings; ++i )
153 		str_strcatc( s, "1" );
154 	if ( inconsistent_len( s, numstrings ) ) failed++;
155 
156 	str_empty( s );
157 	for ( i=0; i<numstrings; ++i )
158 		str_strcatc( s, "XXOO" );
159 	if ( inconsistent_len( s, numstrings*4 ) ) failed++;
160 
161 	return failed;
162 }
163 
164 static int
test_strcat(str * s)165 test_strcat( str *s )
166 {
167 	int numshort = 5, numstrings = 1000, i;
168 	int failed = 0;
169 	str t;
170 
171 	str_init( &t );
172 
173 	/* ...adding empty strings to an empty string shouldn't change length */
174 	str_empty( s );
175 	for ( i=0; i<numstrings; ++i )
176 		str_strcat( s, &t );
177 	if ( string_mismatch( s, 0, "" ) ) failed++;
178 
179 	/* ...adding empty strings to a defined string shouldn't change string */
180 	str_strcpyc( s, "1" );
181 	for ( i=0; i<numstrings; ++i )
182 		str_strcat( s, &t );
183 	if ( string_mismatch( s, 1, "1" ) ) failed++;
184 
185 	/* ...build "1111" with str_strcat */
186 	str_empty( s );
187 	str_strcpyc( &t, "1" );
188 	for ( i=0; i<numshort; ++i )
189 		str_strcat( s, &t );
190 	if ( string_mismatch( s, numshort, "11111" ) ) failed++;
191 
192 	/* ...build "xoxoxoxoxo" with str_strcat */
193 	str_empty( s );
194 	str_strcpyc( &t, "xo" );
195 	for ( i=0; i<numshort; ++i )
196 		str_strcat( s, &t );
197 	if ( string_mismatch( s, numshort*2, "xoxoxoxoxo" ) ) failed++;
198 
199 	str_empty( s );
200 	str_strcpyc( &t, "1" );
201 	for ( i=0; i<numstrings; ++i )
202 		str_strcat( s, &t );
203 	if ( inconsistent_len( s, numstrings ) ) failed++;
204 
205 	str_empty( s );
206 	str_strcpyc( &t, "XXOO" );
207 	for ( i=0; i<numstrings; ++i )
208 		str_strcat( s, &t );
209 	if ( inconsistent_len( s, numstrings*4 ) ) failed++;
210 
211 	str_free( &t );
212 
213 	return failed;
214 }
215 
216 static int
test_strcpyc(str * s)217 test_strcpyc( str *s )
218 {
219 	int failed = 0;
220 	int numstrings = 1000, i;
221 
222 	/* Copying null string should reset string */
223 	str_empty( s );
224 	for ( i=0; i<numstrings; ++i ) {
225 		str_strcpyc( s, "1" );
226 		str_strcpyc( s, "" );
227 		if ( string_mismatch( s, 0, "" ) ) failed++;
228 	}
229 
230 	/* Many rounds of copying just "1" should give "1" */
231 	str_empty( s );
232 	for ( i=0; i<numstrings; ++i ) {
233 		str_strcpyc( s, "1" );
234 		if ( string_mismatch( s, 1, "1" ) ) failed++;
235 	}
236 
237 	/* Many rounds of copying just "XXOO" should give "XXOO" */
238 	str_empty( s );
239 	for ( i=0; i<numstrings; ++i ) {
240 		str_strcpyc( s, "XXOO" );
241 		if ( string_mismatch( s, 4, "XXOO" ) ) failed++;
242 	}
243 
244 	return failed;
245 }
246 
247 static int
test_strcpy(str * s)248 test_strcpy( str *s )
249 {
250 	int failed = 0;
251 	int numstrings = 1000, i;
252 	str t;
253 
254 	str_init( &t );
255 
256 	/* Copying null string should reset string */
257 	str_empty( s );
258 	for ( i=0; i<numstrings; ++i ) {
259 		str_strcpyc( s, "1" );
260 		str_strcpy( s, &t );
261 		if ( string_mismatch( s, 0, "" ) ) failed++;
262 	}
263 
264 	/* Many rounds of copying just "1" should give "1" */
265 	str_empty( s );
266 	str_strcpyc( &t, "1" );
267 	for ( i=0; i<numstrings; ++i ) {
268 		str_strcpy( s, &t );
269 		if ( string_mismatch( s, t.len, t.data ) ) failed++;
270 	}
271 
272 	/* Many rounds of copying just "XXOO" should give "XXOO" */
273 	str_empty( s );
274 	str_strcpyc( &t, "XXOO" );
275 	for ( i=0; i<numstrings; ++i ) {
276 		str_strcpy( s, &t );
277 		if ( string_mismatch( s, t.len, t.data ) ) failed++;
278 	}
279 
280 	str_free( &t );
281 
282 	return failed;
283 }
284 
285 static int
test_segcpy(str * s)286 test_segcpy( str *s )
287 {
288 	char segment[]="0123456789";
289 	char *start=&(segment[2]), *end=&(segment[5]);
290 	int numstrings = 1000, i;
291 	str t, u;
292 	int failed = 0;
293 
294 	str_init( &t );
295 	str_init( &u );
296 
297 	str_empty( s );
298 	str_segcpy( s, start, start );
299 	if ( string_mismatch( s, 0, "" ) ) failed++;
300 
301 	str_segcpy( &t, start, start );
302 	if ( string_mismatch( &t, 0, "" ) ) failed++;
303 
304 	str_segcpy( &u, start, end );
305 	if ( string_mismatch( &u, 3, "234" ) ) failed++;
306 
307 	str_empty( s );
308 	for ( i=0; i<numstrings; ++i ) {
309 		str_segcpy( s, start, end );
310 		if ( string_mismatch( s, 3, "234" ) ) failed++;
311 	}
312 
313 	str_free( &t );
314 	str_free( &u );
315 
316 	return failed;
317 }
318 
319 static int
test_indxcpy(str * s)320 test_indxcpy( str *s )
321 {
322 	char segment[]="0123456789";
323 	int numstrings = 10, i;
324 	str t, u;
325 	int failed = 0;
326 
327 	str_init( &t );
328 	str_init( &u );
329 
330 	str_empty( s );
331 	str_indxcpy( s, segment, 2, 2 );
332 	if ( string_mismatch( s, 0, "" ) ) failed++;
333 
334 	str_indxcpy( &t, segment, 2, 2 );
335 	if ( string_mismatch( &t, 0, "" ) ) failed++;
336 
337 	str_indxcpy( &u, segment, 2, 5 );
338 	if ( string_mismatch( &u, 3, "234" ) ) failed++;
339 
340 	str_empty( s );
341 	for ( i=0; i<numstrings; ++i ) {
342 		str_indxcpy( s, segment, 2, 5 );
343 		if ( string_mismatch( s, 3, "234" ) ) failed++;
344 	}
345 
346 	str_free( &t );
347 	str_free( &u );
348 
349 	return failed;
350 }
351 
352 /* void str_copyposlen  ( str *s, str *in, unsigned long pos, unsigned long len ); */
353 static int
test_copyposlen(str * s)354 test_copyposlen( str *s )
355 {
356 	str t;
357 	int failed = 0;
358 
359 	str_init( &t );
360 
361 	str_copyposlen( s, &t, 1, 5 );
362 	if ( string_mismatch( s, 0, "" ) ) failed++;
363 
364 	str_strcpyc( &t, "0123456789" );
365 
366 	str_copyposlen( s, &t, 1, 5 );
367 	if ( string_mismatch( s, 5, "12345" ) ) failed++;
368 
369 	str_free( &t );
370 
371 	return failed;
372 }
373 
374 static int
test_indxcat(str * s)375 test_indxcat( str *s )
376 {
377 	char segment[]="0123456789";
378 	int numstrings = 3, i;
379 	str t, u;
380 	int failed = 0;
381 
382 	str_init( &t );
383 	str_init( &u );
384 
385 	str_empty( s );
386 	str_indxcat( s, segment, 2, 2 );
387 	if ( string_mismatch( s, 0, "" ) ) failed++;
388 
389 	str_indxcat( &t, segment, 2, 2 );
390 	if ( string_mismatch( &t, 0, "" ) ) failed++;
391 
392 	str_indxcat( &u, segment, 2, 5 );
393 	if ( string_mismatch( &u, 3, "234" ) ) failed++;
394 
395 	str_empty( s );
396 	for ( i=0; i<numstrings; ++i )
397 		str_indxcat( s, segment, 2, 5 );
398 	if ( string_mismatch( s, 9, "234234234" ) ) failed++;
399 
400 	str_free( &t );
401 	str_free( &u );
402 
403 	return failed;
404 }
405 
406 static int
test_segcat(str * s)407 test_segcat( str *s )
408 {
409 	char segment[]="0123456789";
410 	char *start=&(segment[2]), *end=&(segment[5]);
411 	int numstrings = 1000, i;
412 	int failed = 0;
413 	str t, u;
414 
415 	str_init( &t );
416 	str_init( &u );
417 
418 	str_empty( s );
419 	str_segcpy( s, start, start );
420 	if ( string_mismatch( s, 0, "" ) ) failed++;
421 
422 	str_segcpy( &t, start, start );
423 	if ( string_mismatch( &t, 0, "" ) ) failed++;
424 
425 	str_segcpy( &u, start, end );
426 	if ( string_mismatch( &u, 3, "234" ) ) failed++;
427 
428 	str_empty( s );
429 	for ( i=0; i<numstrings; ++i )
430 		str_segcat( s, start, end );
431 	if ( inconsistent_len( s, 3*numstrings ) ) failed++;
432 
433 	str_free( &t );
434 	str_free( &u );
435 
436 	return failed;
437 }
438 
439 static int
test_prepend(str * s)440 test_prepend( str *s )
441 {
442 	int failed = 0;
443 
444 	str_empty( s );
445 	str_prepend( s, "" );
446 	if ( string_mismatch( s, 0, "" ) ) failed++;
447 	str_prepend( s, "asdf" );
448 	if ( string_mismatch( s, 4, "asdf" ) ) failed++;
449 
450 	str_strcpyc( s, "567890" );
451 	str_prepend( s, "01234" );
452 	if ( string_mismatch( s, 11, "01234567890" ) ) failed++;
453 
454 	return failed;
455 }
456 
457 static int
test_pad(str * s)458 test_pad( str *s )
459 {
460 	int failed = 0;
461 
462 	str_empty( s );
463 	str_pad( s, 10, '-' );
464 	if ( string_mismatch( s, 10, "----------" ) ) failed++;
465 
466 	str_strcpyc( s, "012" );
467 	str_pad( s, 10, '-' );
468 	if ( string_mismatch( s, 10, "012-------" ) ) failed++;
469 
470 	str_strcpyc( s, "0123456789" );
471 	str_pad( s, 10, '-' );
472 	if ( string_mismatch( s, 10, "0123456789" ) ) failed++;
473 
474 	str_strcpyc( s, "01234567890" );
475 	str_pad( s, 10, '-' );
476 	if ( string_mismatch( s, 11, "01234567890" ) ) failed++;
477 
478 	return failed;
479 }
480 
481 static int
test_makepath(str * s)482 test_makepath( str *s )
483 {
484 	int failed = 0;
485 
486 	str_empty( s );
487 	str_makepath( s, "", "", '/' );
488 	if ( string_mismatch( s, 0, "" ) ) failed++;
489 
490 	str_makepath( s, "", "file1.txt", '/' );
491 	if ( string_mismatch( s, 9, "file1.txt" ) ) failed++;
492 
493 	str_makepath( s, "/home/user", "", '/' );
494 	if ( string_mismatch( s, 11, "/home/user/" ) ) failed++;
495 
496 	str_makepath( s, "/home/user", "file1.txt", '/' );
497 	if ( string_mismatch( s, 20, "/home/user/file1.txt" ) ) failed++;
498 
499 	str_makepath( s, "/home/user/", "", '/' );
500 	if ( string_mismatch( s, 11, "/home/user/" ) ) failed++;
501 
502 	str_makepath( s, "/home/user/", "file1.txt", '/' );
503 	if ( string_mismatch( s, 20, "/home/user/file1.txt" ) ) failed++;
504 
505 	return failed;
506 }
507 
508 static int
test_findreplace(str * s)509 test_findreplace( str *s )
510 {
511 	char segment[]="0123456789";
512 	int numstrings = 1000, i;
513 	int failed = 0;
514 
515 	for ( i=0; i<numstrings; ++i ) {
516 		str_strcpyc( s, segment );
517 		str_findreplace( s, "234", "" );
518 	}
519 	if ( string_mismatch( s, 7, "0156789" ) ) failed++;
520 
521 	for ( i=0; i<numstrings; ++i ) {
522 		str_strcpyc( s, segment );
523 		str_findreplace( s, "234", "223344" );
524 	}
525 	if ( string_mismatch( s, 13, "0122334456789" ) ) failed++;
526 
527 	return failed;
528 }
529 
530 static int
test_mergestrs(str * s)531 test_mergestrs( str *s )
532 {
533 	int failed = 0;
534 
535 	str_empty( s );
536 
537 	/* don't add any anything */
538 	str_mergestrs( s, NULL );
539 	if ( string_mismatch( s, 0, "" ) ) failed++;
540 
541 	/* add just one string */
542 	str_mergestrs( s, "01", NULL );
543 	if ( string_mismatch( s, 2, "01" ) ) failed++;
544 
545 	/* add multiple strings */
546 	str_mergestrs( s, "01", "23", "45", "67", "89", NULL );
547 	if ( string_mismatch( s, 10, "0123456789" ) ) failed++;
548 
549 	return failed;
550 }
551 
552 static int
test_cpytodelim(str * s)553 test_cpytodelim( str *s )
554 {
555 	char str0[]="\0";
556 	char str1[]="Col1\tCol2\tCol3\n";
557 	char str2[]="Col1 Col2 Col3";
558 	const char *q;
559 	int failed = 0;
560 
561 	q = str_cpytodelim( s, str0, "\t", 0 );
562 	if ( string_mismatch( s, 0, "" ) ) failed++;
563 	if ( *q!='\0' ) {
564 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected '\\t'\n", __FUNCTION__, __LINE__, *q );
565 		failed++;
566 	}
567 
568 	q = str_cpytodelim( s, str1, "\t", 0 );
569 	if ( string_mismatch( s, 4, "Col1" ) ) failed++;
570 	if ( *q!='\t' ) {
571 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected '\\t'\n", __FUNCTION__, __LINE__, *q );
572 		failed++;
573 	}
574 
575 	q = str_cpytodelim( s, str1, " \t", 0 );
576 	if ( string_mismatch( s, 4, "Col1" ) ) failed++;
577 	if ( *q!='\t' ) {
578 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected '\\t'\n", __FUNCTION__, __LINE__, *q );
579 		failed++;
580 	}
581 
582 	q = str_cpytodelim( s, str1, "\t", 1 );
583 	if ( string_mismatch( s, 4, "Col1" ) ) failed++;
584 	if ( *q!='C' ) {
585 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected 'C'\n", __FUNCTION__, __LINE__, *q );
586 		failed++;
587 	}
588 
589 	q = str_cpytodelim( s, str1, "\n", 0 );
590 	if ( string_mismatch( s, strlen(str1)-1, "Col1\tCol2\tCol3" ) ) failed++;
591 	if ( *q!='\n' ) {
592 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected '\\n'\n", __FUNCTION__, __LINE__, *q );
593 		failed++;
594 	}
595 
596 	q = str_cpytodelim( s, str1, "\r", 0 );
597 	if ( string_mismatch( s, strlen(str1), "Col1\tCol2\tCol3\n" ) ) failed++;
598 	if ( *q!='\0' ) {
599 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected '\\n'\n", __FUNCTION__, __LINE__, *q );
600 		failed++;
601 	}
602 
603 	q = str_cpytodelim( s, str2, " ", 0 );
604 	if ( string_mismatch( s, 4, "Col1" ) ) failed++;
605 	if ( *q!=' ' ) {
606 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected '\\t'\n", __FUNCTION__, __LINE__, *q );
607 		failed++;
608 	}
609 
610 	q = str_cpytodelim( s, str2, "\t", 0 );
611 	if ( string_mismatch( s, strlen(str2), str2 ) ) failed++;
612 	if ( *q!='\0' ) {
613 		fprintf( stdout, "%s line %d: str_cpytodelim() returned '%c', expected '\\t'\n", __FUNCTION__, __LINE__, *q );
614 		failed++;
615 	}
616 
617 	return failed;
618 }
619 
620 /* char *str_caytodelim  ( str *s, char *p, const char *delim, unsigned char finalstep ); */
621 static int
test_cattodelim(str * s)622 test_cattodelim( str *s )
623 {
624 	char str1[] = "1 1 1 1 1 1 1";
625 	int failed = 0, i, n = 2;
626 	const char *q;
627 
628 	str_empty( s );
629 	for ( i=0; i<n; ++i ) {
630 		q = str_cattodelim( s, str1, " ", 0 );
631 		if ( *q!=' ' ) {
632 			fprintf( stdout, "%s line %d: str_cattodelim() returned '%c', expected ' '\n", __FUNCTION__, __LINE__, *q );
633 			failed++;
634 		}
635 	}
636 	if ( string_mismatch( s, n, "11" ) ) failed++;
637 
638 	str_empty( s );
639 	q = str1;
640 	while ( *q ) {
641 		q = str_cattodelim( s, q, " ", 1 );
642 		if ( *q!='1' && *q!='\0' ) {
643 			fprintf( stdout, "%s line %d: str_cattodelim() returned '%c', expected '1' or '\\0' \n", __FUNCTION__, __LINE__, *q );
644 			failed++;
645 		}
646 	}
647 	if ( string_mismatch( s, 7, "1111111" ) ) failed++;
648 
649 	return failed;
650 }
651 
652 static int
test_strdup(void)653 test_strdup( void )
654 {
655 	char str1[] = "In Isbel's case and mine own. Service is no heritage: and I think I shall never have the blessing of God till I have issue o' my body; for they say barnes are blessings.";
656 	char str2[] = "Here once again we sit, once again crown'd, And looked upon, I hope, with cheerful eyes.";
657 	int failed = 0;
658 	str *dup;
659 
660 	dup = str_strdupc( "" );
661 	if ( dup==NULL ) {
662 		fprintf( stdout, "%s line %d: str_strdup() returned NULL\n", __FUNCTION__, __LINE__ );
663 		failed++;
664 	} else {
665 		if ( string_mismatch( dup, 0, "" ) ) failed++;
666 		str_delete( dup );
667 	}
668 
669 	dup = str_strdupc( str1 );
670 	if ( dup==NULL ) {
671 		fprintf( stdout, "%s line %d: str_strdup() returned NULL\n", __FUNCTION__, __LINE__ );
672 		failed++;
673 	} else {
674 		if ( string_mismatch( dup, strlen(str1), str1 ) ) failed++;
675 		str_delete( dup );
676 	}
677 
678 	dup = str_strdupc( str2 );
679 	if ( dup==NULL ) {
680 		fprintf( stdout, "%s line %d: str_strdup() returned NULL\n", __FUNCTION__, __LINE__ );
681 		failed++;
682 	} else {
683 		if ( string_mismatch( dup, strlen(str2), str2 ) ) failed++;
684 		str_delete( dup );
685 	}
686 	return failed;
687 }
688 
689 static int
test_toupper(str * s)690 test_toupper( str *s )
691 {
692 	char str1[] = "abcde_ABCDE_12345";
693 	char str2[] = "0123456789";
694 	int failed = 0;
695 
696 	str_empty( s );
697 	str_toupper( s );
698 	if ( string_mismatch( s, 0, "" ) ) failed++;
699 
700 	str_strcpyc( s, str1 );
701 	str_toupper( s );
702 	if ( string_mismatch( s, strlen(str1), "ABCDE_ABCDE_12345" ) ) failed++;
703 
704 	str_strcpyc( s, str2 );
705 	str_toupper( s );
706 	if ( string_mismatch( s, strlen(str2), str2 ) ) failed++;
707 
708 	return failed;
709 }
710 
711 static int
test_tolower(str * s)712 test_tolower( str *s )
713 {
714 	char str1[] = "abcde_ABCDE_12345";
715 	char str2[] = "0123456789";
716 	int failed = 0;
717 
718 	str_empty( s );
719 	str_tolower( s );
720 	if ( string_mismatch( s, 0, "" ) ) failed++;
721 
722 	str_strcpyc( s, str1 );
723 	str_tolower( s );
724 	if ( string_mismatch( s, strlen(str1), "abcde_abcde_12345" ) ) failed++;
725 
726 	str_strcpyc( s, str2 );
727 	str_tolower( s );
728 	if ( string_mismatch( s, strlen(str2), str2 ) ) failed++;
729 
730 	return failed;
731 }
732 
733 static int
test_trimws(str * s)734 test_trimws( str *s )
735 {
736 	char str1[] = "      ksjadfk    lajskfjds      askdjflkj   ";
737 	char str2[] = "        ";
738 	int failed = 0;
739 
740 	str_empty( s );
741 	str_trimstartingws( s );
742 	if ( string_mismatch( s, 0, "" ) ) failed++;
743 	str_trimendingws( s );
744 	if ( string_mismatch( s, 0, "" ) ) failed++;
745 
746 	str_strcpyc( s, str2 );
747 	str_trimstartingws( s );
748 	if ( string_mismatch( s, 0, "" ) ) failed++;
749 
750 	str_strcpyc( s, str2 );
751 	str_trimendingws( s );
752 	if ( string_mismatch( s, 0, "" ) ) failed++;
753 
754 	str_strcpyc( s, str1 );
755 	str_trimstartingws( s );
756 	if ( string_mismatch( s, strlen("ksjadfk    lajskfjds      askdjflkj   "), "ksjadfk    lajskfjds      askdjflkj   " ) ) failed++;
757 	str_trimendingws( s );
758 	if ( string_mismatch( s, strlen("ksjadfk    lajskfjds      askdjflkj"), "ksjadfk    lajskfjds      askdjflkj" ) ) failed++;
759 
760 	str_strcpyc( s, str1 );
761 	str_trimendingws( s );
762 	if ( string_mismatch( s, strlen("      ksjadfk    lajskfjds      askdjflkj"), "      ksjadfk    lajskfjds      askdjflkj" ) ) failed++;
763 	str_trimstartingws( s );
764 	if ( string_mismatch( s, strlen("ksjadfk    lajskfjds      askdjflkj"), "ksjadfk    lajskfjds      askdjflkj" ) ) failed++;
765 
766 	str_empty( s );
767 	str_stripws( s );
768 	if ( string_mismatch( s, 0, "" ) ) failed++;
769 
770 	str_strcpyc( s, "0123456789" );
771 	str_stripws( s );
772 	if ( string_mismatch( s, 10, "0123456789" ) ) failed++;
773 
774 	str_strcpyc( s, str1 );
775 	str_stripws( s );
776 	if ( string_mismatch( s, strlen("ksjadfklajskfjdsaskdjflkj"), "ksjadfklajskfjdsaskdjflkj" ) ) failed++;
777 
778 	return failed;
779 }
780 
781 static int
test_reverse(str * s)782 test_reverse( str *s )
783 {
784 	int failed = 0;
785 
786 	/* empty string */
787 	str_strcpyc( s, "" );
788 	str_reverse( s );
789 	if ( string_mismatch( s, 0, "" ) ) failed++;
790 
791 	/* string with even number of elements */
792 	str_strcpyc( s, "0123456789" );
793 	str_reverse( s );
794 	if ( string_mismatch( s, 10, "9876543210" ) ) failed++;
795 	str_reverse( s );
796 	if ( string_mismatch( s, 10, "0123456789" ) ) failed++;
797 
798 	/* string with odd number of elements */
799 	str_strcpyc( s, "123456789" );
800 	str_reverse( s );
801 	if ( string_mismatch( s, 9, "987654321" ) ) failed++;
802 	str_reverse( s );
803 	if ( string_mismatch( s, 9, "123456789" ) ) failed++;
804 
805 	return failed;
806 }
807 
808 static int
test_trim(str * s)809 test_trim( str *s )
810 {
811 	char str1[] = "123456789";
812 	char str2[] = "987654321";
813 	int failed = 0;
814 
815 	str_strcpyc( s, str1 );
816 	str_trimbegin( s, 0 );
817 	if ( string_mismatch( s, 9, str1 ) ) failed++;
818 	str_trimend( s, 0 );
819 	if ( string_mismatch( s, 9, str1 ) ) failed++;
820 
821 	str_strcpyc( s, str1 );
822 	str_trimbegin( s, 1 );
823 	if ( string_mismatch( s, 8, "23456789" ) ) failed++;
824 
825 	str_strcpyc( s, str1 );
826 	str_trimbegin( s, 4 );
827 	if ( string_mismatch( s, 5, "56789" ) ) failed++;
828 
829 	str_strcpyc( s, str1 );
830 	str_trimbegin( s, 9 );
831 	if ( string_mismatch( s, 0, "" ) ) failed++;
832 
833 	str_strcpyc( s, str2 );
834 	str_trimend( s, 1 );
835 	if ( string_mismatch( s, 8, "98765432" ) ) failed++;
836 
837 	str_strcpyc( s, str2 );
838 	str_trimend( s, 6 );
839 	if ( string_mismatch( s, 3, "987" ) ) failed++;
840 
841 	str_strcpyc( s, str2 );
842 	str_trimend( s, 9 );
843 	if ( string_mismatch( s, 0, "" ) ) failed++;
844 
845 	return failed;
846 }
847 
848 static int
test_case(str * s)849 test_case( str *s )
850 {
851 	int failed = 0;
852 
853 	str_strcpyc( s, "asdfjalskjfljasdfjlsfjd" );
854 	if ( !str_is_lowercase( s ) ) {
855 		fprintf( stdout, "%s line %d: str_is_lowercase('%s') returned false\n", __FUNCTION__, __LINE__, s->data );
856 		failed++;
857 	}
858 	if ( str_is_uppercase( s ) ) {
859 		fprintf( stdout, "%s line %d: str_is_uppercase('%s') returned true\n", __FUNCTION__, __LINE__, s->data );
860 		failed++;
861 	}
862 	if ( str_is_mixedcase( s ) ) {
863 		fprintf( stdout, "%s line %d: str_is_mixedcase('%s') returned true\n", __FUNCTION__, __LINE__, s->data );
864 		failed++;
865 	}
866 
867 	str_strcpyc( s, "ASDFJALSKJFLJASDFJLSFJD" );
868 	if ( str_is_lowercase( s ) ) {
869 		fprintf( stdout, "%s line %d: str_is_lowercase('%s') returned true\n", __FUNCTION__, __LINE__, s->data );
870 		failed++;
871 	}
872 	if ( !str_is_uppercase( s ) ) {
873 		fprintf( stdout, "%s line %d: str_is_uppercase('%s') returned false\n", __FUNCTION__, __LINE__, s->data );
874 		failed++;
875 	}
876 	if ( str_is_mixedcase( s ) ) {
877 		fprintf( stdout, "%s line %d: str_is_mixedcase('%s') returned true\n", __FUNCTION__, __LINE__, s->data );
878 		failed++;
879 	}
880 
881 	str_strcpyc( s, "ASdfjalsKJFLJASdfjlsfjd" );
882 	if ( str_is_lowercase( s ) ) {
883 		fprintf( stdout, "%s line %d: str_is_lowercase('%s') returned true\n", __FUNCTION__, __LINE__, s->data );
884 		failed++;
885 	}
886 	if ( str_is_uppercase( s ) ) {
887 		fprintf( stdout, "%s line %d: str_is_uppercase('%s') returned true\n", __FUNCTION__, __LINE__, s->data );
888 		failed++;
889 	}
890 	if ( !str_is_mixedcase( s ) ) {
891 		fprintf( stdout, "%s line %d: str_is_mixedcase('%s') returned false\n", __FUNCTION__, __LINE__, s->data );
892 		failed++;
893 	}
894 
895 	return failed;
896 }
897 
898 static int
test_strcmp(str * s)899 test_strcmp( str *s )
900 {
901 	int failed = 0;
902 	str t;
903 
904 	str_init( &t );
905 
906 	str_empty( s );
907 	if ( str_strcmp( s, s ) ) {
908 		fprintf( stdout, "%s line %d: str_strcmp(s,s) returned non-zero\n", __FUNCTION__, __LINE__ );
909 		failed++;
910 	}
911 	if ( str_strcmp( s, &t ) ) {
912 		fprintf( stdout, "%s line %d: str_strcmp(s,t) returned non-zero\n", __FUNCTION__, __LINE__ );
913 		failed++;
914 	}
915 
916 	str_strcpyc( s, "lakjsdlfjdskljfklsjf" );
917 	if ( str_strcmp( s, s ) ) {
918 		fprintf( stdout, "%s line %d: str_strcmp(s,s) returned non-zero\n", __FUNCTION__, __LINE__ );
919 		failed++;
920 	}
921 	if ( !str_strcmp( s, &t ) ) {
922 		fprintf( stdout, "%s line %d: str_strcmp(s,t) returned zero\n", __FUNCTION__, __LINE__ );
923 		failed++;
924 	}
925 
926 	str_strcpy( &t, s );
927 	if ( str_strcmp( s, s ) ) {
928 		fprintf( stdout, "%s line %d: str_strcmp(s,s) returned non-zero\n", __FUNCTION__, __LINE__ );
929 		failed++;
930 	}
931 	if ( str_strcmp( s, &t ) ) {
932 		fprintf( stdout, "%s line %d: str_strcmp(s,t) returned non-zero\n", __FUNCTION__, __LINE__ );
933 		failed++;
934 	}
935 
936 	str_free( &t );
937 
938 	return failed;
939 }
940 
941 static int
test_match(str * s)942 test_match( str *s )
943 {
944 	int failed = 0;
945 
946 	str_empty( s );
947 	if ( str_match_first( s, '0' ) ) {
948 		fprintf( stdout, "%s line %d: str_match_first() returned non-zero\n", __FUNCTION__, __LINE__ );
949 		failed++;
950 	}
951 	str_strcpyc( s, "012345" );
952 	if ( !str_match_first( s, '0' ) ) {
953 		fprintf( stdout, "%s line %d: str_match_first() returned zero\n", __FUNCTION__, __LINE__ );
954 		failed++;
955 	}
956 	if ( !str_match_end( s, '5' ) ) {
957 		fprintf( stdout, "%s line %d: str_match_end() returned zero\n", __FUNCTION__, __LINE__ );
958 		failed++;
959 	}
960 
961 	return failed;
962 }
963 
964 static int
test_char(str * s)965 test_char( str *s )
966 {
967 	unsigned long i;
968 	str t, u;
969 	int failed = 0;
970 
971 	str_init( &t );
972 	str_init( &u );
973 
974 	str_empty( s );
975 	for ( i=0; i<5; ++i ) {
976 		if ( str_char( s, i ) != '\0' ) {
977 			fprintf( stdout, "%s line %d: str_char() did not return '\\0'\n", __FUNCTION__, __LINE__ );
978 			failed++;
979 		}
980 		if ( str_revchar( s, i ) != '\0' ) {
981 			fprintf( stdout, "%s line %d: str_revchar() did not return '\\0'\n", __FUNCTION__, __LINE__ );
982 			failed++;
983 		}
984 	}
985 
986 	str_strcpyc( s, "0123456789" );
987 	for ( i=0; i<s->len; ++i ) {
988 		str_addchar( &t, str_char( s, i ) );
989 		str_addchar( &u, str_revchar( s, i ) );
990 	}
991 
992 	if ( string_mismatch( &t, s->len, s->data ) ) failed++;
993 
994 	str_reverse( s );
995 	if ( string_mismatch( &u, s->len, s->data ) ) failed++;
996 
997 	str_free( &t );
998 	str_free( &u );
999 
1000 	return failed;
1001 }
1002 
1003 static int
test_swapstrings(str * s)1004 test_swapstrings( str *s )
1005 {
1006 	int failed = 0;
1007 	str t;
1008 
1009 	str_init( &t );
1010 
1011 	str_strcpyc( &t, "0123456789" );
1012 	str_strcpyc( s,  "abcde" );
1013 
1014 	str_swapstrings( s, &t );
1015 	if ( string_mismatch( &t, 5, "abcde" ) ) failed++;
1016 	if ( string_mismatch( s, 10, "0123456789" ) ) failed++;
1017 
1018 	str_swapstrings( s, &t );
1019 	if ( string_mismatch( s, 5, "abcde" ) ) failed++;
1020 	if ( string_mismatch( &t, 10, "0123456789" ) ) failed++;
1021 
1022 	str_free( &t );
1023 
1024 	return failed;
1025 }
1026 
1027 int
main(int argc,char * argv[])1028 main ( int argc, char *argv[] )
1029 {
1030 	int failed = 0;
1031 	int ntest = 2;
1032 	int i;
1033 	str s;
1034 	str_init( &s );
1035 
1036 	/* ...core functions */
1037 	for ( i=0; i<ntest; ++i )
1038 		failed += test_empty( &s );
1039 
1040 	/* ...adding functions */
1041 	for ( i=0; i<ntest; ++i)
1042 		failed += test_addchar( &s );
1043 	for ( i=0; i<ntest; ++i)
1044 		failed += test_strcatc( &s );
1045 	for ( i=0; i<ntest; ++i )
1046 		failed += test_strcat( &s );
1047 	for ( i=0; i<ntest; ++i )
1048 		failed += test_segcat( &s );
1049 	for ( i=0; i<ntest; ++i )
1050 		failed += test_indxcat( &s );
1051 	for ( i=0; i<ntest; ++i )
1052 		failed += test_cattodelim( &s );
1053 	for ( i=0; i<ntest; ++i )
1054 		failed += test_prepend( &s );
1055 	for ( i=0; i<ntest; ++i )
1056 		failed += test_pad( &s );
1057 	for ( i=0; i<ntest; ++i )
1058 		failed += test_mergestrs( &s );
1059 	for ( i=0; i<ntest; ++i )
1060 		failed += test_makepath( &s );
1061 
1062 	/* ...copying functions */
1063 	for ( i=0; i<ntest; ++i)
1064 		failed += test_strcpyc( &s );
1065 	for ( i=0; i<ntest; ++i)
1066 		failed += test_strcpy( &s );
1067 	for ( i=0; i<ntest; ++i )
1068 		failed += test_cpytodelim( &s );
1069 	for ( i=0; i<ntest; ++i)
1070 		failed += test_segcpy( &s );
1071 	for ( i=0; i<ntest; ++i)
1072 		failed += test_indxcpy( &s );
1073 	for ( i=0; i<ntest; ++i )
1074 		failed += test_copyposlen( &s );
1075 	for ( i=0; i<ntest; ++i )
1076 		failed += test_strdup();
1077 
1078 	/* ...utility functions */
1079 	for ( i=0; i<ntest; ++i)
1080 		failed += test_findreplace( &s );
1081 	for ( i=0; i<ntest; ++i )
1082 		failed += test_reverse( &s );
1083 	for ( i=0; i<ntest; ++i )
1084 		failed += test_toupper( &s );
1085 	for ( i=0; i<ntest; ++i )
1086 		failed += test_tolower( &s );
1087 	for ( i=0; i<ntest; ++i )
1088 		failed += test_trimws( &s );
1089 	for ( i=0; i<ntest; ++i )
1090 		failed += test_trim( &s );
1091 	for ( i=0; i<ntest; ++i )
1092 		failed += test_case( &s );
1093 	for ( i=0; i<ntest; ++i )
1094 		failed += test_strcmp( &s );
1095 	for ( i=0; i<ntest; ++i )
1096 		failed += test_char( &s );
1097 	for ( i=0; i<ntest; ++i )
1098 		failed += test_swapstrings( &s );
1099 	for ( i=0; i<ntest; ++i )
1100 		failed += test_match( &s );
1101 
1102 	str_free( &s );
1103 
1104 	if ( !failed ) {
1105 		printf( "%s: PASSED\n", progname );
1106 		return EXIT_SUCCESS;
1107 	} else {
1108 		printf( "%s: FAILED\n", progname );
1109 		return EXIT_FAILURE;
1110 	}
1111 	return EXIT_SUCCESS;
1112 }
1113