test_archive_pathmatch.c revision 238856
159769Sgrog/*-
259769Sgrog * Copyright (c) 2003-2007 Tim Kientzle
324424Swosch * All rights reserved.
424424Swosch *
524424Swosch * Redistribution and use in source and binary forms, with or without
624424Swosch * modification, are permitted provided that the following conditions
724424Swosch * are met:
824424Swosch * 1. Redistributions of source code must retain the above copyright
924424Swosch *    notice, this list of conditions and the following disclaimer.
1024424Swosch * 2. Redistributions in binary form must reproduce the above copyright
1124424Swosch *    notice, this list of conditions and the following disclaimer in the
1224424Swosch *    documentation and/or other materials provided with the distribution.
1324424Swosch *
1424424Swosch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
1542704Swosch * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1642704Swosch * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1742704Swosch * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
1824424Swosch * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1942704Swosch * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2042704Swosch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2142704Swosch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2242704Swosch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2342704Swosch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2442704Swosch */
2542704Swosch#include "test.h"
2642704Swosch__FBSDID("$FreeBSD$");
2742704Swosch
28195044Simp#define __LIBARCHIVE_TEST
2942704Swosch#include "archive_pathmatch.h"
3059769Sgrog
3159769Sgrog/*
3259769Sgrog * Verify that the pattern matcher implements the wildcard logic specified
3359769Sgrog * in SUSv2 for the cpio command.  This is essentially the
3459769Sgrog * shell glob syntax:
3559769Sgrog *   * - matches any sequence of chars, including '/'
3659769Sgrog *   ? - matches any single char, including '/'
3759769Sgrog *   [...] - matches any of a set of chars, '-' specifies a range,
3859769Sgrog *        initial '!' is undefined
3924424Swosch *
4042704Swosch * The specification in SUSv2 is a bit incomplete, I assume the following:
4124424Swosch *   Trailing '-' in [...] is not special.
4242704Swosch *
4324424Swosch * TODO: Figure out if there's a good way to extend this to handle
4442704Swosch * Windows paths that use '\' as a path separator.  <sigh>
4524424Swosch */
4624424Swosch
4724424SwoschDEFINE_TEST(test_archive_pathmatch)
4842704Swosch{
4925031Swosch	assertEqualInt(1, archive_pathmatch("a/b/c", "a/b/c", 0));
5059156Swosch	assertEqualInt(0, archive_pathmatch("a/b/", "a/b/c", 0));
5125031Swosch	assertEqualInt(0, archive_pathmatch("a/b", "a/b/c", 0));
5225031Swosch	assertEqualInt(0, archive_pathmatch("a/b/c", "a/b/", 0));
5324424Swosch	assertEqualInt(0, archive_pathmatch("a/b/c", "a/b", 0));
5424424Swosch
5524424Swosch	/* Empty pattern only matches empty string. */
5624424Swosch	assertEqualInt(1, archive_pathmatch("","", 0));
5771231Sitojun	assertEqualInt(0, archive_pathmatch("","a", 0));
5824424Swosch	assertEqualInt(1, archive_pathmatch("*","", 0));
5971231Sitojun	assertEqualInt(1, archive_pathmatch("*","a", 0));
6025031Swosch	assertEqualInt(1, archive_pathmatch("*","abcd", 0));
6171231Sitojun	/* SUSv2: * matches / */
6224424Swosch	assertEqualInt(1, archive_pathmatch("*","abcd/efgh/ijkl", 0));
6325031Swosch	assertEqualInt(1, archive_pathmatch("abcd*efgh/ijkl","abcd/efgh/ijkl", 0));
6425031Swosch	assertEqualInt(1, archive_pathmatch("abcd***efgh/ijkl","abcd/efgh/ijkl", 0));
6571231Sitojun	assertEqualInt(1, archive_pathmatch("abcd***/efgh/ijkl","abcd/efgh/ijkl", 0));
6625031Swosch	assertEqualInt(0, archive_pathmatch("?", "", 0));
6771231Sitojun	assertEqualInt(0, archive_pathmatch("?", "\0", 0));
6870110Swosch	assertEqualInt(1, archive_pathmatch("?", "a", 0));
6970110Swosch	assertEqualInt(0, archive_pathmatch("?", "ab", 0));
7070110Swosch	assertEqualInt(1, archive_pathmatch("?", ".", 0));
7170110Swosch	assertEqualInt(1, archive_pathmatch("?", "?", 0));
7270110Swosch	assertEqualInt(1, archive_pathmatch("a", "a", 0));
7370110Swosch	assertEqualInt(0, archive_pathmatch("a", "ab", 0));
7470110Swosch	assertEqualInt(0, archive_pathmatch("a", "ab", 0));
7570110Swosch	assertEqualInt(1, archive_pathmatch("a?c", "abc", 0));
7670110Swosch	/* SUSv2: ? matches / */
7770110Swosch	assertEqualInt(1, archive_pathmatch("a?c", "a/c", 0));
7870110Swosch	assertEqualInt(1, archive_pathmatch("a?*c*", "a/c", 0));
7980675Sasmodai	assertEqualInt(1, archive_pathmatch("*a*", "a/c", 0));
8080675Sasmodai	assertEqualInt(1, archive_pathmatch("*a*", "/a/c", 0));
8180675Sasmodai	assertEqualInt(1, archive_pathmatch("*a*", "defaaaaaaa", 0));
8280675Sasmodai	assertEqualInt(0, archive_pathmatch("a*", "defghi", 0));
8380675Sasmodai	assertEqualInt(0, archive_pathmatch("*a*", "defghi", 0));
8480675Sasmodai
8580675Sasmodai	/* Character classes */
8680675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[def", "abc[def", 0));
8780675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[def]", "abc[def", 0));
8880675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[def", "abcd", 0));
8980675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[def]", "abcd", 0));
9080675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[def]", "abce", 0));
9180675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[def]", "abcf", 0));
9280675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[def]", "abcg", 0));
9380675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d*f]", "abcd", 0));
9480675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d*f]", "abc*", 0));
9580675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d*f]", "abcdefghi", 0));
9680675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d*", "abcdefghi", 0));
9780675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d*", "abc[defghi", 0));
9880675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-f]", "abcd", 0));
9980675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-f]", "abce", 0));
10080675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-f]", "abcf", 0));
10180675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d-f]", "abcg", 0));
10280675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abca", 0));
10380675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcd", 0));
10480675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abce", 0));
10580675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcf", 0));
10680675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abcg", 0));
10780675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abch", 0));
10880675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abci", 0));
10980675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcj", 0));
11080675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abck", 0));
11180675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abcl", 0));
11280675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abc-", 0));
11380675Sasmodai
11480675Sasmodai	/* [] matches nothing, [!] is the same as ? */
11580675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[]efg", "abcdefg", 0));
11680675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[]efg", "abcqefg", 0));
11780675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[]efg", "abcefg", 0));
11880675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[!]efg", "abcdefg", 0));
11980675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[!]efg", "abcqefg", 0));
12080675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[!]efg", "abcefg", 0));
12180675Sasmodai
12280675Sasmodai	/* I assume: Trailing '-' is non-special. */
12380675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d-fh-]", "abcl", 0));
12480675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abch", 0));
12580675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abc-", 0));
12680675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abc-", 0));
12780675Sasmodai
12880675Sasmodai	/* ']' can be backslash-quoted within a character class. */
12980675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[\\]]", "abc]", 0));
13080675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[\\]d]", "abc]", 0));
13180675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[\\]d]", "abcd", 0));
13280675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d\\]]", "abc]", 0));
13380675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d\\]]", "abcd", 0));
13480675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d]e]", "abcde]", 0));
13580675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d\\]e]", "abc]", 0));
13680675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d\\]e]", "abcd]e", 0));
13780675Sasmodai	assertEqualInt(0, archive_pathmatch("abc[d]e]", "abc]", 0));
138101401Swosch
13980675Sasmodai	/* backslash-quoted chars can appear as either end of a range. */
140147593Shrs	assertEqualInt(1, archive_pathmatch("abc[\\d-f]gh", "abcegh", 0));
14187200Swosch	assertEqualInt(0, archive_pathmatch("abc[\\d-f]gh", "abcggh", 0));
142147593Shrs	assertEqualInt(0, archive_pathmatch("abc[\\d-f]gh", "abc\\gh", 0));
14380675Sasmodai	assertEqualInt(1, archive_pathmatch("abc[d-\\f]gh", "abcegh", 0));
144104772Smaxim	assertEqualInt(1, archive_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
145104772Smaxim	assertEqualInt(1, archive_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
146104772Smaxim	/* backslash-quoted '-' isn't special. */
147104772Smaxim	assertEqualInt(0, archive_pathmatch("abc[d\\-f]gh", "abcegh", 0));
148104781Sjhb	assertEqualInt(1, archive_pathmatch("abc[d\\-f]gh", "abc-gh", 0));
149104781Sjhb
150104781Sjhb	/* Leading '!' negates a character class. */
151104781Sjhb	assertEqualInt(0, archive_pathmatch("abc[!d]", "abcd", 0));
152104781Sjhb	assertEqualInt(1, archive_pathmatch("abc[!d]", "abce", 0));
153104781Sjhb	assertEqualInt(1, archive_pathmatch("abc[!d]", "abcc", 0));
154214628Suqs	assertEqualInt(0, archive_pathmatch("abc[!d-z]", "abcq", 0));
155147593Shrs	assertEqualInt(1, archive_pathmatch("abc[!d-gi-z]", "abch", 0));
156147593Shrs	assertEqualInt(1, archive_pathmatch("abc[!fgijkl]", "abch", 0));
157119217Smurray	assertEqualInt(0, archive_pathmatch("abc[!fghijkl]", "abch", 0));
158119217Smurray
159119217Smurray	/* Backslash quotes next character. */
160119217Smurray	assertEqualInt(0, archive_pathmatch("abc\\[def]", "abc\\d", 0));
161132652Sosa	assertEqualInt(1, archive_pathmatch("abc\\[def]", "abc[def]", 0));
162132652Sosa	assertEqualInt(0, archive_pathmatch("abc\\\\[def]", "abc[def]", 0));
163132652Sosa	assertEqualInt(0, archive_pathmatch("abc\\\\[def]", "abc\\[def]", 0));
164132652Sosa	assertEqualInt(1, archive_pathmatch("abc\\\\[def]", "abc\\d", 0));
165132652Sosa	assertEqualInt(1, archive_pathmatch("abcd\\", "abcd\\", 0));
166132652Sosa	assertEqualInt(0, archive_pathmatch("abcd\\", "abcd\\[", 0));
167132652Sosa	assertEqualInt(0, archive_pathmatch("abcd\\", "abcde", 0));
168132652Sosa	assertEqualInt(0, archive_pathmatch("abcd\\[", "abcd\\", 0));
169132652Sosa
170132652Sosa	/*
171140831Smaxim	 * Because '.' and '/' have special meanings, we can
172176637Smaxim	 * identify many equivalent paths even if they're expressed
173176637Smaxim	 * differently.  (But quoting a character with '\\' suppresses
174132652Sosa	 * special meanings!)
175132652Sosa	 */
176132652Sosa	assertEqualInt(0, archive_pathmatch("a/b/", "a/bc", 0));
177171778Smaxim	assertEqualInt(1, archive_pathmatch("a/./b", "a/b", 0));
178132652Sosa	assertEqualInt(0, archive_pathmatch("a\\/./b", "a/b", 0));
179132652Sosa	assertEqualInt(0, archive_pathmatch("a/\\./b", "a/b", 0));
180132652Sosa	assertEqualInt(0, archive_pathmatch("a/.\\/b", "a/b", 0));
181132652Sosa	assertEqualInt(0, archive_pathmatch("a\\/\\.\\/b", "a/b", 0));
182132652Sosa	assertEqualInt(1, archive_pathmatch("./abc/./def/", "abc/def/", 0));
183132652Sosa	assertEqualInt(1, archive_pathmatch("abc/def", "./././abc/./def", 0));
184132652Sosa	assertEqualInt(1, archive_pathmatch("abc/def/././//", "./././abc/./def/", 0));
185158916Smaxim	assertEqualInt(1, archive_pathmatch(".////abc/.//def", "./././abc/./def", 0));
186158916Smaxim	assertEqualInt(1, archive_pathmatch("./abc?def/", "abc/def/", 0));
187158916Smaxim	failure("\"?./\" is not the same as \"/./\"");
188171778Smaxim	assertEqualInt(0, archive_pathmatch("./abc?./def/", "abc/def/", 0));
189158916Smaxim	failure("Trailing '/' should match no trailing '/'");
190158916Smaxim	assertEqualInt(1, archive_pathmatch("./abc/./def/", "abc/def", 0));
191158916Smaxim	failure("Trailing '/./' is still the same directory.");
192158916Smaxim	assertEqualInt(1, archive_pathmatch("./abc/./def/./", "abc/def", 0));
193158916Smaxim	failure("Trailing '/.' is still the same directory.");
194158916Smaxim	assertEqualInt(1, archive_pathmatch("./abc/./def/.", "abc/def", 0));
195158916Smaxim	assertEqualInt(1, archive_pathmatch("./abc/./def", "abc/def/", 0));
196158916Smaxim	failure("Trailing '/./' is still the same directory.");
197158916Smaxim	assertEqualInt(1, archive_pathmatch("./abc/./def", "abc/def/./", 0));
198158916Smaxim	failure("Trailing '/.' is still the same directory.");
199158916Smaxim	assertEqualInt(1, archive_pathmatch("./abc*/./def", "abc/def/.", 0));
200158916Smaxim
201171778Smaxim	/* Matches not anchored at beginning. */
202164001Smaxim	assertEqualInt(0,
203164001Smaxim	    archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
204164001Smaxim	assertEqualInt(1,
205164001Smaxim	    archive_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_START));
206171778Smaxim	assertEqualInt(0,
207164001Smaxim	    archive_pathmatch("^bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
208166020Smaxim	assertEqualInt(1,
209166020Smaxim	    archive_pathmatch("b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
210166020Smaxim	assertEqualInt(0,
211166020Smaxim	    archive_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
212171778Smaxim	assertEqualInt(0,
213169192Smaxim	    archive_pathmatch("^b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
214171777Smaxim
215176637Smaxim	/* Matches not anchored at end. */
216176637Smaxim	assertEqualInt(0,
217173289Smaxim	    archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_END));
218174783Smaxim	assertEqualInt(1,
219175454Smaxim	    archive_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_END));
220185405Smaxim	assertEqualInt(1,
221185405Smaxim	    archive_pathmatch("abcd", "abcd/", PATHMATCH_NO_ANCHOR_END));
222185405Smaxim	assertEqualInt(1,
223185405Smaxim	    archive_pathmatch("abcd", "abcd/.", PATHMATCH_NO_ANCHOR_END));
224186785Smaxim	assertEqualInt(0,
225186785Smaxim	    archive_pathmatch("abc", "abcd", PATHMATCH_NO_ANCHOR_END));
226186785Smaxim	assertEqualInt(1,
227186785Smaxim	    archive_pathmatch("a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
228186785Smaxim	assertEqualInt(0,
229188749Smaxim	    archive_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
230191834Smaxim	assertEqualInt(1,
231215733Smaxim	    archive_pathmatch("a/b/c$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
232219308Sgavin	assertEqualInt(1,
233219308Sgavin	    archive_pathmatch("a/b/c$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
234215733Smaxim	assertEqualInt(1,
235215733Smaxim	    archive_pathmatch("a/b/c/", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
236215733Smaxim	assertEqualInt(0,
237215733Smaxim	    archive_pathmatch("a/b/c/$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
238215733Smaxim	assertEqualInt(1,
239219024Smaxim	    archive_pathmatch("a/b/c/$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
240215733Smaxim	assertEqualInt(1,
241219024Smaxim	    archive_pathmatch("a/b/c/$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
242219024Smaxim	assertEqualInt(0,
243219024Smaxim	    archive_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
244219024Smaxim}
245219024Smaxim