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