1 /*-
2  * Copyright (c) 2012 Michihiro NAKAJIMA
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 
26 #include "test.h"
27 __FBSDID("$FreeBSD$");
28 
29 static void
30 test_exclusion_mbs(void)
31 {
32 	struct archive_entry *ae;
33 	struct archive *m;
34 
35 	if (!assert((m = archive_match_new()) != NULL))
36 		return;
37 	if (!assert((ae = archive_entry_new()) != NULL)) {
38 		archive_match_free(m);
39 		return;
40 	}
41 
42 	/* Test for pattern "^aa*" */
43 	assertEqualIntA(m, 0, archive_match_exclude_pattern(m, "^aa*"));
44 
45 	/* Test with 'aa1234', which should be excluded. */
46 	archive_entry_copy_pathname(ae, "aa1234");
47 	failure("'aa1234' should be excluded");
48 	assertEqualInt(1, archive_match_path_excluded(m, ae));
49 	assertEqualInt(1, archive_match_excluded(m, ae));
50 	archive_entry_clear(ae);
51 	archive_entry_copy_pathname_w(ae, L"aa1234");
52 	failure("'aa1234' should be excluded");
53 	assertEqualInt(1, archive_match_path_excluded(m, ae));
54 	assertEqualInt(1, archive_match_excluded(m, ae));
55 
56 	/* Test with 'a1234', which should not be excluded. */
57 	archive_entry_copy_pathname(ae, "a1234");
58 	failure("'a1234' should not be excluded");
59 	assertEqualInt(0, archive_match_path_excluded(m, ae));
60 	assertEqualInt(0, archive_match_excluded(m, ae));
61 	archive_entry_clear(ae);
62 	archive_entry_copy_pathname_w(ae, L"a1234");
63 	failure("'a1234' should not be excluded");
64 	assertEqualInt(0, archive_match_path_excluded(m, ae));
65 	assertEqualInt(0, archive_match_excluded(m, ae));
66 
67 	/* Clean up. */
68 	archive_entry_free(ae);
69 	archive_match_free(m);
70 }
71 
72 static void
73 test_exclusion_wcs(void)
74 {
75 	struct archive_entry *ae;
76 	struct archive *m;
77 
78 	if (!assert((m = archive_match_new()) != NULL))
79 		return;
80 	if (!assert((ae = archive_entry_new()) != NULL)) {
81 		archive_match_free(m);
82 		return;
83 	}
84 
85 	/* Test for pattern "^aa*" */
86 	assertEqualIntA(m, 0, archive_match_exclude_pattern_w(m, L"^aa*"));
87 
88 	/* Test with 'aa1234', which should be excluded. */
89 	archive_entry_copy_pathname(ae, "aa1234");
90 	failure("'aa1234' should be excluded");
91 	assertEqualInt(1, archive_match_path_excluded(m, ae));
92 	assertEqualInt(1, archive_match_excluded(m, ae));
93 	archive_entry_clear(ae);
94 	archive_entry_copy_pathname_w(ae, L"aa1234");
95 	failure("'aa1234' should be excluded");
96 	assertEqualInt(1, archive_match_path_excluded(m, ae));
97 	assertEqualInt(1, archive_match_excluded(m, ae));
98 
99 	/* Test with 'a1234', which should not be excluded. */
100 	archive_entry_copy_pathname(ae, "a1234");
101 	failure("'a1234' should not be excluded");
102 	assertEqualInt(0, archive_match_path_excluded(m, ae));
103 	assertEqualInt(0, archive_match_excluded(m, ae));
104 	archive_entry_clear(ae);
105 	archive_entry_copy_pathname_w(ae, L"a1234");
106 	failure("'a1234' should not be excluded");
107 	assertEqualInt(0, archive_match_path_excluded(m, ae));
108 	assertEqualInt(0, archive_match_excluded(m, ae));
109 
110 	/* Clean up. */
111 	archive_entry_free(ae);
112 	archive_match_free(m);
113 }
114 
115 static void
116 exclusion_from_file(struct archive *m)
117 {
118 	struct archive_entry *ae;
119 
120 	if (!assert((ae = archive_entry_new()) != NULL)) {
121 		archive_match_free(m);
122 		return;
123 	}
124 
125 	/* Test with 'first', which should not be excluded. */
126 	archive_entry_copy_pathname(ae, "first");
127 	failure("'first' should not be excluded");
128 	assertEqualInt(0, archive_match_path_excluded(m, ae));
129 	assertEqualInt(0, archive_match_excluded(m, ae));
130 	archive_entry_clear(ae);
131 	archive_entry_copy_pathname_w(ae, L"first");
132 	failure("'first' should not be excluded");
133 	assertEqualInt(0, archive_match_path_excluded(m, ae));
134 	assertEqualInt(0, archive_match_excluded(m, ae));
135 
136 	/* Test with 'second', which should be excluded. */
137 	archive_entry_copy_pathname(ae, "second");
138 	failure("'second' should be excluded");
139 	assertEqualInt(1, archive_match_path_excluded(m, ae));
140 	assertEqualInt(1, archive_match_excluded(m, ae));
141 	archive_entry_clear(ae);
142 	archive_entry_copy_pathname_w(ae, L"second");
143 	failure("'second' should be excluded");
144 	assertEqualInt(1, archive_match_path_excluded(m, ae));
145 	assertEqualInt(1, archive_match_excluded(m, ae));
146 
147 	/* Test with 'third', which should not be excluded. */
148 	archive_entry_copy_pathname(ae, "third");
149 	failure("'third' should not be excluded");
150 	assertEqualInt(0, archive_match_path_excluded(m, ae));
151 	assertEqualInt(0, archive_match_excluded(m, ae));
152 	archive_entry_clear(ae);
153 	archive_entry_copy_pathname_w(ae, L"third");
154 	failure("'third' should not be excluded");
155 	assertEqualInt(0, archive_match_path_excluded(m, ae));
156 	assertEqualInt(0, archive_match_excluded(m, ae));
157 
158 	/* Test with 'four', which should be excluded. */
159 	archive_entry_copy_pathname(ae, "four");
160 	failure("'four' should be excluded");
161 	assertEqualInt(1, archive_match_path_excluded(m, ae));
162 	assertEqualInt(1, archive_match_excluded(m, ae));
163 	archive_entry_clear(ae);
164 	archive_entry_copy_pathname_w(ae, L"four");
165 	failure("'four' should be excluded");
166 	assertEqualInt(1, archive_match_path_excluded(m, ae));
167 	assertEqualInt(1, archive_match_excluded(m, ae));
168 
169 	/* Clean up. */
170 	archive_entry_free(ae);
171 }
172 
173 static void
174 test_exclusion_from_file_mbs(void)
175 {
176 	struct archive *m;
177 
178 	/* Test1: read exclusion patterns from file */
179 	if (!assert((m = archive_match_new()) != NULL))
180 		return;
181 	assertEqualIntA(m, 0,
182 	    archive_match_exclude_pattern_from_file(m, "exclusion", 0));
183 	exclusion_from_file(m);
184 	/* Clean up. */
185 	archive_match_free(m);
186 
187 	/* Test2: read exclusion patterns in a null separator from file */
188 	if (!assert((m = archive_match_new()) != NULL))
189 		return;
190 	/* Test for pattern reading from file */
191 	assertEqualIntA(m, 0,
192 	    archive_match_exclude_pattern_from_file(m, "exclusion_null", 1));
193 	exclusion_from_file(m);
194 	/* Clean up. */
195 	archive_match_free(m);
196 }
197 
198 static void
199 test_exclusion_from_file_wcs(void)
200 {
201 	struct archive *m;
202 
203 	/* Test1: read exclusion patterns from file */
204 	if (!assert((m = archive_match_new()) != NULL))
205 		return;
206 	assertEqualIntA(m, 0,
207 	    archive_match_exclude_pattern_from_file_w(m, L"exclusion", 0));
208 	exclusion_from_file(m);
209 	/* Clean up. */
210 	archive_match_free(m);
211 
212 	/* Test2: read exclusion patterns in a null separator from file */
213 	if (!assert((m = archive_match_new()) != NULL))
214 		return;
215 	/* Test for pattern reading from file */
216 	assertEqualIntA(m, 0,
217 	    archive_match_exclude_pattern_from_file_w(m, L"exclusion_null", 1));
218 	exclusion_from_file(m);
219 	/* Clean up. */
220 	archive_match_free(m);
221 }
222 
223 static void
224 test_inclusion_mbs(void)
225 {
226 	struct archive_entry *ae;
227 	struct archive *m;
228 	const char *mp;
229 
230 	if (!assert((m = archive_match_new()) != NULL))
231 		return;
232 	if (!assert((ae = archive_entry_new()) != NULL)) {
233 		archive_match_free(m);
234 		return;
235 	}
236 
237 	/* Test for pattern "^aa*" */
238 	assertEqualIntA(m, 0, archive_match_include_pattern(m, "^aa*"));
239 
240 	/* Test with 'aa1234', which should not be excluded. */
241 	archive_entry_copy_pathname(ae, "aa1234");
242 	failure("'aa1234' should not be excluded");
243 	assertEqualInt(0, archive_match_path_excluded(m, ae));
244 	assertEqualInt(0, archive_match_excluded(m, ae));
245 	archive_entry_clear(ae);
246 	archive_entry_copy_pathname_w(ae, L"aa1234");
247 	failure("'aa1234' should not be excluded");
248 	assertEqualInt(0, archive_match_path_excluded(m, ae));
249 	assertEqualInt(0, archive_match_excluded(m, ae));
250 
251 	/* Test with 'a1234', which should be excluded. */
252 	archive_entry_copy_pathname(ae, "a1234");
253 	failure("'a1234' should be excluded");
254 	assertEqualInt(1, archive_match_path_excluded(m, ae));
255 	assertEqualInt(1, archive_match_excluded(m, ae));
256 	archive_entry_clear(ae);
257 	archive_entry_copy_pathname_w(ae, L"a1234");
258 	failure("'a1234' should be excluded");
259 	assertEqualInt(1, archive_match_path_excluded(m, ae));
260 	assertEqualInt(1, archive_match_excluded(m, ae));
261 
262 	/* Verify unmatched_inclusions. */
263 	assertEqualInt(0, archive_match_path_unmatched_inclusions(m));
264 	assertEqualIntA(m, ARCHIVE_EOF,
265 	    archive_match_path_unmatched_inclusions_next(m, &mp));
266 
267 	/* Clean up. */
268 	archive_entry_free(ae);
269 	archive_match_free(m);
270 }
271 
272 static void
273 test_inclusion_wcs(void)
274 {
275 	struct archive_entry *ae;
276 	struct archive *m;
277 	const char *mp;
278 
279 	if (!assert((m = archive_match_new()) != NULL))
280 		return;
281 	if (!assert((ae = archive_entry_new()) != NULL)) {
282 		archive_match_free(m);
283 		return;
284 	}
285 
286 	/* Test for pattern "^aa*" */
287 	assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*"));
288 
289 	/* Test with 'aa1234', which should not be excluded. */
290 	archive_entry_copy_pathname(ae, "aa1234");
291 	failure("'aa1234' should not be excluded");
292 	assertEqualInt(0, archive_match_path_excluded(m, ae));
293 	assertEqualInt(0, archive_match_excluded(m, ae));
294 	archive_entry_clear(ae);
295 	archive_entry_copy_pathname_w(ae, L"aa1234");
296 	failure("'aa1234' should not be excluded");
297 	assertEqualInt(0, archive_match_path_excluded(m, ae));
298 	assertEqualInt(0, archive_match_excluded(m, ae));
299 
300 	/* Test with 'a1234', which should be excluded. */
301 	archive_entry_copy_pathname(ae, "a1234");
302 	failure("'a1234' should be excluded");
303 	assertEqualInt(1, archive_match_path_excluded(m, ae));
304 	assertEqualInt(1, archive_match_excluded(m, ae));
305 	archive_entry_clear(ae);
306 	archive_entry_copy_pathname_w(ae, L"a1234");
307 	failure("'a1234' should be excluded");
308 	assertEqualInt(1, archive_match_path_excluded(m, ae));
309 	assertEqualInt(1, archive_match_excluded(m, ae));
310 
311 	/* Verify unmatched_inclusions. */
312 	assertEqualInt(0, archive_match_path_unmatched_inclusions(m));
313 	assertEqualIntA(m, ARCHIVE_EOF,
314 	    archive_match_path_unmatched_inclusions_next(m, &mp));
315 
316 	/* Clean up. */
317 	archive_entry_free(ae);
318 	archive_match_free(m);
319 }
320 
321 static void
322 test_inclusion_from_file_mbs(void)
323 {
324 	struct archive *m;
325 
326 	/* Test1: read inclusion patterns from file */
327 	if (!assert((m = archive_match_new()) != NULL))
328 		return;
329 	assertEqualIntA(m, 0,
330 	    archive_match_include_pattern_from_file(m, "inclusion", 0));
331 	exclusion_from_file(m);
332 	/* Clean up. */
333 	archive_match_free(m);
334 
335 	/* Test2: read inclusion patterns in a null separator from file */
336 	if (!assert((m = archive_match_new()) != NULL))
337 		return;
338 	assertEqualIntA(m, 0,
339 	    archive_match_include_pattern_from_file(m, "inclusion_null", 1));
340 	exclusion_from_file(m);
341 	/* Clean up. */
342 	archive_match_free(m);
343 }
344 
345 static void
346 test_inclusion_from_file_wcs(void)
347 {
348 	struct archive *m;
349 
350 	/* Test1: read inclusion patterns from file */
351 	if (!assert((m = archive_match_new()) != NULL))
352 		return;
353 	/* Test for pattern reading from file */
354 	assertEqualIntA(m, 0,
355 	    archive_match_include_pattern_from_file_w(m, L"inclusion", 0));
356 	exclusion_from_file(m);
357 	/* Clean up. */
358 	archive_match_free(m);
359 
360 	/* Test2: read inclusion patterns in a null separator from file */
361 	if (!assert((m = archive_match_new()) != NULL))
362 		return;
363 	/* Test for pattern reading from file */
364 	assertEqualIntA(m, 0,
365 	    archive_match_include_pattern_from_file_w(m, L"inclusion_null", 1));
366 	exclusion_from_file(m);
367 	/* Clean up. */
368 	archive_match_free(m);
369 }
370 
371 static void
372 test_exclusion_and_inclusion(void)
373 {
374 	struct archive_entry *ae;
375 	struct archive *m;
376 	const char *mp;
377 	const wchar_t *wp;
378 
379 	if (!assert((m = archive_match_new()) != NULL))
380 		return;
381 	if (!assert((ae = archive_entry_new()) != NULL)) {
382 		archive_match_free(m);
383 		return;
384 	}
385 
386 	assertEqualIntA(m, 0, archive_match_exclude_pattern(m, "^aaa*"));
387 	assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*"));
388 	assertEqualIntA(m, 0, archive_match_include_pattern(m, "^a1*"));
389 
390 	/* Test with 'aa1234', which should not be excluded. */
391 	archive_entry_copy_pathname(ae, "aa1234");
392 	failure("'aa1234' should not be excluded");
393 	assertEqualInt(0, archive_match_path_excluded(m, ae));
394 	assertEqualInt(0, archive_match_excluded(m, ae));
395 	archive_entry_clear(ae);
396 	archive_entry_copy_pathname_w(ae, L"aa1234");
397 	failure("'aa1234' should not be excluded");
398 	assertEqualInt(0, archive_match_path_excluded(m, ae));
399 	assertEqualInt(0, archive_match_excluded(m, ae));
400 
401 	/* Test with 'aaa1234', which should be excluded. */
402 	archive_entry_copy_pathname(ae, "aaa1234");
403 	failure("'aaa1234' should be excluded");
404 	assertEqualInt(1, archive_match_path_excluded(m, ae));
405 	assertEqualInt(1, archive_match_excluded(m, ae));
406 	archive_entry_clear(ae);
407 	archive_entry_copy_pathname_w(ae, L"aaa1234");
408 	failure("'aaa1234' should be excluded");
409 	assertEqualInt(1, archive_match_path_excluded(m, ae));
410 	assertEqualInt(1, archive_match_excluded(m, ae));
411 
412 	/* Verify unmatched_inclusions. */
413 	assertEqualInt(1, archive_match_path_unmatched_inclusions(m));
414 	/* Verify unmatched inclusion patterns. */
415 	assertEqualIntA(m, ARCHIVE_OK,
416 	    archive_match_path_unmatched_inclusions_next(m, &mp));
417 	assertEqualString("^a1*", mp);
418 	assertEqualIntA(m, ARCHIVE_EOF,
419 	    archive_match_path_unmatched_inclusions_next(m, &mp));
420 	/* Verify unmatched inclusion patterns again in Wide-Char. */
421 	assertEqualIntA(m, ARCHIVE_OK,
422 	    archive_match_path_unmatched_inclusions_next_w(m, &wp));
423 	assertEqualWString(L"^a1*", wp);
424 	assertEqualIntA(m, ARCHIVE_EOF,
425 	    archive_match_path_unmatched_inclusions_next_w(m, &wp));
426 
427 	/* Clean up. */
428 	archive_entry_free(ae);
429 	archive_match_free(m);
430 }
431 
432 DEFINE_TEST(test_archive_match_path)
433 {
434 	/* Make exclusion sample files which contain exclusion patterns. */
435 	assertMakeFile("exclusion", 0666, "second\nfour\n");
436 	assertMakeBinFile("exclusion_null", 0666, 12, "second\0four\0");
437 	/* Make inclusion sample files which contain inclusion patterns. */
438 	assertMakeFile("inclusion", 0666, "first\nthird\n");
439 	assertMakeBinFile("inclusion_null", 0666, 12, "first\0third\0");
440 
441 	test_exclusion_mbs();
442 	test_exclusion_wcs();
443 	test_exclusion_from_file_mbs();
444 	test_exclusion_from_file_wcs();
445 	test_inclusion_mbs();
446 	test_inclusion_wcs();
447 	test_inclusion_from_file_mbs();
448 	test_inclusion_from_file_wcs();
449 	test_exclusion_and_inclusion();
450 }
451