xref: /openbsd-src/regress/usr.bin/rsync-unit/rmatch_test.c (revision 52f7a49a0ee111d9854d8e7b2f1084047e63d612)
1 /*	$OpenBSD: rmatch_test.c,v 1.2 2024/02/20 10:37:35 claudio Exp $	*/
2 
3 /*
4  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 
20 #include <stdio.h>
21 #include <string.h>
22 
23 int	rmatch(const char *, const char *, int);
24 
25 struct tv {
26 	const char *pattern;
27 	const char *string;
28 	int result;
29 	const char *reason;
30 } tvs[] = {
31 	{ "*abc", "aaaabc", 0 },
32 	{ "abc", "abc", 0 },
33 	{ "*aaa", "bbbcaa", 1 },
34 	{ "aaa", "aabb", 1 },
35 	{ "[a]??", "aaa", 0 },
36 	{ "*[a]??", "abcabc", 0 },
37 	{ "[b]??", "abcabc", 1 },
38 	{ "*[b]??*", "abcabc", 0 },
39 	{ "[a-z]", "a", 0 },
40 	{ "*[a-z]", "1234a", 0 },
41 	{ "[a-z]", "A", 1 },
42 	{ "*[a-z]", "1234A", 1 },
43 	{ "[[:lower:]]", "a", 0 },
44 	{ "*[[:lower:]]", "1234a", 0 },
45 	{ "[[:lower:]]", "A", 1 },
46 	{ "*[[:lower:]]", "1234A", 1 },
47 	{ "?", "a", 0 },
48 	{ "*?", "1234a", 0 },
49 	{ "\\a", "a", 0 },
50 	{ "*\\a", "1234a", 0 },
51 	{ "/", "/", 0 },
52 	{ "*/", "1234/", 0 },
53 	{ "?", "/", 1 },
54 	{ "*?", "1234/", 1 },
55 	{ "\\/", "/", 0 },
56 	{ "*\\/", "1234/", 0 },
57 	{ "*abc/", "abc/", 0 },
58 	{ "*abc/", "ababc/", 0 },
59 	{ "*abc/*", "abc/xyz", 0 },
60 	{ "*abc/", "xyz/abc", 1 },
61 	{ "*abc/", "ab/", 1 },
62 	{ "*abc/", "abc", 1 },
63 	{ "*abc/", "abc.", 1 },
64 	{ "*abc/", "abcab/", 1 },
65 	{ "*abc/", "abcd/abc", 1 },
66 	{ "**??""?/", "a/aa/aaa/", 0 },
67 	{ "**??""?/", "a/aa/aa/", 1 },
68 	{ "**??""?/", "a/aa/aaaxxxx/", 0 },
69 	{ "**abc/", "a/aa/xxabc/", 0 },
70 
71 	/* rysnc wildtest.txt */
72 
73 	{ "foo", "foo", 0 },
74 	{ "bar", "foo", 1 },
75 	{ "", "", 0 },
76 	{ "???", "foo", 0 },
77 	{ "??", "foo", 1 },
78 	{ "*", "foo", 0 },
79 	{ "f*", "foo", 0 },
80 	{ "*f", "foo", 1 },
81 	{ "*foo*", "foo", 0 },
82 	{ "*ob*a*r*", "foobar", 0 },
83 	{ "*ab", "aaaaaaabababab", 0 },
84 	{ "foo\\*", "foo*", 0 },
85 	{ "foo\\*bar", "foobar", 1 },
86 	{ "f\\\\oo", "f\\oo", 0 },
87 	{ "*[al]?", "ball", 0 },
88 	{ "[ten]", "ten", 1 },
89 	{ "**[!te]", "ten", 0 },
90 	{ "**[!ten]", "ten", 1 },
91 	{ "t[a-g]n", "ten", 0 },
92 	{ "t[!a-g]n", "ten", 1 },
93 	{ "t[!a-g]n", "ton", 0 },
94 	{ "t[^a-g]n", "ton", 0 },
95 	{ "a[]]b", "a]b", 0 },
96 	{ "a[]-]b", "a-b", 0 },
97 	{ "a[]-]b", "a]b", 0 },
98 	{ "a[]-]b", "aab", 1 },
99 	{ "a[]a-]b", "aab", 0 },
100 	{ "]", "]", 0 },
101 	{ "foo*bar", "foo/baz/bar", 1 },
102 	{ "foo**bar", "foo/baz/bar", 0 },
103 	{ "foo?bar", "foo/bar", 1 },
104 	{ "foo[/]bar", "foo/bar", 1 },
105 	{ "f[^eiu][^eiu][^eiu][^eiu][^eiu]r", "foo/bar", 1 },
106 	{ "f[^eiu][^eiu][^eiu][^eiu][^eiu]r", "foo-bar", 0 },
107 	{ "**/foo", "foo", 1 },
108 	{ "**/foo", "/foo", 0 },
109 	{ "**/foo", "bar/baz/foo", 0 },
110 	{ "*/foo", "bar/baz/foo", 1 },
111 	{ "**/bar*", "foo/bar/baz", 1 },
112 	{ "**/bar/*", "deep/foo/bar/baz", 0 },
113 	{ "**/bar/*", "deep/foo/bar/baz/", 1 },
114 	{ "**/bar/**", "deep/foo/bar/baz/", 0 },
115 	{ "**/bar/*", "deep/foo/bar", 1 },
116 	{ "**/bar/**", "deep/foo/bar/", 0 },
117 	{ "**/bar**", "foo/bar/baz", 0 },
118 	{ "*/bar/**", "foo/bar/baz/x", 0 },
119 	{ "*/bar/**", "deep/foo/bar/baz/x", 1 },
120 	{ "**/bar/*/*", "deep/foo/bar/baz/x", 0 },
121 	{ "a[c-c]st", "acrt", 1 },
122 	{ "a[c-c]rt", "acrt", 0 },
123 	{ "[!]-]", "]", 1 },
124 	{ "[!]-]", "a", 0 },
125 	{ "\\", "", 1 },
126 	{ "\\", "\\", 1, "backslash at end is taken literally" },
127 	{ "*/\\", "/\\", 1, "backslash at end is taken literally" },
128 	{ "*/\\\\", "/\\", 0 },
129 	{ "foo", "foo", 0 },
130 	{ "@foo", "@foo", 0 },
131 	{ "@foo", "foo", 1 },
132 	{ "\\[ab]", "[ab]", 0 },
133 	{ "[[]ab]", "[ab]", 0 },
134 	{ "[[:]ab]", "[ab]", 0 },
135 	{ "[[::]ab]", "[ab]", 1, "bad char class taken literally" },
136 	{ "[[:digit]ab]", "[ab]", 0 },
137 	{ "[\\[:]ab]", "[ab]", 0 },
138 	{ "\\??\\?b", "?a?b", 0 },
139 	{ "\\a\\b\\c", "abc", 0 },
140 	{ "", "foo", 1 },
141 	{ "**/t[o]", "foo/bar/baz/to", 0 },
142 	{ "[[:alpha:]][[:digit:]][[:upper:]]", "a1B", 0 },
143 	{ "[[:digit:][:upper:][:space:]]", "a", 1 },
144 	{ "[[:digit:][:upper:][:space:]]", "A", 0 },
145 	{ "[[:digit:][:upper:][:space:]]", "1", 0 },
146 	{ "[[:digit:][:upper:][:spaci:]]", "1", 1 },
147 	{ "[[:digit:][:upper:][:space:]]", " ", 0 },
148 	{ "[[:digit:][:upper:][:space:]]", ".", 1 },
149 	{ "[[:digit:][:punct:][:space:]]", ".", 0 },
150 	{ "[[:xdigit:]]", "5", 0 },
151 	{ "[[:xdigit:]]", "f", 0 },
152 	{ "[[:xdigit:]]", "D", 0 },
153 	{ "[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]", "_", 0 },
154 	{ "[^[:alnum:][:alpha:][:blank:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]", "", 0 },
155 	{ "[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]", ".", 0 },
156 	{ "[a-c[:digit:]x-z]", "5", 0 },
157 	{ "[a-c[:digit:]x-z]", "b", 0 },
158 	{ "[a-c[:digit:]x-z]", "y", 0 },
159 	{ "[a-c[:digit:]x-z]", "q", 1 },
160 	{ "[\\\\-^]", "]", 0 },
161 	{ "[\\\\-^]", "[", 1 },
162 	{ "[\\-_]", "-", 0 },
163 	{ "[\\]]", "]", 0 },
164 	{ "[\\]]", "\\]", 1 },
165 	{ "[\\]]", "\\", 1 },
166 	{ "a[]b", "ab", 1 },
167 	{ "a[]b", "a[]b", 1, "empty [] is taken literally" },
168 	{ "ab[", "ab[", 1, "single [ char taken literally" },
169 	{ "[!", "ab", 1 },
170 	{ "[-", "ab", 1 },
171 	{ "[-]", "-", 0 },
172 	{ "[a-", "-", 1 },
173 	{ "[!a-", "-", 1 },
174 	{ "[--A]", "-", 0 },
175 	{ "[--A]", "5", 0 },
176 	{ "[ --]", " ", 0 },
177 	{ "[ --]", "$", 0 },
178 	{ "[ --]", "-", 0 },
179 	{ "[ --]", "0", 1 },
180 	{ "[---]", "-", 0 },
181 	{ "[------]", "-", 0 },
182 	{ "[a-e-n]", "j", 1 },
183 	{ "[a-e-n]", "-", 0 },
184 	{ "[!------]", "a", 0 },
185 	{ "[]-a]", "[", 1 },
186 	{ "[]-a]", "^", 0 },
187 	{ "[!]-a]", "^", 1 },
188 	{ "[!]-a]", "[", 0 },
189 	{ "[a^bc]", "^", 0 },
190 	{ "[a-]b]", "-b]", 0 },
191 	{ "[\\]", "\\", 1 },
192 	{ "[\\\\]", "\\", 0 },
193 	{ "[!\\\\]", "\\", 1 },
194 	{ "[A-\\\\]", "G", 0 },
195 	{ "b*a", "aaabbb", 1 },
196 	{ "*ba*", "aabcaa", 1 },
197 	{ "[,]", ",", 0 },
198 	{ "[\\\\,]", ",", 0 },
199 	{ "[\\\\,]", "\\", 0 },
200 	{ "[,-.]", "-", 0 },
201 	{ "[,-.]", "+", 1 },
202 	{ "[,-.]", "-.]", 1 },
203 	{ "[\\1-\\3]", "2", 0 },
204 	{ "[\\1-\\3]", "3", 0 },
205 	{ "[\\1-\\3]", "4", 1 },
206 	{ "[[-\\]]", "\\", 0 },
207 	{ "[[-\\]]", "[", 0 },
208 	{ "[[-\\]]", "]", 0 },
209 	{ "[[-\\]]", "-", 1 },
210 	{ "-*-*-*-*-*-*-12-*-*-*-m-*-*-*", "-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1", 0 },
211 	{ "-*-*-*-*-*-*-12-*-*-*-m-*-*-*", "-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1", 1 },
212 	{ "-*-*-*-*-*-*-12-*-*-*-m-*-*-*", "-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1", 1 },
213 	{ "/*/*/*/*/*/*/12/*/*/*/m/*/*/*", "/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1", 0 },
214 	{ "/*/*/*/*/*/*/12/*/*/*/m/*/*/*", "/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1", 1 },
215 	{ "**/*a*b*g*n*t", "abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt", 0 },
216 	{ "**/*a*b*g*n*t", "abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz", 1 },
217 
218 	/* infinte loop test from Kyle Evans */
219 	{ "dir/*.o", "dir1/a.o", 1 },
220 
221 	{ NULL },
222 };
223 
224 int
main(int argc,char ** argv)225 main (int argc, char **argv)
226 {
227 	const char *p, *s;
228 	size_t i;
229 	int rv = 0;
230 
231 	for (i = 0; tvs[i].pattern != NULL; i++) {
232 		p = tvs[i].pattern;
233 		s = tvs[i].string;
234 		if (rmatch(p, s, 0) == tvs[i].result) {
235 			printf("string %s pattern %s does %s\n",
236 			    tvs[i].string, tvs[i].pattern,
237 			    tvs[i].result ? "not match" : "match");
238 		} else if (tvs[i].reason) {
239 			printf("string %s pattern %s SHOULD %s but %s\n",
240 			    tvs[i].string, tvs[i].pattern,
241 			    tvs[i].result ? "not match" : "match",
242 			    tvs[i].reason);
243 		} else {
244 			printf("FAILED: string %s pattern %s failed to %s\n",
245 			    tvs[i].string, tvs[i].pattern,
246 			    tvs[i].result ? "not match" : "match");
247 			rv = 1;
248 		}
249 	}
250 
251 	return rv;
252 }
253