1 /*-
2  * Copyright (c) 2011 Tim Kientzle
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "test.h"
26 __FBSDID("$FreeBSD$");
27 
28 #define __LIBARCHIVE_TEST
29 #include "archive_string.h"
30 
31 #define EXTENT 32
32 
33 #define assertStringSizes(strlen, buflen, as) \
34 	assertEqualInt(strlen, (as).length); \
35 	assertEqualInt(buflen, (as).buffer_length);
36 
37 #define assertExactString(strlen, buflen, data, as) \
38 	do { \
39 		assertStringSizes(strlen, buflen, as); \
40 		assertEqualString(data, (as).s); \
41 	} while (0)
42 
43 #define assertNonNULLString(strlen, buflen, as) \
44 	do { \
45 		assertStringSizes(strlen, buflen, as); \
46 		assert(NULL != (as).s); \
47 	} while (0)
48 
49 static void
50 test_archive_string_ensure(void)
51 {
52 	struct archive_string s;
53 
54 	archive_string_init(&s);
55 	assertExactString(0, 0, NULL, s);
56 
57 	/* single-extent allocation */
58 	assert(&s == archive_string_ensure(&s, 5));
59 	assertNonNULLString(0, EXTENT, s);
60 
61 	/* what happens around extent boundaries? */
62 	assert(&s == archive_string_ensure(&s, EXTENT - 1));
63 	assertNonNULLString(0, EXTENT, s);
64 
65 	assert(&s == archive_string_ensure(&s, EXTENT));
66 	assertNonNULLString(0, EXTENT, s);
67 
68 	assert(&s == archive_string_ensure(&s, EXTENT + 1));
69 	assertNonNULLString(0, 2 * EXTENT, s);
70 
71 	archive_string_free(&s);
72 }
73 
74 static void
75 test_archive_strcat(void)
76 {
77 	struct archive_string s;
78 
79 	archive_string_init(&s);
80 	assertExactString(0, 0, NULL, s);
81 
82 	/* null target, empty source */
83 	assert(&s == archive_strcat(&s, ""));
84 	assertExactString(0, EXTENT, "", s);
85 
86 	/* empty target, empty source */
87 	assert(&s == archive_strcat(&s, ""));
88 	assertExactString(0, EXTENT, "", s);
89 
90 	/* empty target, non-empty source */
91 	assert(&s == archive_strcat(&s, "fubar"));
92 	assertExactString(5, EXTENT, "fubar", s);
93 
94 	/* non-empty target, non-empty source */
95 	assert(&s == archive_strcat(&s, "baz"));
96 	assertExactString(8, EXTENT, "fubarbaz", s);
97 
98 	archive_string_free(&s);
99 }
100 
101 static void
102 test_archive_strappend_char(void)
103 {
104 	struct archive_string s;
105 
106 	archive_string_init(&s);
107 	assertExactString(0, 0, NULL, s);
108 
109 	/* null target */
110 	archive_strappend_char(&s, 'X');
111 	assertExactString(1, EXTENT, "X", s);
112 
113 	/* non-empty target */
114 	archive_strappend_char(&s, 'Y');
115 	assertExactString(2, EXTENT, "XY", s);
116 
117 	archive_string_free(&s);
118 }
119 
120 /* archive_strnXXX() tests focus on length handling.
121  * other behaviors are tested by proxy through archive_strXXX()
122  */
123 
124 static void
125 test_archive_strncat(void)
126 {
127 	struct archive_string s;
128 
129 	archive_string_init(&s);
130 	assertExactString(0, 0, NULL, s);
131 
132 	/* perfect length */
133 	assert(&s == archive_strncat(&s, "snafu", 5));
134 	assertExactString(5, EXTENT, "snafu", s);
135 
136 	/* short read */
137 	assert(&s == archive_strncat(&s, "barbazqux", 3));
138 	assertExactString(8, EXTENT, "snafubar", s);
139 
140 	/* long read is ok too! */
141 	assert(&s == archive_strncat(&s, "snafu", 8));
142 	assertExactString(13, EXTENT, "snafubarsnafu", s);
143 
144 	archive_string_free(&s);
145 }
146 
147 static void
148 test_archive_strncpy(void)
149 {
150 	struct archive_string s;
151 
152 	archive_string_init(&s);
153 	assertExactString(0, 0, NULL, s);
154 
155 	/* perfect length */
156 	assert(&s == archive_strncpy(&s, "fubar", 5));
157 	assertExactString(5, EXTENT, "fubar", s);
158 
159 	/* short read */
160 	assert(&s == archive_strncpy(&s, "snafubar", 5));
161 	assertExactString(5, EXTENT, "snafu", s);
162 
163 	/* long read is ok too! */
164 	assert(&s == archive_strncpy(&s, "snafu", 8));
165 	assertExactString(5, EXTENT, "snafu", s);
166 
167 	archive_string_free(&s);
168 }
169 
170 static void
171 test_archive_strcpy(void)
172 {
173 	struct archive_string s;
174 
175 	archive_string_init(&s);
176 	assertExactString(0, 0, NULL, s);
177 
178 	/* null target */
179 	assert(&s == archive_strcpy(&s, "snafu"));
180 	assertExactString(5, EXTENT, "snafu", s);
181 
182 	/* dirty target */
183 	assert(&s == archive_strcpy(&s, "foo"));
184 	assertExactString(3, EXTENT, "foo", s);
185 
186 	/* dirty target, empty source */
187 	assert(&s == archive_strcpy(&s, ""));
188 	assertExactString(0, EXTENT, "", s);
189 
190 	archive_string_free(&s);
191 }
192 
193 static void
194 test_archive_string_concat(void)
195 {
196 	struct archive_string s, t, u, v;
197 
198 	archive_string_init(&s);
199 	assertExactString(0, 0, NULL, s);
200 	archive_string_init(&t);
201 	assertExactString(0, 0, NULL, t);
202 	archive_string_init(&u);
203 	assertExactString(0, 0, NULL, u);
204 	archive_string_init(&v);
205 	assertExactString(0, 0, NULL, v);
206 
207 	/* null target, null source */
208 	archive_string_concat(&t, &s);
209 	assertExactString(0, 0, NULL, s);
210 	assertExactString(0, EXTENT, "", t);
211 
212 	/* null target, empty source */
213 	assert(&s == archive_strcpy(&s, ""));
214 	archive_string_concat(&u, &s);
215 	assertExactString(0, EXTENT, "", s);
216 	assertExactString(0, EXTENT, "", u);
217 
218 	/* null target, non-empty source */
219 	assert(&s == archive_strcpy(&s, "foo"));
220 	archive_string_concat(&v, &s);
221 	assertExactString(3, EXTENT, "foo", s);
222 	assertExactString(3, EXTENT, "foo", v);
223 
224 	/* empty target, empty source */
225 	assert(&s == archive_strcpy(&s, ""));
226 	assert(&t == archive_strcpy(&t, ""));
227 	archive_string_concat(&t, &s);
228 	assertExactString(0, EXTENT, "", s);
229 	assertExactString(0, EXTENT, "", t);
230 
231 	/* empty target, non-empty source */
232 	assert(&s == archive_strcpy(&s, "snafu"));
233 	assert(&t == archive_strcpy(&t, ""));
234 	archive_string_concat(&t, &s);
235 	assertExactString(5, EXTENT, "snafu", s);
236 	assertExactString(5, EXTENT, "snafu", t);
237 
238 	archive_string_free(&v);
239 	archive_string_free(&u);
240 	archive_string_free(&t);
241 	archive_string_free(&s);
242 }
243 
244 static void
245 test_archive_string_copy(void)
246 {
247 	struct archive_string s, t, u, v;
248 
249 	archive_string_init(&s);
250 	assertExactString(0, 0, NULL, s);
251 	archive_string_init(&t);
252 	assertExactString(0, 0, NULL, t);
253 	archive_string_init(&u);
254 	assertExactString(0, 0, NULL, u);
255 	archive_string_init(&v);
256 	assertExactString(0, 0, NULL, v);
257 
258 	/* null target, null source */
259 	archive_string_copy(&t, &s);
260 	assertExactString(0, 0, NULL, s);
261 	assertExactString(0, EXTENT, "", t);
262 
263 	/* null target, empty source */
264 	archive_string_copy(&u, &t);
265 	assertExactString(0, EXTENT, "", t);
266 	assertExactString(0, EXTENT, "", u);
267 
268 	/* empty target, empty source */
269 	archive_string_copy(&u, &t);
270 	assertExactString(0, EXTENT, "", t);
271 	assertExactString(0, EXTENT, "", u);
272 
273 	/* null target, non-empty source */
274 	assert(NULL != archive_strcpy(&s, "snafubar"));
275 	assertExactString(8, EXTENT, "snafubar", s);
276 
277 	archive_string_copy(&v, &s);
278 	assertExactString(8, EXTENT, "snafubar", s);
279 	assertExactString(8, EXTENT, "snafubar", v);
280 
281 	/* empty target, non-empty source */
282 	assertExactString(0, EXTENT, "", t);
283 	archive_string_copy(&t, &s);
284 	assertExactString(8, EXTENT, "snafubar", s);
285 	assertExactString(8, EXTENT, "snafubar", t);
286 
287 	/* non-empty target, non-empty source */
288 	assert(NULL != archive_strcpy(&s, "fubar"));
289 	assertExactString(5, EXTENT, "fubar", s);
290 
291 	archive_string_copy(&t, &s);
292 	assertExactString(5, EXTENT, "fubar", s);
293 	assertExactString(5, EXTENT, "fubar", t);
294 
295 	archive_string_free(&v);
296 	archive_string_free(&u);
297 	archive_string_free(&t);
298 	archive_string_free(&s);
299 }
300 
301 static void
302 test_archive_string_sprintf(void)
303 {
304 	struct archive_string s;
305 #define S16 "0123456789abcdef"
306 #define S32 S16 S16
307 #define S64 S32 S32
308 #define S128 S64 S64
309 	const char *s32 = S32;
310 	const char *s33 = S32 "0";
311 	const char *s64 = S64;
312 	const char *s65 = S64 "0";
313 	const char *s128 = S128;
314 	const char *s129 = S128 "0";
315 #undef S16
316 #undef S32
317 #undef S64
318 #undef S128
319 
320 	archive_string_init(&s);
321 	assertExactString(0, 0, NULL, s);
322 
323 	archive_string_sprintf(&s, "%s", "");
324 	assertExactString(0, 2 * EXTENT, "", s);
325 
326 	archive_string_empty(&s);
327 	archive_string_sprintf(&s, "%s", s32);
328 	assertExactString(32, 2 * EXTENT, s32, s);
329 
330 	archive_string_empty(&s);
331 	archive_string_sprintf(&s, "%s", s33);
332 	assertExactString(33, 2 * EXTENT, s33, s);
333 
334 	archive_string_empty(&s);
335 	archive_string_sprintf(&s, "%s", s64);
336 	assertExactString(64, 4 * EXTENT, s64, s);
337 
338 	archive_string_empty(&s);
339 	archive_string_sprintf(&s, "%s", s65);
340 	assertExactString(65, 4 * EXTENT, s65, s);
341 
342 	archive_string_empty(&s);
343 	archive_string_sprintf(&s, "%s", s128);
344 	assertExactString(128, 8 * EXTENT, s128, s);
345 
346 	archive_string_empty(&s);
347 	archive_string_sprintf(&s, "%s", s129);
348 	assertExactString(129, 8 * EXTENT, s129, s);
349 
350 	archive_string_empty(&s);
351 	archive_string_sprintf(&s, "%d", 1234567890);
352 	assertExactString(10, 8 * EXTENT, "1234567890", s);
353 
354 	archive_string_free(&s);
355 }
356 
357 DEFINE_TEST(test_archive_string)
358 {
359 	test_archive_string_ensure();
360 	test_archive_strcat();
361 	test_archive_strappend_char();
362 	test_archive_strncat();
363 	test_archive_strncpy();
364 	test_archive_strcpy();
365 	test_archive_string_concat();
366 	test_archive_string_copy();
367 	test_archive_string_sprintf();
368 }
369 
370 static const char *strings[] =
371 {
372   "dir/path",
373   "dir/path2",
374   "dir/path3",
375   "dir/path4",
376   "dir/path5",
377   "dir/path6",
378   "dir/path7",
379   "dir/path8",
380   "dir/path9",
381   "dir/subdir/path",
382   "dir/subdir/path2",
383   "dir/subdir/path3",
384   "dir/subdir/path4",
385   "dir/subdir/path5",
386   "dir/subdir/path6",
387   "dir/subdir/path7",
388   "dir/subdir/path8",
389   "dir/subdir/path9",
390   "dir2/path",
391   "dir2/path2",
392   "dir2/path3",
393   "dir2/path4",
394   "dir2/path5",
395   "dir2/path6",
396   "dir2/path7",
397   "dir2/path8",
398   "dir2/path9",
399   NULL
400 };
401 
402 DEFINE_TEST(test_archive_string_sort)
403 {
404   unsigned int i, j, size;
405   char **test_strings, *tmp;
406 
407   srand((unsigned int)time(NULL));
408   size = sizeof(strings) / sizeof(char *);
409   assert((test_strings = (char **)calloc(1, sizeof(strings))) != NULL);
410   for (i = 0; i < (size - 1); i++)
411     assert((test_strings[i] = strdup(strings[i])) != NULL);
412 
413   /* Shuffle the test strings */
414   for (i = 0; i < (size - 1); i++)
415   {
416     j = rand() % ((size - 1) - i);
417     j += i;
418     tmp = test_strings[i];
419     test_strings[i] = test_strings[j];
420     test_strings[j] = tmp;
421   }
422 
423   /* Sort and test */
424   assertEqualInt(ARCHIVE_OK, archive_utility_string_sort(test_strings));
425   for (i = 0; i < (size - 1); i++)
426     assertEqualString(test_strings[i], strings[i]);
427 
428   for (i = 0; i < (size - 1); i++)
429     free(test_strings[i]);
430   free(test_strings);
431 }
432