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 
72 static void
73 test_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 
97 static void
98 test_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 
118 static void
119 test_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 
139 static void
140 test_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 
160 static void
161 test_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 
181 static void
182 test_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 
227 static void
228 test_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 
279 static void
280 test_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 
333 DEFINE_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