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