Imported Upstream version 3.1.0
[debian/amanda] / common-src / match-test.c
1 /*
2  * Copyright (c) 2010 Zmanda, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16  *
17  * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19  */
20
21 #include "amanda.h"
22 #include "testutils.h"
23 #include "match.h"
24
25 /* NOTE: this is an incomplete set of tests for match.c */
26
27 /*
28  * Tests
29  */
30
31 /****
32  * Test some host expressions
33  */
34 static int
35 test_host_match(void)
36 {
37     gboolean ok = TRUE;
38     struct { char *expr, *str; gboolean should_match; } tests[] = {
39         /* examples from amanda(8) */
40         { "hosta", "hosta", TRUE },
41         { "hosta", "foo.hosta.org", TRUE },
42         { "hosta", "hOsTA.domain.org", TRUE },
43         { "hosta", "hostb", FALSE },
44         { "host", "host", TRUE },
45         { "host", "hosta", FALSE },
46         { "host?", "hosta", TRUE },
47         { "host?", "host", FALSE },
48         { "ho*na", "hoina", TRUE },
49         { "ho*na", "ho.aina.org", FALSE },
50         { "ho**na", "hoina", TRUE },
51         { "ho**na", "ho.aina.org", TRUE },
52         { "^hosta", "hosta", TRUE },
53         { "^hosta", "hosta.foo.org", TRUE },
54         { "^hosta", "foo.hosta.org", FALSE },
55
56         { ".hosta.", "hosta", TRUE },
57         { ".hosta.", "foo.hosta", TRUE },
58         { ".hosta.", "hosta.org", TRUE },
59         { ".hosta.", "foo.hosta.org", TRUE },
60         { "/hosta", "hosta", FALSE },
61         { "/hosta", "foo.hosta", FALSE },
62         { "/hosta", "hosta.org", FALSE },
63         { "/hosta", "foo.hosta.org", FALSE },
64
65         /* additional checks */
66         { "^hosta$", "hosta", TRUE },
67         { "^hosta$", "foo.hosta", FALSE },
68         { "^hosta$", "hosta.org", FALSE },
69         { "^hosta$", "foo.hosta.org", FALSE },
70
71         { "^lu.vis.ta$", "lu.vis.ta", TRUE },
72         { "^lu.vis.ta$", "lu-vis.ta", FALSE },
73         { "^lu.vis.ta$", "luvista", FALSE },
74         { "^lu.vis.ta$", "foo.lu.vis.ta", FALSE },
75         { "^lu.vis.ta$", "lu.vis.ta.org", FALSE },
76         { "^lu.vis.ta$", "foo.lu.vis.ta.org", FALSE },
77
78         { "mo[st]a", "mota", TRUE },
79         { "mo[st]a", "mosa", TRUE },
80         { "mo[st]a", "mosta", FALSE },
81         { "mo[!st]a", "mota", FALSE },
82         { "mo[!st]a", "moma", TRUE },
83         { "mo[!st]a", "momma", FALSE },
84
85         { NULL, NULL, FALSE },
86     }, *t;
87
88     for (t = tests; t->expr; t++) {
89         gboolean matched = match_host(t->expr, t->str);
90         if (!!matched != !!t->should_match) {
91             ok = FALSE;
92             if (t->should_match) {
93                 g_fprintf(stderr, "%s should have matched host expr %s\n",
94                         t->str, t->expr);
95             } else {
96                 g_fprintf(stderr, "%s unexpectedly matched host expr %s\n",
97                         t->str, t->expr);
98             }
99         }
100     }
101
102     return ok;
103 }
104
105 /****
106  * Test some disk expressions
107  */
108 static int
109 test_disk_match(void)
110 {
111     gboolean ok = TRUE;
112     struct { char *expr, *str; gboolean should_match; } tests[] = {
113         /* examples from amanda(8) */
114         { "sda*", "/dev/sda1", TRUE },
115         { "sda*", "/dev/sda12", TRUE },
116         { "opt", "opt", TRUE },
117         { "opt", "/opt", TRUE },
118         { "opt", "/opt/foo", TRUE },
119         { "opt", "opt/foo", TRUE },
120         { "/", "/", TRUE },
121         { "/", "/opt", FALSE },
122         { "/", "/opt/var", FALSE },
123         { "/usr", "/", FALSE },
124         { "/usr", "/usr", TRUE },
125         { "/usr", "/usr/local", TRUE },
126         { "/usr$", "/", FALSE },
127         { "/usr$", "/usr", TRUE },
128         { "/usr$", "/usr/local", FALSE },
129         { "share", "//windows1/share", TRUE },
130         { "share", "//windows2/share", TRUE },
131         { "share", "\\\\windows1\\share", TRUE },
132         { "share", "\\\\windows2\\share", TRUE },
133         { "share*", "//windows/share1", TRUE },
134         { "share*", "//windows/share2", TRUE },
135         { "share*", "\\\\windows\\share1", TRUE },
136         { "share*", "\\\\windows\\share2", TRUE },
137         { "//windows/share", "//windows/share", TRUE },
138         { "//windows/share", "\\\\windows\\share", TRUE },
139
140         /* and now things get murky */
141         { "\\\\windows\\share", "//windows/share", FALSE },
142         { "\\\\windows\\share", "\\\\windows\\share", FALSE },
143         { "\\\\\\\\windows\\\\share", "//windows/share", FALSE },
144         { "\\\\\\\\windows\\\\share", "\\\\windows\\share", TRUE },
145
146         /* longer expressions */
147         { "local/var", "/local/var", TRUE },
148         { "local/var", "/opt/local/var", TRUE },
149         { "local/var", "/local/var/lib", TRUE },
150         { "local/var", "/local/usr/var", FALSE },
151
152         /* trailing slashes */
153         { "/usr/bin", "/usr/bin", TRUE },
154         { "/usr/bin", "/usr/bin/", TRUE },
155         { "/usr/bin/", "/usr/bin", TRUE },
156         { "/usr/bin/", "/usr/bin/", TRUE },
157         { "/usr/bin", "/usr/bin//", TRUE },
158         { "/usr/bin//", "/usr/bin", FALSE },
159         { "/usr/bin//", "/usr/bin//", TRUE },
160
161         /* quoting '/' is weird: it doesn't work on the leading slash.  Note that
162          * the documentation does not specify how to quote metacharacters in a host
163          * or disk expression. */
164         { "/usr\\/bin", "/usr/bin", TRUE },
165         { "^/usr\\/bin$", "/usr/bin", TRUE },
166         { "\\/usr\\/bin", "/usr/bin", FALSE },
167         { "^\\/usr\\/bin$", "/usr/bin", FALSE },
168
169         { NULL, NULL, FALSE },
170     }, *t;
171
172     for (t = tests; t->expr; t++) {
173         gboolean matched = match_disk(t->expr, t->str);
174         if (!!matched != !!t->should_match) {
175             ok = FALSE;
176             if (t->should_match) {
177                 g_fprintf(stderr, "%s should have matched disk expr %s\n",
178                         t->str, t->expr);
179             } else {
180                 g_fprintf(stderr, "%s unexpectedly matched disk expr %s\n",
181                         t->str, t->expr);
182             }
183         }
184     }
185
186     return ok;
187 }
188
189 /****
190  * Test make_exact_host_expression
191  */
192 static int
193 test_make_exact_host_expression(void)
194 {
195     gboolean ok = TRUE;
196     guint i, j;
197     const char *test_strs[] = {
198         "host",
199         "host.org",
200         "host.host.org",
201         /* note that these will inter-match: */
202         /*
203         ".host",
204         ".host.org",
205         ".host.host.org",
206         "host.",
207         "host.org.",
208         "host.host.org.",
209         */
210         "org",
211         "^host",
212         "host$",
213         "^host$",
214         "ho[s]t",
215         "ho[!s]t",
216         "ho\\st",
217         "ho/st",
218         "ho?t",
219         "h*t",
220         "h**t",
221     };
222
223     for (i = 0; i < G_N_ELEMENTS(test_strs); i++) {
224         for (j = 0; j < G_N_ELEMENTS(test_strs); j++) {
225             char *expr = make_exact_host_expression(test_strs[i]);
226             gboolean matched = match_host(expr, test_strs[j]);
227             if (!!matched != !!(i == j)) {
228                 ok = FALSE;
229                 if (matched) {
230                     g_fprintf(stderr, "expr %s for str %s unexpectedly matched %s\n",
231                             expr, test_strs[i], test_strs[j]);
232                 } else {
233                     g_fprintf(stderr, "expr %s for str %s should have matched %s\n",
234                             expr, test_strs[i], test_strs[j]);
235                 }
236             }
237         }
238     }
239
240     return ok;
241 }
242
243 /****
244  * Test make_exact_disk_expression
245  */
246 static int
247 test_make_exact_disk_expression(void)
248 {
249     gboolean ok = TRUE;
250     guint i, j;
251     const char *test_strs[] = {
252         "/disk",
253         "/disk/disk",
254         "d[i]sk",
255         "d**k",
256         "d*k",
257         "d?sk",
258         "d.sk",
259         "d[!pqr]sk",
260         "^disk",
261         "disk$",
262         "^disk$",
263         /* these intermatch due to some special-casing */
264         /*
265         "//windows/share",
266         "\\\\windows\\share",
267         */
268     };
269
270     for (i = 0; i < G_N_ELEMENTS(test_strs); i++) {
271         for (j = 0; j < G_N_ELEMENTS(test_strs); j++) {
272             char *expr = make_exact_disk_expression(test_strs[i]);
273             gboolean matched = match_disk(expr, test_strs[j]);
274             if (!!matched != !!(i == j)) {
275                 ok = FALSE;
276                 if (matched) {
277                     g_fprintf(stderr, "expr %s for str %s unexpectedly matched %s\n",
278                             expr, test_strs[i], test_strs[j]);
279                 } else {
280                     g_fprintf(stderr, "expr %s for str %s should have matched %s\n",
281                             expr, test_strs[i], test_strs[j]);
282                 }
283             }
284         }
285     }
286
287     return ok;
288 }
289
290 /*
291  * Main driver
292  */
293
294 int
295 main(int argc, char **argv)
296 {
297     static TestUtilsTest tests[] = {
298         TU_TEST(test_host_match, 90),
299         TU_TEST(test_disk_match, 90),
300         TU_TEST(test_make_exact_host_expression, 90),
301         TU_TEST(test_make_exact_disk_expression, 90),
302         TU_END()
303     };
304
305     return testutils_run_tests(argc, argv, tests);
306 }
307