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 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