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
test_archive_string_ensure(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
test_archive_strcat(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
test_archive_strappend_char(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
test_archive_strncat(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
test_archive_strncpy(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
test_archive_strcpy(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
test_archive_string_concat(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
test_archive_string_copy(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
test_archive_string_sprintf(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
test_archive_string_dirname(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
DEFINE_TEST(test_archive_string)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
DEFINE_TEST(test_archive_string_sort)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