2 * string-test.c: a collection of libsvn_string tests
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
19 /* ====================================================================
20 To add tests, look toward the bottom of this file.
29 #include <apr_pools.h>
30 #include <apr_file_io.h>
33 #include "svn_error.h"
34 #include "svn_string.h" /* This includes <apr_*.h> */
36 #include "../svn_test.h"
39 /* A quick way to create error messages. */
41 fail(apr_pool_t
*pool
, const char *fmt
, ...)
47 msg
= apr_pvsprintf(pool
, fmt
, ap
);
50 return svn_error_create(SVN_ERR_TEST_FAILED
, 0, msg
);
54 /* Some of our own global variables, for simplicity. Yes,
56 svn_stringbuf_t
*a
= NULL
, *b
= NULL
, *c
= NULL
;
57 const char *phrase_1
= "hello, ";
58 const char *phrase_2
= "a longish phrase of sorts, longer than 16 anyway";
64 test1(const char **msg
,
65 svn_boolean_t msg_only
,
66 svn_test_opts_t
*opts
,
69 *msg
= "make svn_stringbuf_t from cstring";
74 a
= svn_stringbuf_create(phrase_1
, pool
);
76 /* Test that length, data, and null-termination are correct. */
77 if ((a
->len
== strlen(phrase_1
)) && ((strcmp(a
->data
, phrase_1
)) == 0))
80 return fail(pool
, "test failed");
85 test2(const char **msg
,
86 svn_boolean_t msg_only
,
87 svn_test_opts_t
*opts
,
90 *msg
= "make svn_stringbuf_t from substring of cstring";
95 b
= svn_stringbuf_ncreate(phrase_2
, 16, pool
);
97 /* Test that length, data, and null-termination are correct. */
98 if ((b
->len
== 16) && ((strncmp(b
->data
, phrase_2
, 16)) == 0))
101 return fail(pool
, "test failed");
106 test3(const char **msg
,
107 svn_boolean_t msg_only
,
108 svn_test_opts_t
*opts
,
114 *msg
= "append svn_stringbuf_t to svn_stringbuf_t";
119 a
= svn_stringbuf_create(phrase_1
, pool
);
120 b
= svn_stringbuf_ncreate(phrase_2
, 16, pool
);
122 tmp
= apr_palloc(pool
, (a
->len
+ b
->len
+ 1));
123 strcpy(tmp
, a
->data
);
124 strcat(tmp
, b
->data
);
126 svn_stringbuf_appendstr(a
, b
);
128 /* Test that length, data, and null-termination are correct. */
129 if ((a
->len
== (old_len
+ b
->len
)) && ((strcmp(a
->data
, tmp
)) == 0))
132 return fail(pool
, "test failed");
137 test4(const char **msg
,
138 svn_boolean_t msg_only
,
139 svn_test_opts_t
*opts
,
142 *msg
= "append C string to svn_stringbuf_t";
147 a
= svn_stringbuf_create(phrase_1
, pool
);
148 svn_stringbuf_appendcstr(a
, "new bytes to append");
150 /* Test that length, data, and null-termination are correct. */
151 if (svn_stringbuf_compare
152 (a
, svn_stringbuf_create("hello, new bytes to append", pool
)))
155 return fail(pool
, "test failed");
160 test5(const char **msg
,
161 svn_boolean_t msg_only
,
162 svn_test_opts_t
*opts
,
165 *msg
= "append bytes, then compare two strings";
170 a
= svn_stringbuf_create(phrase_1
, pool
);
171 svn_stringbuf_appendbytes(a
, "new bytes to append", 9);
173 /* Test that length, data, and null-termination are correct. */
174 if (svn_stringbuf_compare
175 (a
, svn_stringbuf_create("hello, new bytes", pool
)))
178 return fail(pool
, "test failed");
183 test6(const char **msg
,
184 svn_boolean_t msg_only
,
185 svn_test_opts_t
*opts
,
188 *msg
= "dup two strings, then compare";
193 a
= svn_stringbuf_create(phrase_1
, pool
);
194 b
= svn_stringbuf_create(phrase_2
, pool
);
195 c
= svn_stringbuf_dup(a
, pool
);
197 /* Test that length, data, and null-termination are correct. */
198 if ((svn_stringbuf_compare(a
, c
)) && (! svn_stringbuf_compare(b
, c
)))
201 return fail(pool
, "test failed");
206 test7(const char **msg
,
207 svn_boolean_t msg_only
,
208 svn_test_opts_t
*opts
,
214 *msg
= "chopping a string";
219 c
= svn_stringbuf_create(phrase_2
, pool
);
222 tmp
= apr_palloc(pool
, c
->len
+ 1);
223 strcpy(tmp
, c
->data
);
225 svn_stringbuf_chop(c
, 11);
227 if ((c
->len
== (tmp_len
- 11))
228 && (strncmp(tmp
, c
->data
, c
->len
) == 0)
229 && (c
->data
[c
->len
] == '\0'))
232 return fail(pool
, "test failed");
237 test8(const char **msg
,
238 svn_boolean_t msg_only
,
239 svn_test_opts_t
*opts
,
242 *msg
= "emptying a string";
247 c
= svn_stringbuf_create(phrase_2
, pool
);
249 svn_stringbuf_setempty(c
);
251 if ((c
->len
== 0) && (c
->data
[0] == '\0'))
254 return fail(pool
, "test failed");
259 test9(const char **msg
,
260 svn_boolean_t msg_only
,
261 svn_test_opts_t
*opts
,
264 *msg
= "fill string with hashmarks";
269 a
= svn_stringbuf_create(phrase_1
, pool
);
271 svn_stringbuf_fillchar(a
, '#');
273 if ((strcmp(a
->data
, "#######") == 0)
274 && ((strncmp(a
->data
, "############", a
->len
- 1)) == 0)
275 && (a
->data
[(a
->len
- 1)] == '#')
276 && (a
->data
[(a
->len
)] == '\0'))
279 return fail(pool
, "test failed");
285 test10(const char **msg
,
286 svn_boolean_t msg_only
,
287 svn_test_opts_t
*opts
,
290 svn_stringbuf_t
*s
, *t
;
293 size_t block_len_1
= 0;
294 size_t block_len_2
= 0;
296 *msg
= "block initialization and growth";
301 s
= svn_stringbuf_create("a small string", pool
);
303 block_len_1
= (s
->blocksize
);
305 t
= svn_stringbuf_create(", plus a string more than twice as long", pool
);
306 svn_stringbuf_appendstr(s
, t
);
308 block_len_2
= (s
->blocksize
);
311 * - The initial block was just the right fit.
312 * - The block more than doubled (because second string so long).
313 * - The block grew by a power of 2.
315 if ((len_1
== (block_len_1
- 1))
316 && ((block_len_2
/ block_len_1
) > 2)
317 && (((block_len_2
/ block_len_1
) % 2) == 0))
320 return fail(pool
, "test failed");
325 test11(const char **msg
,
326 svn_boolean_t msg_only
,
327 svn_test_opts_t
*opts
,
332 *msg
= "formatting strings from varargs";
337 s
= svn_stringbuf_createf(pool
,
338 "This %s is used in test %d.",
342 if (strcmp(s
->data
, "This string is used in test 12.") == 0)
345 return fail(pool
, "test failed");
349 check_string_contents(svn_stringbuf_t
*string
,
351 apr_size_t ftext_len
,
361 for (i
= 0; i
< repeat
; ++i
)
363 if (len
< ftext_len
|| memcmp(ftext
, data
, ftext_len
))
364 return fail(pool
, "comparing failed");
368 if (len
< 1 || memcmp(data
, "\0", 1))
369 return fail(pool
, "comparing failed");
372 for (i
= 0; i
< repeat
; ++i
)
374 if (len
< ftext_len
|| memcmp(ftext
, data
, ftext_len
))
375 return fail(pool
, "comparing failed");
381 return fail(pool
, "comparing failed");
388 test12(const char **msg
,
389 svn_boolean_t msg_only
,
390 svn_test_opts_t
*opts
,
394 const char fname
[] = "string-test.tmp";
400 "Just some boring text. Avoiding newlines 'cos I don't know"
401 "if any of the Subversion platfoms will mangle them! There's no"
402 "need to test newline handling here anyway, it's not relevant.";
404 *msg
= "create string from file";
409 status
= apr_file_open(&file
, fname
, APR_WRITE
| APR_TRUNCATE
| APR_CREATE
,
410 APR_OS_DEFAULT
, pool
);
412 return fail(pool
, "opening file");
417 for (i
= 0; i
< repeat
; ++i
)
419 status
= apr_file_write_full(file
, ftext
, sizeof(ftext
) - 1, &len
);
421 return fail(pool
, "writing file");
424 /* A null byte, I don't *think* any of our platforms mangle these */
425 status
= apr_file_write_full(file
, "\0", 1, &len
);
427 return fail(pool
, "writing file");
430 for (i
= 0; i
< repeat
; ++i
)
432 status
= apr_file_write_full(file
, ftext
, sizeof(ftext
) - 1, &len
);
434 return fail(pool
, "writing file");
437 status
= apr_file_close(file
);
439 return fail(pool
, "closing file");
441 SVN_ERR(svn_stringbuf_from_file(&s
, fname
, pool
));
442 SVN_ERR(check_string_contents(s
, ftext
, sizeof(ftext
) - 1, repeat
, pool
));
444 /* Reset to avoid false positives */
447 status
= apr_file_open(&file
, fname
, APR_READ
, APR_OS_DEFAULT
, pool
);
449 return fail(pool
, "opening file");
451 SVN_ERR(svn_stringbuf_from_aprfile(&s
, file
, pool
));
452 SVN_ERR(check_string_contents(s
, ftext
, sizeof(ftext
) - 1, repeat
, pool
));
454 status
= apr_file_close(file
);
456 return fail(pool
, "closing file");
461 /* Helper function for checking correctness of find_char_backward */
463 test_find_char_backward(const char* data
,
467 svn_boolean_t msg_only
,
475 a
= svn_stringbuf_create(data
, pool
);
476 i
= svn_stringbuf_find_char_backward(a
, ch
);
481 return fail(pool
, "test failed");
485 test13(const char **msg
,
486 svn_boolean_t msg_only
,
487 svn_test_opts_t
*opts
,
490 *msg
= "find_char_backward; middle case";
491 a
= svn_stringbuf_create("test, test", pool
);
494 test_find_char_backward(a
->data
, a
->len
, ',', 4, msg_only
, pool
);
498 test14(const char **msg
,
499 svn_boolean_t msg_only
,
500 svn_test_opts_t
*opts
,
503 *msg
= "find_char_backward; 0 case";
505 a
= svn_stringbuf_create(",test test", pool
);
508 test_find_char_backward(a
->data
, a
->len
, ',', 0, msg_only
, pool
);
512 test15(const char **msg
,
513 svn_boolean_t msg_only
,
514 svn_test_opts_t
*opts
,
517 *msg
= "find_char_backward; strlen - 1 case";
519 a
= svn_stringbuf_create("testing,", pool
);
521 return test_find_char_backward(a
->data
,
530 test16(const char **msg
,
531 svn_boolean_t msg_only
,
532 svn_test_opts_t
*opts
,
535 *msg
= "find_char_backward; len = 0 case";
537 a
= svn_stringbuf_create("", pool
);
540 test_find_char_backward(a
->data
, a
->len
, ',', 0, msg_only
, pool
);
544 test17(const char **msg
,
545 svn_boolean_t msg_only
,
546 svn_test_opts_t
*opts
,
549 *msg
= "find_char_backward; no occurence case";
551 a
= svn_stringbuf_create("test test test", pool
);
553 return test_find_char_backward(a
->data
,
562 test_first_non_whitespace(const char *str
,
563 const apr_size_t pos
,
564 svn_boolean_t msg_only
,
572 a
= svn_stringbuf_create(str
, pool
);
574 i
= svn_stringbuf_first_non_whitespace(a
);
579 return fail(pool
, "test failed");
583 test18(const char **msg
,
584 svn_boolean_t msg_only
,
585 svn_test_opts_t
*opts
,
588 *msg
= "check whitespace removal; common case";
590 return test_first_non_whitespace(" \ttest", 4, msg_only
, pool
);
594 test19(const char **msg
,
595 svn_boolean_t msg_only
,
596 svn_test_opts_t
*opts
,
599 *msg
= "check whitespace removal; no whitespace case";
601 return test_first_non_whitespace("test", 0, msg_only
, pool
);
605 test20(const char **msg
,
606 svn_boolean_t msg_only
,
607 svn_test_opts_t
*opts
,
610 *msg
= "check whitespace removal; all whitespace case";
612 return test_first_non_whitespace(" ", 3, msg_only
, pool
);
616 test21(const char **msg
,
617 svn_boolean_t msg_only
,
618 svn_test_opts_t
*opts
,
621 *msg
= "check that whitespace will be stripped correctly";
626 a
= svn_stringbuf_create(" \ttest\t\t \t ", pool
);
627 b
= svn_stringbuf_create("test", pool
);
629 svn_stringbuf_strip_whitespace(a
);
631 if (svn_stringbuf_compare(a
, b
) == TRUE
)
634 return fail(pool
, "test failed");
638 test_stringbuf_unequal(const char* str1
,
640 svn_boolean_t msg_only
,
646 a
= svn_stringbuf_create(str1
, pool
);
647 b
= svn_stringbuf_create(str2
, pool
);
649 if (svn_stringbuf_compare(a
, b
))
650 return fail(pool
, "test failed");
656 test22(const char **msg
,
657 svn_boolean_t msg_only
,
658 svn_test_opts_t
*opts
,
661 *msg
= "compare stringbufs; different lengths";
663 return test_stringbuf_unequal("abc", "abcd", msg_only
, pool
);
667 test23(const char **msg
,
668 svn_boolean_t msg_only
,
669 svn_test_opts_t
*opts
,
672 *msg
= "compare stringbufs; same length, different content";
674 return test_stringbuf_unequal("abc", "abb", msg_only
, pool
);
678 ====================================================================
679 If you add a new test to this file, update this array.
681 (These globals are required by our included main())
684 /* An array of all test functions */
685 struct svn_test_descriptor_t test_funcs
[] =
688 SVN_TEST_PASS(test1
),
689 SVN_TEST_PASS(test2
),
690 SVN_TEST_PASS(test3
),
691 SVN_TEST_PASS(test4
),
692 SVN_TEST_PASS(test5
),
693 SVN_TEST_PASS(test6
),
694 SVN_TEST_PASS(test7
),
695 SVN_TEST_PASS(test8
),
696 SVN_TEST_PASS(test9
),
697 SVN_TEST_PASS(test10
),
698 SVN_TEST_PASS(test11
),
699 SVN_TEST_PASS(test12
),
700 SVN_TEST_PASS(test13
),
701 SVN_TEST_PASS(test14
),
702 SVN_TEST_PASS(test15
),
703 SVN_TEST_PASS(test16
),
704 SVN_TEST_PASS(test17
),
705 SVN_TEST_PASS(test18
),
706 SVN_TEST_PASS(test19
),
707 SVN_TEST_PASS(test20
),
708 SVN_TEST_PASS(test21
),
709 SVN_TEST_PASS(test22
),
710 SVN_TEST_PASS(test23
),