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
10typedef struct {
11 const char *pat;
12 const char *str;
13 gboolean no_leading_period;
14 gboolean ci;
15 gboolean result;
16} TestCase;
17
18static 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
120static void
121test_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
128typedef struct {
129 const char *glob;
130 const char *ci;
131} CITest;
132
133static 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
148static void
149test_ci_glob (gconstpointer data)
150{
151 const CITest *test = data;
152 char *ci;
153
154 ci = _gtk_make_ci_glob_pattern (pattern: test->glob);
155 g_assert_cmpstr (ci, ==, test->ci);
156 g_free (mem: ci);
157}
158
159int
160main (int argc, char *argv[])
161{
162 (g_test_init) (argc: &argc, argv: &argv, NULL);
163
164 for (int i = 0; i < G_N_ELEMENTS (tests); i++)
165 {
166 char *path = g_strdup_printf (format: "/fnmatch/test%d", i);
167 g_test_add_data_func (testpath: path, test_data: &tests[i], test_func: test_fnmatch);
168 g_free (mem: path);
169 }
170
171 for (int i = 0; i < G_N_ELEMENTS (citests); i++)
172 {
173 char *path = g_strdup_printf (format: "/ci-glob/test%d", i);
174 g_test_add_data_func (testpath: path, test_data: &citests[i], test_func: test_ci_glob);
175 g_free (mem: path);
176 }
177
178 return g_test_run ();
179}
180

source code of gtk/testsuite/gtk/fnmatch.c