test_archive_string.c revision 302001
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
49static void
50test_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
72static void
73test_archive_strcat(void)
74{
75	struct archive_string s;
76
77	archive_string_init(&s);
78	assertExactString(0, 0, NULL, s);
79
80	/* null target, empty source */
81	assert(&s == archive_strcat(&s, ""));
82	assertExactString(0, EXTENT, "", s);
83
84	/* empty target, empty source */
85	assert(&s == archive_strcat(&s, ""));
86	assertExactString(0, EXTENT, "", s);
87
88	/* empty target, non-empty source */
89	assert(&s == archive_strcat(&s, "fubar"));
90	assertExactString(5, EXTENT, "fubar", s);
91
92	/* non-empty target, non-empty source */
93	assert(&s == archive_strcat(&s, "baz"));
94	assertExactString(8, EXTENT, "fubarbaz", s);
95}
96
97static void
98test_archive_strappend_char(void)
99{
100	struct archive_string s;
101
102	archive_string_init(&s);
103	assertExactString(0, 0, NULL, s);
104
105	/* null target */
106	archive_strappend_char(&s, 'X');
107	assertExactString(1, EXTENT, "X", s);
108
109	/* non-empty target */
110	archive_strappend_char(&s, 'Y');
111	assertExactString(2, EXTENT, "XY", s);
112}
113
114/* archive_strnXXX() tests focus on length handling.
115 * other behaviors are tested by proxy through archive_strXXX()
116 */
117
118static void
119test_archive_strncat(void)
120{
121	struct archive_string s;
122
123	archive_string_init(&s);
124	assertExactString(0, 0, NULL, s);
125
126	/* perfect length */
127	assert(&s == archive_strncat(&s, "snafu", 5));
128	assertExactString(5, EXTENT, "snafu", s);
129
130	/* short read */
131	assert(&s == archive_strncat(&s, "barbazqux", 3));
132	assertExactString(8, EXTENT, "snafubar", s);
133
134	/* long read is ok too! */
135	assert(&s == archive_strncat(&s, "snafu", 8));
136	assertExactString(13, EXTENT, "snafubarsnafu", s);
137}
138
139static void
140test_archive_strncpy(void)
141{
142	struct archive_string s;
143
144	archive_string_init(&s);
145	assertExactString(0, 0, NULL, s);
146
147	/* perfect length */
148	assert(&s == archive_strncpy(&s, "fubar", 5));
149	assertExactString(5, EXTENT, "fubar", s);
150
151	/* short read */
152	assert(&s == archive_strncpy(&s, "snafubar", 5));
153	assertExactString(5, EXTENT, "snafu", s);
154
155	/* long read is ok too! */
156	assert(&s == archive_strncpy(&s, "snafu", 8));
157	assertExactString(5, EXTENT, "snafu", s);
158}
159
160static void
161test_archive_strcpy(void)
162{
163	struct archive_string s;
164
165	archive_string_init(&s);
166	assertExactString(0, 0, NULL, s);
167
168	/* null target */
169	assert(&s == archive_strcpy(&s, "snafu"));
170	assertExactString(5, EXTENT, "snafu", s);
171
172	/* dirty target */
173	assert(&s == archive_strcpy(&s, "foo"));
174	assertExactString(3, EXTENT, "foo", s);
175
176	/* dirty target, empty source */
177	assert(&s == archive_strcpy(&s, ""));
178	assertExactString(0, EXTENT, "", s);
179}
180
181static void
182test_archive_string_concat(void)
183{
184	struct archive_string s, t, u, v;
185
186	archive_string_init(&s);
187	assertExactString(0, 0, NULL, s);
188	archive_string_init(&t);
189	assertExactString(0, 0, NULL, t);
190	archive_string_init(&u);
191	assertExactString(0, 0, NULL, u);
192	archive_string_init(&v);
193	assertExactString(0, 0, NULL, v);
194
195	/* null target, null source */
196	archive_string_concat(&t, &s);
197	assertExactString(0, 0, NULL, s);
198	assertExactString(0, EXTENT, "", t);
199
200	/* null target, empty source */
201	assert(&s == archive_strcpy(&s, ""));
202	archive_string_concat(&u, &s);
203	assertExactString(0, EXTENT, "", s);
204	assertExactString(0, EXTENT, "", u);
205
206	/* null target, non-empty source */
207	assert(&s == archive_strcpy(&s, "foo"));
208	archive_string_concat(&v, &s);
209	assertExactString(3, EXTENT, "foo", s);
210	assertExactString(3, EXTENT, "foo", v);
211
212	/* empty target, empty source */
213	assert(&s == archive_strcpy(&s, ""));
214	assert(&t == archive_strcpy(&t, ""));
215	archive_string_concat(&t, &s);
216	assertExactString(0, EXTENT, "", s);
217	assertExactString(0, EXTENT, "", t);
218
219	/* empty target, non-empty source */
220	assert(&s == archive_strcpy(&s, "snafu"));
221	assert(&t == archive_strcpy(&t, ""));
222	archive_string_concat(&t, &s);
223	assertExactString(5, EXTENT, "snafu", s);
224	assertExactString(5, EXTENT, "snafu", t);
225}
226
227static void
228test_archive_string_copy(void)
229{
230	struct archive_string s, t, u, v;
231
232	archive_string_init(&s);
233	assertExactString(0, 0, NULL, s);
234	archive_string_init(&t);
235	assertExactString(0, 0, NULL, t);
236	archive_string_init(&u);
237	assertExactString(0, 0, NULL, u);
238	archive_string_init(&v);
239	assertExactString(0, 0, NULL, v);
240
241	/* null target, null source */
242	archive_string_copy(&t, &s);
243	assertExactString(0, 0, NULL, s);
244	assertExactString(0, EXTENT, "", t);
245
246	/* null target, empty source */
247	archive_string_copy(&u, &t);
248	assertExactString(0, EXTENT, "", t);
249	assertExactString(0, EXTENT, "", u);
250
251	/* empty target, empty source */
252	archive_string_copy(&u, &t);
253	assertExactString(0, EXTENT, "", t);
254	assertExactString(0, EXTENT, "", u);
255
256	/* null target, non-empty source */
257	assert(NULL != archive_strcpy(&s, "snafubar"));
258	assertExactString(8, EXTENT, "snafubar", s);
259
260	archive_string_copy(&v, &s);
261	assertExactString(8, EXTENT, "snafubar", s);
262	assertExactString(8, EXTENT, "snafubar", v);
263
264	/* empty target, non-empty source */
265	assertExactString(0, EXTENT, "", t);
266	archive_string_copy(&t, &s);
267	assertExactString(8, EXTENT, "snafubar", s);
268	assertExactString(8, EXTENT, "snafubar", t);
269
270	/* non-empty target, non-empty source */
271	assert(NULL != archive_strcpy(&s, "fubar"));
272	assertExactString(5, EXTENT, "fubar", s);
273
274	archive_string_copy(&t, &s);
275	assertExactString(5, EXTENT, "fubar", s);
276	assertExactString(5, EXTENT, "fubar", t);
277}
278
279static void
280test_archive_string_sprintf(void)
281{
282	struct archive_string s;
283#define S16 "0123456789abcdef"
284#define S32 S16 S16
285#define S64 S32 S32
286#define S128 S64 S64
287	const char *s32 = S32;
288	const char *s33 = S32 "0";
289	const char *s64 = S64;
290	const char *s65 = S64 "0";
291	const char *s128 = S128;
292	const char *s129 = S128 "0";
293#undef S16
294#undef S32
295#undef S64
296#undef S128
297
298	archive_string_init(&s);
299	assertExactString(0, 0, NULL, s);
300
301	archive_string_sprintf(&s, "%s", "");
302	assertExactString(0, 2 * EXTENT, "", s);
303
304	archive_string_empty(&s);
305	archive_string_sprintf(&s, "%s", s32);
306	assertExactString(32, 2 * EXTENT, s32, s);
307
308	archive_string_empty(&s);
309	archive_string_sprintf(&s, "%s", s33);
310	assertExactString(33, 2 * EXTENT, s33, s);
311
312	archive_string_empty(&s);
313	archive_string_sprintf(&s, "%s", s64);
314	assertExactString(64, 4 * EXTENT, s64, s);
315
316	archive_string_empty(&s);
317	archive_string_sprintf(&s, "%s", s65);
318	assertExactString(65, 4 * EXTENT, s65, s);
319
320	archive_string_empty(&s);
321	archive_string_sprintf(&s, "%s", s128);
322	assertExactString(128, 8 * EXTENT, s128, s);
323
324	archive_string_empty(&s);
325	archive_string_sprintf(&s, "%s", s129);
326	assertExactString(129, 8 * EXTENT, s129, s);
327
328	archive_string_empty(&s);
329	archive_string_sprintf(&s, "%d", 1234567890);
330	assertExactString(10, 8 * EXTENT, "1234567890", s);
331}
332
333DEFINE_TEST(test_archive_string)
334{
335	test_archive_string_ensure();
336	test_archive_strcat();
337	test_archive_strappend_char();
338	test_archive_strncat();
339	test_archive_strncpy();
340	test_archive_strcpy();
341	test_archive_string_concat();
342	test_archive_string_copy();
343	test_archive_string_sprintf();
344}
345
346static const char *strings[] =
347{
348  "dir/path",
349  "dir/path2",
350  "dir/path3",
351  "dir/path4",
352  "dir/path5",
353  "dir/path6",
354  "dir/path7",
355  "dir/path8",
356  "dir/path9",
357  "dir/subdir/path",
358  "dir/subdir/path2",
359  "dir/subdir/path3",
360  "dir/subdir/path4",
361  "dir/subdir/path5",
362  "dir/subdir/path6",
363  "dir/subdir/path7",
364  "dir/subdir/path8",
365  "dir/subdir/path9",
366  "dir2/path",
367  "dir2/path2",
368  "dir2/path3",
369  "dir2/path4",
370  "dir2/path5",
371  "dir2/path6",
372  "dir2/path7",
373  "dir2/path8",
374  "dir2/path9",
375  NULL
376};
377
378DEFINE_TEST(test_archive_string_sort)
379{
380  unsigned int i, j, size;
381  char **test_strings, *tmp;
382
383  srand((unsigned int)time(NULL));
384  size = sizeof(strings) / sizeof(char *);
385  assert((test_strings = (char **)calloc(1, sizeof(strings))) != NULL);
386  for (i = 0; i < (size - 1); i++)
387    assert((test_strings[i] = strdup(strings[i])) != NULL);
388
389  /* Shuffle the test strings */
390  for (i = 0; i < (size - 1); i++)
391  {
392    j = rand() % ((size - 1) - i);
393    j += i;
394    tmp = test_strings[i];
395    test_strings[i] = test_strings[j];
396    test_strings[j] = tmp;
397  }
398
399  /* Sort and test */
400  assertEqualInt(ARCHIVE_OK, archive_utility_string_sort(test_strings));
401  for (i = 0; i < (size - 1); i++)
402    assertEqualString(test_strings[i], strings[i]);
403
404  for (i = 0; i < (size - 1); i++)
405    free(test_strings[i]);
406  free(test_strings);
407}
408