1 #include <gtk/gtk.h>
2 #include "gtk/gtkprivate.h"
3
4 #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
5 #define DO_ESCAPE 0
6 #else
7 #define DO_ESCAPE 1
8 #endif
9
10 typedef struct {
11 const char *pat;
12 const char *str;
13 gboolean no_leading_period;
14 gboolean ci;
15 gboolean result;
16 } TestCase;
17
18 static TestCase tests[] = {
19 { "[a-]", "-", TRUE, FALSE, TRUE },
20
21 { "a", "a", TRUE, FALSE, TRUE },
22 { "a", "b", TRUE, FALSE, FALSE },
23
24 /* Test what ? matches */
25 { "?", "a", TRUE, FALSE, TRUE },
26 { "?", ".", TRUE, FALSE, FALSE },
27 { "a?", "a.", TRUE, FALSE, TRUE },
28 { "a/?", "a/b", TRUE, FALSE, TRUE },
29 { "a/?", "a/.", TRUE, FALSE, FALSE },
30 { "?", "/", TRUE, FALSE, FALSE },
31
32 /* Test what * matches */
33 { "*", "a", TRUE, FALSE, TRUE },
34 { "*", ".", TRUE, FALSE, FALSE },
35 { "a*", "a.", TRUE, FALSE, TRUE },
36 { "a/*", "a/b", TRUE, FALSE, TRUE },
37 { "a/*", "a/.", TRUE, FALSE, FALSE },
38 { "*", "/", TRUE, FALSE, FALSE },
39
40 /* Range tests */
41 { "[ab]", "a", TRUE, FALSE, TRUE },
42 { "[ab]", "c", TRUE, FALSE, FALSE },
43 { "[^ab]", "a", TRUE, FALSE, FALSE },
44 { "[!ab]", "a", TRUE, FALSE, FALSE },
45 { "[^ab]", "c", TRUE, FALSE, TRUE },
46 { "[!ab]", "c", TRUE, FALSE, TRUE },
47 { "[a-c]", "b", TRUE, FALSE, TRUE },
48 { "[a-c]", "d", TRUE, FALSE, FALSE },
49 { "[a-]", "-", TRUE, FALSE, TRUE },
50 { "[]]", "]", TRUE, FALSE, TRUE },
51 { "[^]]", "a", TRUE, FALSE, TRUE },
52 { "[!]]", "a", TRUE, FALSE, TRUE },
53
54 /* Various unclosed ranges */
55 { "[ab", "a", TRUE, FALSE, FALSE },
56 { "[a-", "a", TRUE, FALSE, FALSE },
57 { "[ab", "c", TRUE, FALSE, FALSE },
58 { "[a-", "c", TRUE, FALSE, FALSE },
59 { "[^]", "a", TRUE, FALSE, FALSE },
60
61 /* Ranges and special no-wildcard matches */
62 { "[.]", ".", TRUE, FALSE, FALSE },
63 { "a[.]", "a.", TRUE, FALSE, TRUE },
64 { "a/[.]", "a/.", TRUE, FALSE, FALSE },
65 { "[/]", "/", TRUE, FALSE, FALSE },
66 { "[^/]", "a", TRUE, FALSE, TRUE },
67
68 /* Basic tests of * (and combinations of * and ?) */
69 { "a*b", "ab", TRUE, FALSE, TRUE },
70 { "a*b", "axb", TRUE, FALSE, TRUE },
71 { "a*b", "axxb", TRUE, FALSE, TRUE },
72 { "a**b", "ab", TRUE, FALSE, TRUE },
73 { "a**b", "axb", TRUE, FALSE, TRUE },
74 { "a**b", "axxb", TRUE, FALSE, TRUE },
75 { "a*?*b", "ab", TRUE, FALSE, FALSE },
76 { "a*?*b", "axb", TRUE, FALSE, TRUE },
77 { "a*?*b", "axxb", TRUE, FALSE, TRUE },
78
79 /* Test of *[range] */
80 { "a*[cd]", "ac", TRUE, FALSE, TRUE },
81 { "a*[cd]", "axc", TRUE, FALSE, TRUE },
82 { "a*[cd]", "axx", TRUE, FALSE, FALSE },
83
84 { "a/[.]", "a/.", TRUE, FALSE, FALSE },
85 { "a*[.]", "a/.", TRUE, FALSE, FALSE },
86
87
88 /* Test of UTF-8 */
89
90 { "ä", "ä", TRUE, FALSE, TRUE },
91 { "?", "ä", TRUE, FALSE, TRUE },
92 { "*ö", "äö", TRUE, FALSE, TRUE },
93 { "*ö", "ääö", TRUE, FALSE, TRUE },
94 { "[ä]", "ä", TRUE, FALSE, TRUE },
95 { "[ä-ö]", "é", TRUE, FALSE, TRUE },
96 { "[ä-ö]", "a", TRUE, FALSE, FALSE },
97
98 /* ci patterns */
99 { "*.txt", "a.TXT", TRUE, TRUE, TRUE },
100 { "*.txt", "a.TxT", TRUE, TRUE, TRUE },
101 { "*.txt", "a.txT", TRUE, TRUE, TRUE },
102 { "*ö", "äÖ", TRUE, TRUE, TRUE },
103
104 #ifdef DO_ESCAPE
105 /* Tests of escaping */
106 { "\\\\", "\\", TRUE, FALSE, TRUE },
107 { "\\?", "?", TRUE, FALSE, TRUE },
108 { "\\?", "a", TRUE, FALSE, FALSE },
109 { "\\*", "*", TRUE, FALSE, TRUE },
110 { "\\*", "a", TRUE, FALSE, FALSE },
111 { "\\[a-b]", "[a-b]", TRUE, FALSE, TRUE },
112 { "[\\\\]", "\\", TRUE, FALSE, TRUE },
113 { "[\\^a]", "a", TRUE, FALSE, TRUE },
114 { "[a\\-c]", "b", TRUE, FALSE, FALSE },
115 { "[a\\-c]", "-", TRUE, FALSE, TRUE },
116 { "[a\\]", "a", TRUE, FALSE, FALSE },
117 #endif /* DO_ESCAPE */
118 };
119
120 static void
test_fnmatch(gconstpointer data)121 test_fnmatch (gconstpointer data)
122 {
123 const TestCase *test = data;
124
125 g_assert_true (_gtk_fnmatch (test->pat, test->str, test->no_leading_period, test->ci) == test->result);
126 }
127
128 typedef struct {
129 const char *glob;
130 const char *ci;
131 } CITest;
132
133 static CITest citests[] = {
134 { "*.txt", "*.[tT][xX][tT]" },
135 { "*.TXT", "*.[tT][xX][tT]" },
136 { "*?[]-abc]t", "*?[]-abc][tT]" },
137 #ifdef DO_ESCAPE
138 /* Tests of escaping */
139 { "\\\\", "\\\\" },
140 { "\\??", "\\??" },
141 { "\\**", "\\**" },
142 { "\\[", "\\[" },
143 { "\\[a-", "\\[[aA]-" },
144 { "\\[]", "\\[]" },
145 #endif
146 };
147
148 static void
test_ci_glob(gconstpointer data)149 test_ci_glob (gconstpointer data)
150 {
151 const CITest *test = data;
152 char *ci;
153
154 ci = _gtk_make_ci_glob_pattern (test->glob);
155 g_assert_cmpstr (ci, ==, test->ci);
156 g_free (ci);
157 }
158
159 int
main(int argc,char * argv[])160 main (int argc, char *argv[])
161 {
162 (g_test_init) (&argc, &argv, NULL);
163
164 for (int i = 0; i < G_N_ELEMENTS (tests); i++)
165 {
166 char *path = g_strdup_printf ("/fnmatch/test%d", i);
167 g_test_add_data_func (path, &tests[i], test_fnmatch);
168 g_free (path);
169 }
170
171 for (int i = 0; i < G_N_ELEMENTS (citests); i++)
172 {
173 char *path = g_strdup_printf ("/ci-glob/test%d", i);
174 g_test_add_data_func (path, &citests[i], test_ci_glob);
175 g_free (path);
176 }
177
178 return g_test_run ();
179 }
180