xref: /freebsd/contrib/libarchive/libarchive/test/test_archive_string.c (revision 8ccc0d235c226d84112561d453c49904398d085c)
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 
27 #define __LIBARCHIVE_TEST
28 #include "archive_string.h"
29 
30 #define EXTENT 32
31 
32 #define assertStringSizes(strlen, buflen, as) \
33 	assertEqualInt(strlen, (as).length); \
34 	assertEqualInt(buflen, (as).buffer_length);
35 
36 #define assertExactString(strlen, buflen, data, as) \
37 	do { \
38 		assertStringSizes(strlen, buflen, as); \
39 		assertEqualString(data, (as).s); \
40 	} while (0)
41 
42 #define assertNonNULLString(strlen, buflen, as) \
43 	do { \
44 		assertStringSizes(strlen, buflen, as); \
45 		assert(NULL != (as).s); \
46 	} while (0)
47 
48 static void
49 test_archive_string_ensure(void)
50 {
51 	struct archive_string s;
52 
53 	archive_string_init(&s);
54 	assertExactString(0, 0, NULL, s);
55 
56 	/* single-extent allocation */
57 	assert(&s == archive_string_ensure(&s, 5));
58 	assertNonNULLString(0, EXTENT, s);
59 
60 	/* what happens around extent boundaries? */
61 	assert(&s == archive_string_ensure(&s, EXTENT - 1));
62 	assertNonNULLString(0, EXTENT, s);
63 
64 	assert(&s == archive_string_ensure(&s, EXTENT));
65 	assertNonNULLString(0, EXTENT, s);
66 
67 	assert(&s == archive_string_ensure(&s, EXTENT + 1));
68 	assertNonNULLString(0, 2 * EXTENT, s);
69 
70 	archive_string_free(&s);
71 }
72 
73 static void
74 test_archive_strcat(void)
75 {
76 	struct archive_string s;
77 
78 	archive_string_init(&s);
79 	assertExactString(0, 0, NULL, s);
80 
81 	/* null target, empty source */
82 	assert(&s == archive_strcat(&s, ""));
83 	assertExactString(0, EXTENT, "", s);
84 
85 	/* empty target, empty source */
86 	assert(&s == archive_strcat(&s, ""));
87 	assertExactString(0, EXTENT, "", s);
88 
89 	/* empty target, non-empty source */
90 	assert(&s == archive_strcat(&s, "fubar"));
91 	assertExactString(5, EXTENT, "fubar", s);
92 
93 	/* non-empty target, non-empty source */
94 	assert(&s == archive_strcat(&s, "baz"));
95 	assertExactString(8, EXTENT, "fubarbaz", s);
96 
97 	archive_string_free(&s);
98 }
99 
100 static void
101 test_archive_strappend_char(void)
102 {
103 	struct archive_string s;
104 
105 	archive_string_init(&s);
106 	assertExactString(0, 0, NULL, s);
107 
108 	/* null target */
109 	archive_strappend_char(&s, 'X');
110 	assertExactString(1, EXTENT, "X", s);
111 
112 	/* non-empty target */
113 	archive_strappend_char(&s, 'Y');
114 	assertExactString(2, EXTENT, "XY", s);
115 
116 	archive_string_free(&s);
117 }
118 
119 /* archive_strnXXX() tests focus on length handling.
120  * other behaviors are tested by proxy through archive_strXXX()
121  */
122 
123 static void
124 test_archive_strncat(void)
125 {
126 	struct archive_string s;
127 
128 	archive_string_init(&s);
129 	assertExactString(0, 0, NULL, s);
130 
131 	/* perfect length */
132 	assert(&s == archive_strncat(&s, "snafu", 5));
133 	assertExactString(5, EXTENT, "snafu", s);
134 
135 	/* short read */
136 	assert(&s == archive_strncat(&s, "barbazqux", 3));
137 	assertExactString(8, EXTENT, "snafubar", s);
138 
139 	/* long read is ok too! */
140 	assert(&s == archive_strncat(&s, "snafu", 8));
141 	assertExactString(13, EXTENT, "snafubarsnafu", s);
142 
143 	archive_string_free(&s);
144 }
145 
146 static void
147 test_archive_strncpy(void)
148 {
149 	struct archive_string s;
150 
151 	archive_string_init(&s);
152 	assertExactString(0, 0, NULL, s);
153 
154 	/* perfect length */
155 	assert(&s == archive_strncpy(&s, "fubar", 5));
156 	assertExactString(5, EXTENT, "fubar", s);
157 
158 	/* short read */
159 	assert(&s == archive_strncpy(&s, "snafubar", 5));
160 	assertExactString(5, EXTENT, "snafu", s);
161 
162 	/* long read is ok too! */
163 	assert(&s == archive_strncpy(&s, "snafu", 8));
164 	assertExactString(5, EXTENT, "snafu", s);
165 
166 	archive_string_free(&s);
167 }
168 
169 static void
170 test_archive_strcpy(void)
171 {
172 	struct archive_string s;
173 
174 	archive_string_init(&s);
175 	assertExactString(0, 0, NULL, s);
176 
177 	/* null target */
178 	assert(&s == archive_strcpy(&s, "snafu"));
179 	assertExactString(5, EXTENT, "snafu", s);
180 
181 	/* dirty target */
182 	assert(&s == archive_strcpy(&s, "foo"));
183 	assertExactString(3, EXTENT, "foo", s);
184 
185 	/* dirty target, empty source */
186 	assert(&s == archive_strcpy(&s, ""));
187 	assertExactString(0, EXTENT, "", s);
188 
189 	archive_string_free(&s);
190 }
191 
192 static void
193 test_archive_string_concat(void)
194 {
195 	struct archive_string s, t, u, v;
196 
197 	archive_string_init(&s);
198 	assertExactString(0, 0, NULL, s);
199 	archive_string_init(&t);
200 	assertExactString(0, 0, NULL, t);
201 	archive_string_init(&u);
202 	assertExactString(0, 0, NULL, u);
203 	archive_string_init(&v);
204 	assertExactString(0, 0, NULL, v);
205 
206 	/* null target, null source */
207 	archive_string_concat(&t, &s);
208 	assertExactString(0, 0, NULL, s);
209 	assertExactString(0, EXTENT, "", t);
210 
211 	/* null target, empty source */
212 	assert(&s == archive_strcpy(&s, ""));
213 	archive_string_concat(&u, &s);
214 	assertExactString(0, EXTENT, "", s);
215 	assertExactString(0, EXTENT, "", u);
216 
217 	/* null target, non-empty source */
218 	assert(&s == archive_strcpy(&s, "foo"));
219 	archive_string_concat(&v, &s);
220 	assertExactString(3, EXTENT, "foo", s);
221 	assertExactString(3, EXTENT, "foo", v);
222 
223 	/* empty target, empty source */
224 	assert(&s == archive_strcpy(&s, ""));
225 	assert(&t == archive_strcpy(&t, ""));
226 	archive_string_concat(&t, &s);
227 	assertExactString(0, EXTENT, "", s);
228 	assertExactString(0, EXTENT, "", t);
229 
230 	/* empty target, non-empty source */
231 	assert(&s == archive_strcpy(&s, "snafu"));
232 	assert(&t == archive_strcpy(&t, ""));
233 	archive_string_concat(&t, &s);
234 	assertExactString(5, EXTENT, "snafu", s);
235 	assertExactString(5, EXTENT, "snafu", t);
236 
237 	archive_string_free(&v);
238 	archive_string_free(&u);
239 	archive_string_free(&t);
240 	archive_string_free(&s);
241 }
242 
243 static void
244 test_archive_string_copy(void)
245 {
246 	struct archive_string s, t, u, v;
247 
248 	archive_string_init(&s);
249 	assertExactString(0, 0, NULL, s);
250 	archive_string_init(&t);
251 	assertExactString(0, 0, NULL, t);
252 	archive_string_init(&u);
253 	assertExactString(0, 0, NULL, u);
254 	archive_string_init(&v);
255 	assertExactString(0, 0, NULL, v);
256 
257 	/* null target, null source */
258 	archive_string_copy(&t, &s);
259 	assertExactString(0, 0, NULL, s);
260 	assertExactString(0, EXTENT, "", t);
261 
262 	/* null target, empty source */
263 	archive_string_copy(&u, &t);
264 	assertExactString(0, EXTENT, "", t);
265 	assertExactString(0, EXTENT, "", u);
266 
267 	/* empty target, empty source */
268 	archive_string_copy(&u, &t);
269 	assertExactString(0, EXTENT, "", t);
270 	assertExactString(0, EXTENT, "", u);
271 
272 	/* null target, non-empty source */
273 	assert(NULL != archive_strcpy(&s, "snafubar"));
274 	assertExactString(8, EXTENT, "snafubar", s);
275 
276 	archive_string_copy(&v, &s);
277 	assertExactString(8, EXTENT, "snafubar", s);
278 	assertExactString(8, EXTENT, "snafubar", v);
279 
280 	/* empty target, non-empty source */
281 	assertExactString(0, EXTENT, "", t);
282 	archive_string_copy(&t, &s);
283 	assertExactString(8, EXTENT, "snafubar", s);
284 	assertExactString(8, EXTENT, "snafubar", t);
285 
286 	/* non-empty target, non-empty source */
287 	assert(NULL != archive_strcpy(&s, "fubar"));
288 	assertExactString(5, EXTENT, "fubar", s);
289 
290 	archive_string_copy(&t, &s);
291 	assertExactString(5, EXTENT, "fubar", s);
292 	assertExactString(5, EXTENT, "fubar", t);
293 
294 	archive_string_free(&v);
295 	archive_string_free(&u);
296 	archive_string_free(&t);
297 	archive_string_free(&s);
298 }
299 
300 static void
301 test_archive_string_sprintf(void)
302 {
303 	struct archive_string s;
304 #define S16 "0123456789abcdef"
305 #define S32 S16 S16
306 #define S64 S32 S32
307 #define S128 S64 S64
308 	const char *s32 = S32;
309 	const char *s33 = S32 "0";
310 	const char *s64 = S64;
311 	const char *s65 = S64 "0";
312 	const char *s128 = S128;
313 	const char *s129 = S128 "0";
314 #undef S16
315 #undef S32
316 #undef S64
317 #undef S128
318 
319 	archive_string_init(&s);
320 	assertExactString(0, 0, NULL, s);
321 
322 	archive_string_sprintf(&s, "%s", "");
323 	assertExactString(0, 2 * EXTENT, "", s);
324 
325 	archive_string_empty(&s);
326 	archive_string_sprintf(&s, "%s", s32);
327 	assertExactString(32, 2 * EXTENT, s32, s);
328 
329 	archive_string_empty(&s);
330 	archive_string_sprintf(&s, "%s", s33);
331 	assertExactString(33, 2 * EXTENT, s33, s);
332 
333 	archive_string_empty(&s);
334 	archive_string_sprintf(&s, "%s", s64);
335 	assertExactString(64, 4 * EXTENT, s64, s);
336 
337 	archive_string_empty(&s);
338 	archive_string_sprintf(&s, "%s", s65);
339 	assertExactString(65, 4 * EXTENT, s65, s);
340 
341 	archive_string_empty(&s);
342 	archive_string_sprintf(&s, "%s", s128);
343 	assertExactString(128, 8 * EXTENT, s128, s);
344 
345 	archive_string_empty(&s);
346 	archive_string_sprintf(&s, "%s", s129);
347 	assertExactString(129, 8 * EXTENT, s129, s);
348 
349 	archive_string_empty(&s);
350 	archive_string_sprintf(&s, "%d", 1234567890);
351 	assertExactString(10, 8 * EXTENT, "1234567890", s);
352 
353 	archive_string_free(&s);
354 }
355 
356 static void
357 test_archive_string_dirname(void)
358 {
359 	static struct pair { const char *str, *exp; } pairs[] = {
360 		{ "",		"." },
361 		{ "/",		"/" },
362 		{ "//",		"/" },
363 		{ "///",	"/" },
364 		{ "./",		"." },
365 		{ ".",		"." },
366 		{ "..",		"." },
367 		{ "foo",	"." },
368 		{ "foo/",	"." },
369 		{ "foo//",	"." },
370 		{ "foo/bar",	"foo" },
371 		{ "foo/bar/",	"foo" },
372 		{ "foo/bar//",	"foo" },
373 		{ "foo//bar",	"foo" },
374 		{ "foo//bar/",	"foo" },
375 		{ "foo//bar//",	"foo" },
376 		{ "/foo",	"/" },
377 		{ "//foo",	"/" },
378 		{ "//foo/",	"/" },
379 		{ "//foo//",	"/" },
380 		{ 0 },
381 	};
382 	struct pair *pair;
383 	struct archive_string s;
384 
385 	archive_string_init(&s);
386 	for (pair = pairs; pair->str; pair++) {
387 		archive_strcpy(&s, pair->str);
388 		archive_string_dirname(&s);
389 		assertEqualString(pair->exp, s.s);
390 	}
391 }
392 
393 DEFINE_TEST(test_archive_string)
394 {
395 	test_archive_string_ensure();
396 	test_archive_strcat();
397 	test_archive_strappend_char();
398 	test_archive_strncat();
399 	test_archive_strncpy();
400 	test_archive_strcpy();
401 	test_archive_string_concat();
402 	test_archive_string_copy();
403 	test_archive_string_sprintf();
404 	test_archive_string_dirname();
405 }
406 
407 static const char *strings[] =
408 {
409   "dir/path",
410   "dir/path2",
411   "dir/path3",
412   "dir/path4",
413   "dir/path5",
414   "dir/path6",
415   "dir/path7",
416   "dir/path8",
417   "dir/path9",
418   "dir/subdir/path",
419   "dir/subdir/path2",
420   "dir/subdir/path3",
421   "dir/subdir/path4",
422   "dir/subdir/path5",
423   "dir/subdir/path6",
424   "dir/subdir/path7",
425   "dir/subdir/path8",
426   "dir/subdir/path9",
427   "dir2/path",
428   "dir2/path2",
429   "dir2/path3",
430   "dir2/path4",
431   "dir2/path5",
432   "dir2/path6",
433   "dir2/path7",
434   "dir2/path8",
435   "dir2/path9",
436   NULL
437 };
438 
439 DEFINE_TEST(test_archive_string_sort)
440 {
441   unsigned int i, j, size;
442   char **test_strings, *tmp;
443 
444   srand((unsigned int)time(NULL));
445   size = sizeof(strings) / sizeof(char *);
446   assert((test_strings = calloc(size, sizeof(char *))) != NULL);
447   for (i = 0; i < (size - 1); i++)
448     assert((test_strings[i] = strdup(strings[i])) != NULL);
449 
450   /* Shuffle the test strings */
451   for (i = 0; i < (size - 1); i++)
452   {
453     j = rand() % ((size - 1) - i);
454     j += i;
455     tmp = test_strings[i];
456     test_strings[i] = test_strings[j];
457     test_strings[j] = tmp;
458   }
459 
460   /* Sort and test */
461   assertEqualInt(ARCHIVE_OK, archive_utility_string_sort(test_strings));
462   for (i = 0; i < (size - 1); i++)
463     assertEqualString(test_strings[i], strings[i]);
464 
465   for (i = 0; i < (size - 1); i++)
466     free(test_strings[i]);
467   free(test_strings);
468 }
469