2 * Copyright (c) 2010-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
23 #include "testutils.h"
31 test_validate_regexp(void)
36 gboolean should_validate;
46 for (t = tests; t->regexp; t++) {
47 char *validated_err = validate_regexp(t->regexp);
48 if (!validated_err != !!t->should_validate) {
50 if (t->should_validate) {
51 g_fprintf(stderr, "should have validated regular expr %s: %s\n",
52 t->regexp, validated_err);
54 g_fprintf(stderr, "unexpectedly validated regular expr %s\n",
69 gboolean should_match, should_match_no_newline;
71 /* literal, unanchored matching */
72 { "a", "a", TRUE, TRUE },
73 { "a", "A", FALSE, FALSE },
74 { "a", "ab", TRUE, TRUE },
75 { "a", "ba", TRUE, TRUE },
76 { "a", "bab", TRUE, TRUE },
79 { ".", "", FALSE, FALSE },
80 { ".", "a", TRUE, TRUE },
81 { "..", "a", FALSE, FALSE },
82 { "..", "bc", TRUE, TRUE },
85 { "[abc]", "xbx", TRUE, TRUE },
86 { "[abc]", "xyz", FALSE, FALSE },
87 { "[^abc]", "cba", FALSE, FALSE },
88 { "[^abc]", "xyz", TRUE, TRUE },
89 { "[a-c]", "b", TRUE, TRUE },
90 { "[^a-c]", "-", TRUE, TRUE },
91 { "[1-9-]", "-", TRUE, TRUE },
92 { "[ab\\-cd]", "-", FALSE, FALSE }, /* NOTE! */
95 { "^xy", "xyz", TRUE, TRUE },
96 { "^xy", "wxyz", FALSE, FALSE },
97 { "yz$", "xyz", TRUE, TRUE },
98 { "yz$", "yza", FALSE, FALSE },
99 { "^123$", "123", TRUE, TRUE },
100 { "^123$", "0123", FALSE, FALSE },
101 { "^123$", "1234", FALSE, FALSE },
104 { "([a-c])([x-y])", "pqaxyr", TRUE, TRUE },
105 { "([a-c])([x-y])", "paqrxy", FALSE, FALSE },
106 { "([a-c])/\\1", "a/b", FALSE, FALSE },
107 { "([a-c])/\\1", "c/c", TRUE, TRUE },
110 { ">[0-9]*<", "><", TRUE, TRUE },
111 { ">[0-9]*<", ">3<", TRUE, TRUE },
112 { ">[0-9]*<", ">34<", TRUE, TRUE },
113 { ">[0-9]*<", ">345<", TRUE, TRUE },
114 { ">[0-9]*<", ">x<", FALSE, FALSE },
117 { ":(abc|ABC);", ":abc;", TRUE, TRUE },
118 { ":(abc|ABC);", ":ABC;", TRUE, TRUE },
119 { ":(abc|ABC);", ":abcBC;", FALSE, FALSE },
122 { ">[0-9]+<", "><", FALSE, FALSE },
123 { ">[0-9]+<", ">3<", TRUE, TRUE },
124 { ">[0-9]+<", ">34<", TRUE, TRUE },
125 { ">[0-9]+<", ">345<", TRUE, TRUE },
126 { ">[0-9]+<", ">x<", FALSE, FALSE },
129 { ">[0-9]{0,1}<", "><", TRUE, TRUE },
130 { ">[0-9]{0,1}<", ">9<", TRUE, TRUE },
131 { ">[0-9]{0,1}<", ">98<", FALSE, FALSE },
132 { ">[0-9]{2,3}<", "><", FALSE, FALSE },
133 { ">[0-9]{2,3}<", ">5<", FALSE, FALSE },
134 { ">[0-9]{2,3}<", ">55<", TRUE, TRUE },
135 { ">[0-9]{2,3}<", ">555<", TRUE, TRUE },
136 { ">[0-9]{2,3}<", ">5555<", FALSE, FALSE },
138 /* quoting metacharacters */
139 { "\\\\", "\\", TRUE, TRUE },
140 { "\\,", ",", TRUE, TRUE },
141 { "\\[", "[", TRUE, TRUE },
142 { "\\*", "*", TRUE, TRUE },
143 { "\\?", "?", TRUE, TRUE },
144 { "\\+", "+", TRUE, TRUE },
145 { "\\.", ".", TRUE, TRUE },
146 { "\\|", "|", TRUE, TRUE },
147 { "\\^", "^", TRUE, TRUE },
148 { "\\$", "$", TRUE, TRUE },
150 /* differences between match and match_no_newline */
151 { "x.y", "x\ny", FALSE, TRUE },
152 { "x[^yz]y", "x\ny", FALSE, TRUE },
153 { "^y", "x\ny", TRUE, FALSE },
154 { "x$", "x\ny", TRUE, FALSE },
156 { NULL, NULL, FALSE, FALSE },
159 for (t = tests; t->expr; t++) {
160 gboolean matched = match(t->expr, t->str);
161 if (!!matched != !!t->should_match) {
163 if (t->should_match) {
164 g_fprintf(stderr, "%s should have matched regular expr %s\n",
167 g_fprintf(stderr, "%s unexpectedly matched regular expr %s\n",
172 matched = match_no_newline(t->expr, t->str);
173 if (!!matched != !!t->should_match_no_newline) {
175 if (t->should_match) {
176 g_fprintf(stderr, "%s should have matched (no_newline) regular expr %s\n",
179 g_fprintf(stderr, "%s unexpectedly matched (no_newline) regular expr %s\n",
189 test_validate_glob(void)
194 gboolean should_validate;
199 { "x[!abc]y", TRUE },
203 { "**?", TRUE }, /* legal, but weird */
204 { "foo\\", FALSE }, /* un-escaped \ is illegal */
205 { "foo\\\\", TRUE }, /* but escaped is OK */
206 { "(){}+.^$|", TRUE }, /* funny characters OK */
207 { "/usr/bin/*", TRUE }, /* filename seps are OK */
211 for (t = tests; t->glob; t++) {
212 char *validated_err = validate_glob(t->glob);
213 if (!validated_err != !!t->should_validate) {
215 if (t->should_validate) {
216 g_fprintf(stderr, "should have validated glob %s: %s\n",
217 t->glob, validated_err);
219 g_fprintf(stderr, "unexpectedly validated glob %s\n",
229 test_glob_to_regex(void)
232 struct { char *glob, *regex; } tests[] = {
234 { "*.txt", "^[^/]*\\.txt$" },
235 { "?.txt", "^[^/]\\.txt$" },
236 { "?*.txt", "^[^/][^/]*\\.txt$" },
237 { "foo.[tT][xX][tT]", "^foo\\.[tT][xX][tT]$" },
238 { "foo.[tT][!yY][tT]", "^foo\\.[tT][^yY][tT]$" },
239 { "foo\\\\", "^foo\\\\$" },
240 { "(){}+.^$|", "^\\(\\)\\{\\}\\+\\.\\^\\$\\|$" },
241 { "/usr/bin/*", "^/usr/bin/[^/]*$" },
245 for (t = tests; t->glob; t++) {
246 char *regex = glob_to_regex(t->glob);
247 if (0 != strcmp(regex, t->regex)) {
249 g_fprintf(stderr, "glob_to_regex(\"%s\") returned \"%s\"; expected \"%s\"\n",
250 t->glob, regex, t->regex);
258 test_match_glob(void)
263 gboolean should_match;
265 /* literal, unanchored matching */
268 { "abc", "abc", TRUE },
269 { "abc", "abcd", FALSE },
270 { "abc", "dabc", FALSE },
271 { "abc", "/usr/bin/abc", FALSE },
273 { "*.txt", "foo.txt", TRUE },
274 { "*.txt", ".txt", TRUE },
275 { "*.txt", "txt", FALSE },
277 { "?.txt", "X.txt", TRUE },
278 { "?.txt", ".txt", FALSE },
279 { "?.txt", "XY.txt", FALSE },
281 { "?*.txt", ".txt", FALSE },
282 { "?*.txt", "a.txt", TRUE },
283 { "?*.txt", "aa.txt", TRUE },
284 { "?*.txt", "aaa.txt", TRUE },
286 { "foo.[tT][xX][tT]", "foo.txt", TRUE },
287 { "foo.[tT][xX][tT]", "foo.TXt", TRUE },
288 { "foo.[tT][xX][tT]", "foo.TXT", TRUE },
289 { "foo.[tT][xX][tT]", "foo.TaT", FALSE },
291 { "foo.[tT][!yY][tT]", "foo.TXt", TRUE },
292 { "foo.[tT][!yY][tT]", "foo.TXT", TRUE },
293 { "foo.[tT][!yY][tT]", "foo.TyT", FALSE },
295 { "foo\\\\", "foo", FALSE },
296 { "foo\\\\", "foo\\", TRUE },
297 { "foo\\\\", "foo\\\\", FALSE },
299 { "(){}+.^$|", "(){}+.^$|", TRUE },
301 { "/usr/bin/*", "/usr/bin/tar", TRUE },
302 { "/usr/bin/*", "/usr/bin/local/tar", FALSE },
303 { "/usr/bin/*", "/usr/sbin/tar", FALSE },
304 { "/usr/bin/*", "/opt/usr/bin/tar", FALSE },
306 { "/usr?bin", "/usr/bin", FALSE },
307 { "/usr*bin", "/usr/bin", FALSE },
309 { NULL, NULL, FALSE },
312 for (t = tests; t->expr; t++) {
313 gboolean matched = match_glob(t->expr, t->str);
314 if (!!matched != !!t->should_match) {
316 if (t->should_match) {
317 g_fprintf(stderr, "%s should have matched glob %s\n",
320 g_fprintf(stderr, "%s unexpectedly matched glob %s\n",
335 gboolean should_match;
337 /* literal, unanchored matching */
340 { "abc", "abc", TRUE },
341 { "abc", "abcd", FALSE },
342 { "abc", "dabc", FALSE },
343 { "abc", "/usr/bin/abc", TRUE },
345 { "*.txt", "foo.txt", TRUE },
346 { "*.txt", ".txt", TRUE },
347 { "*.txt", "txt", FALSE },
349 { "?.txt", "X.txt", TRUE },
350 { "?.txt", ".txt", FALSE },
351 { "?.txt", "XY.txt", FALSE },
353 { "?*.txt", ".txt", FALSE },
354 { "?*.txt", "a.txt", TRUE },
355 { "?*.txt", "aa.txt", TRUE },
356 { "?*.txt", "aaa.txt", TRUE },
358 { "foo.[tT][xX][tT]", "foo.txt", TRUE },
359 { "foo.[tT][xX][tT]", "foo.TXt", TRUE },
360 { "foo.[tT][xX][tT]", "foo.TXT", TRUE },
361 { "foo.[tT][xX][tT]", "foo.TaT", FALSE },
363 { "foo.[tT][!yY][tT]", "foo.TXt", TRUE },
364 { "foo.[tT][!yY][tT]", "foo.TXT", TRUE },
365 { "foo.[tT][!yY][tT]", "foo.TyT", FALSE },
367 { "foo\\\\", "foo", FALSE },
368 { "foo\\\\", "foo\\", TRUE },
369 { "foo\\\\", "foo\\\\", FALSE },
371 { "(){}+.^$|", "(){}+.^$|", TRUE },
373 { "/usr/bin/*", "/usr/bin/tar", TRUE },
374 { "/usr/bin/*", "/usr/bin/local/tar", TRUE }, /* different from match_glob */
375 { "/usr/bin/*", "/usr/sbin/tar", FALSE },
376 { "/usr/bin/*", "/opt/usr/bin/tar", FALSE },
378 { "/usr?bin", "/usr/bin", FALSE },
379 { "/usr*bin", "/usr/bin", TRUE }, /* different from match_glob */
381 /* examples from the amgtar manpage */
382 { "./temp-files", "./temp-files", TRUE },
383 { "./temp-files", "./temp-files/foo", TRUE },
384 { "./temp-files", "./temp-files/foo/bar", TRUE },
385 { "./temp-files", "./temp-files.bak", FALSE },
386 { "./temp-files", "./backup/temp-files", FALSE },
388 { "./temp-files/", "./temp-files", FALSE },
389 { "./temp-files/", "./temp-files/", TRUE },
390 { "./temp-files/", "./temp-files/foo", FALSE },
391 { "./temp-files/", "./temp-files/foo/bar", FALSE },
392 { "./temp-files/", "./temp-files.bak", FALSE },
394 { "/temp-files/", "./temp-files", FALSE },
395 { "/temp-files/", "./temp-files/", FALSE },
396 { "/temp-files/", "./temp-files/foo", FALSE },
397 { "/temp-files/", "./temp-files/foo/bar", FALSE },
398 { "/temp-files/", "./temp-files.bak", FALSE },
400 { "./temp-files/*", "./temp-files", FALSE },
401 { "./temp-files/*", "./temp-files/", TRUE },
402 { "./temp-files/*", "./temp-files/foo", TRUE },
403 { "./temp-files/*", "./temp-files/foo/bar", TRUE },
405 { "temp-files", "./my/temp-files", TRUE },
406 { "temp-files", "./my/temp-files/bar", TRUE },
407 { "temp-files", "./temp-files", TRUE },
408 { "temp-files", "./her-temp-files", FALSE },
409 { "temp-files", "./her/old-temp-files", FALSE },
410 { "temp-files", "./her/old-temp-files/bar", FALSE },
412 { "generated-*", "./my/generated-xyz", TRUE },
413 { "generated-*", "./my/generated-xyz/bar", TRUE },
414 { "generated-*", "./generated-xyz", TRUE },
415 { "generated-*", "./her-generated-xyz", FALSE },
416 { "generated-*", "./her/old-generated-xyz", FALSE },
417 { "generated-*", "./her/old-generated-xyz/bar", FALSE },
419 { "*.iso", "./my/amanda.iso", TRUE },
420 { "*.iso", "./amanda.iso", TRUE },
422 { "proxy/local/cache", "./usr/proxy/local/cache", TRUE },
423 { "proxy/local/cache", "./proxy/local/cache", TRUE },
424 { "proxy/local/cache", "./proxy/local/cache/7a", TRUE },
426 { NULL, NULL, FALSE },
429 for (t = tests; t->expr; t++) {
430 gboolean matched = match_tar(t->expr, t->str);
431 if (!!matched != !!t->should_match) {
433 if (t->should_match) {
434 g_fprintf(stderr, "%s should have matched tar %s\n",
437 g_fprintf(stderr, "%s unexpectedly matched tar %s\n",
447 test_make_exact_host_expression(void)
451 const char *test_strs[] = {
455 /* note that these will inter-match: */
477 for (i = 0; i < G_N_ELEMENTS(test_strs); i++) {
478 for (j = 0; j < G_N_ELEMENTS(test_strs); j++) {
479 char *expr = make_exact_host_expression(test_strs[i]);
480 gboolean matched = match_host(expr, test_strs[j]);
481 if (!!matched != !!(i == j)) {
484 g_fprintf(stderr, "expr %s for str %s unexpectedly matched %s\n",
485 expr, test_strs[i], test_strs[j]);
487 g_fprintf(stderr, "expr %s for str %s should have matched %s\n",
488 expr, test_strs[i], test_strs[j]);
498 test_match_host(void)
503 gboolean should_match;
505 /* from the amanda(8) manpage */
506 { "hosta", "hosta", TRUE },
507 { "hosta", "foo.hosta.org", TRUE },
508 { "hosta", "hoSTA.dOMAIna.ORG", TRUE },
509 { "hosta", "hostb", FALSE },
510 { "hOsta", "hosta", TRUE },
511 { "hOsta", "foo.hosta.org", TRUE },
512 { "hOsta", "hoSTA.dOMAIna.ORG", TRUE },
513 { "hOsta", "hostb", FALSE },
515 { "host", "host", TRUE },
516 { "host", "hosta", FALSE },
518 { "host?", "hosta", TRUE },
519 { "host?", "hostb", TRUE },
520 { "host?", "host", FALSE },
521 { "host?", "hostabc", FALSE },
523 { "ho*na", "hona", TRUE },
524 { "ho*na", "hoina", TRUE },
525 { "ho*na", "hoina.org", TRUE },
526 { "ho*na", "ns.hoina.org", TRUE },
527 { "ho*na", "ho.aina.org", FALSE },
529 { "ho**na", "hona", TRUE },
530 { "ho**na", "hoina", TRUE },
531 { "ho**na", "hoina.org", TRUE },
532 { "ho**na", "ns.hoina.org", TRUE },
533 { "ho**na", "ho.aina.org", TRUE },
535 { "^hosta", "hosta", TRUE },
536 { "^hosta", "hosta.org", TRUE },
537 { "^hosta", "hostabc", FALSE },
538 { "^hosta", "www.hosta", FALSE },
539 { "^hosta", "www.hosta.org", FALSE },
541 { "/opt", "opt", FALSE },
543 { ".hosta.", "hosta", TRUE },
544 { ".hosta.", "foo.hosta", TRUE },
545 { ".hosta.", "hosta.org", TRUE },
546 { ".hosta.", "foo.hosta.org", TRUE },
547 { "/hosta", "hosta", FALSE },
548 { "/hosta", "foo.hosta", FALSE },
549 { "/hosta", "hosta.org", FALSE },
550 { "/hosta", "foo.hosta.org", FALSE },
552 { ".opt.", "opt", TRUE },
553 { ".opt.", "www.opt", TRUE },
554 { ".opt.", "www.opt.com", TRUE },
555 { ".opt.", "opt.com", TRUE },
558 { "^hosta$", "hosta", TRUE },
559 { "^hosta$", "foo.hosta", FALSE },
560 { "^hosta$", "hosta.org", FALSE },
561 { "^hosta$", "foo.hosta.org", FALSE },
563 { "^lu.vis.ta$", "lu.vis.ta", TRUE },
564 { "^lu.vis.ta$", "lu-vis.ta", FALSE },
565 { "^lu.vis.ta$", "luvista", FALSE },
566 { "^lu.vis.ta$", "foo.lu.vis.ta", FALSE },
567 { "^lu.vis.ta$", "lu.vis.ta.org", FALSE },
568 { "^lu.vis.ta$", "foo.lu.vis.ta.org", FALSE },
570 { "mo[st]a", "mota", TRUE },
571 { "mo[st]a", "mosa", TRUE },
572 { "mo[st]a", "mosta", FALSE },
573 { "mo[!st]a", "mota", FALSE },
574 { "mo[!st]a", "moma", TRUE },
575 { "mo[!st]a", "momma", FALSE },
577 { "host[acd]", "hosta", TRUE },
578 { "host[acd]", "hostb", FALSE },
579 { "host[acd]", "hostc", TRUE },
580 { "host[!acd]", "hosta", FALSE },
581 { "host[!acd]", "hostb", TRUE },
582 { "host[!acd]", "hostc", FALSE },
584 { "toast", "www.toast.com", TRUE },
585 { ".toast", "www.toast.com", TRUE },
586 { "toast.", "www.toast.com", TRUE },
587 { ".toast.", "www.toast.com", TRUE },
589 { NULL, NULL, FALSE },
592 for (t = tests; t->expr; t++) {
593 gboolean matched = match_host(t->expr, t->str);
594 if (!!matched != !!t->should_match) {
596 if (t->should_match) {
597 g_fprintf(stderr, "%s should have matched host expr %s\n",
600 g_fprintf(stderr, "%s unexpectedly matched host expr %s\n",
610 test_make_exact_disk_expression(void)
614 const char *test_strs[] = {
626 /* these intermatch due to some special-casing */
629 "\\\\windows\\share",
633 for (i = 0; i < G_N_ELEMENTS(test_strs); i++) {
634 for (j = 0; j < G_N_ELEMENTS(test_strs); j++) {
635 char *expr = make_exact_disk_expression(test_strs[i]);
636 gboolean matched = match_disk(expr, test_strs[j]);
637 if (!!matched != !!(i == j)) {
640 g_fprintf(stderr, "expr %s for str %s unexpectedly matched %s\n",
641 expr, test_strs[i], test_strs[j]);
643 g_fprintf(stderr, "expr %s for str %s should have matched %s\n",
644 expr, test_strs[i], test_strs[j]);
654 test_match_disk(void)
659 gboolean should_match;
661 /* from the amanda(8) manpage */
662 { "sda*", "/dev/sda1", TRUE },
663 { "sda*", "/dev/sda2", TRUE },
664 { "sda*", "/dev/sdb2", FALSE },
666 { "opt", "opt", TRUE },
667 { "opt", "/opt", TRUE },
668 { "opt", "/opt/foo", TRUE },
669 { "opt", "opt/foo", TRUE },
671 { "/opt", "opt", TRUE },
672 { "/opt", "opt/", TRUE },
673 { "/opt", "/opt", TRUE },
674 { "/opt", "/opt/", TRUE },
675 { "/opt", "/local/opt/", TRUE },
676 { "/opt", "/opt/local/", TRUE },
678 { "opt/", "opt", TRUE },
679 { "opt/", "opt/", TRUE },
680 { "opt/", "/opt", TRUE },
681 { "opt/", "/opt/", TRUE },
682 { "opt/", "/local/opt/", TRUE },
683 { "opt/", "/opt/local/", TRUE },
686 { "/", "/opt/local/", FALSE },
688 { "/usr$", "/", FALSE },
689 { "/usr$", "/usr", TRUE },
690 { "/usr$", "/usr/local", FALSE },
692 { "share", "\\\\windows1\\share", TRUE },
693 { "share", "\\\\windows2\\share", TRUE },
694 { "share", "//windows1/share", TRUE },
695 { "share", "//windows2/share", TRUE },
697 { "share*", "\\\\windows\\share1", TRUE },
698 { "share*", "\\\\windows\\share2", TRUE },
699 { "share*", "//windows/share3", TRUE },
700 { "share*", "//windows/share4", TRUE },
702 { "//windows/share", "//windows/share", TRUE },
703 { "//windows/share", "\\\\windows\\share", TRUE },
704 { "\\\\windows\\share", "//windows/share", FALSE },
705 { "\\\\windows\\share", "\\\\windows\\share", FALSE },
706 { "\\\\\\\\windows\\\\share", "//windows/share", FALSE },
707 { "\\\\\\\\windows\\\\share", "\\\\windows\\share", TRUE },
709 /* other expressions */
710 { "^local", "/local", FALSE },
711 { "^/local", "/local", TRUE },
712 { "^local", "/local/vore", FALSE },
713 { "^/local", "/local/vore", TRUE },
714 { "^local", "/usr/local", FALSE },
716 { "local/bin", "/local/bin", TRUE },
717 { "local/bin", "/opt/local/bin", TRUE },
718 { "local/bin", "/local/bin/git", TRUE },
720 { "//windows/share", "//windows/share/files", TRUE },
721 { "//windows/share", "\\\\windows\\share\\files", TRUE },
722 { "\\\\windows\\share", "//windows/share/files", FALSE },
723 { "\\\\windows\\share", "\\\\windows\\share\\files", FALSE },
725 /* longer expressions */
726 { "local/var", "/local/var", TRUE },
727 { "local/var", "/opt/local/var", TRUE },
728 { "local/var", "/local/var/lib", TRUE },
729 { "local/var", "/local/usr/var", FALSE },
731 /* trailing slashes */
732 { "/usr/bin", "/usr/bin", TRUE },
733 { "/usr/bin", "/usr/bin/", TRUE },
734 { "/usr/bin/", "/usr/bin", TRUE },
735 { "/usr/bin/", "/usr/bin/", TRUE },
736 { "/usr/bin", "/usr/bin//", TRUE },
737 { "/usr/bin//", "/usr/bin", FALSE },
738 { "/usr/bin//", "/usr/bin//", TRUE },
740 /* quoting '/' is weird: it doesn't work on the leading slash. Note that
741 * the documentation does not specify how to quote metacharacters in a host
742 * or disk expression. */
743 { "/usr\\/bin", "/usr/bin", TRUE },
744 { "^/usr\\/bin$", "/usr/bin", TRUE },
745 { "\\/usr\\/bin", "/usr/bin", FALSE },
746 { "^\\/usr\\/bin$", "/usr/bin", TRUE },
747 { "/usr\\/bin\\/", "/usr/bin/", TRUE },
748 { "^/usr\\/bin\\/$", "/usr/bin/", TRUE },
749 { "\\/usr\\/bin\\/", "/usr/bin/", FALSE },
750 { "^\\/usr\\/bin\\/$", "/usr/bin/", TRUE },
752 { "oracle", "oracle", TRUE },
753 { "oracle", "/oracle", TRUE },
754 { "oracle", "oracle/", TRUE },
755 { "oracle", "/oracle/", TRUE },
756 { "/oracle", "oracle", TRUE },
757 { "/oracle", "/oracle", TRUE },
758 { "/oracle", "oracle/", TRUE },
759 { "/oracle", "/oracle/", TRUE },
760 { "^oracle", "oracle", TRUE },
761 { "^oracle", "/oracle", FALSE },
762 { "^oracle", "oracle/", TRUE },
763 { "^oracle", "/oracle/", FALSE },
764 { "^/oracle", "oracle", FALSE },
765 { "^/oracle", "/oracle", TRUE },
766 { "^/oracle", "oracle/", FALSE },
767 { "^/oracle", "/oracle/", TRUE },
769 { "oracle", "oracle", TRUE },
770 { "oracle", "/oracle", TRUE },
771 { "oracle", "oracle/", TRUE },
772 { "oracle", "/oracle/", TRUE },
773 { "oracle$", "oracle", TRUE },
774 { "oracle$", "/oracle", TRUE },
775 { "oracle$", "oracle/", FALSE },
776 { "oracle$", "/oracle/", FALSE },
777 { "oracle/$", "oracle", FALSE },
778 { "oracle/$", "/oracle", FALSE },
779 { "oracle/$", "oracle/", TRUE },
780 { "oracle/$", "/oracle/", TRUE },
782 { NULL, NULL, FALSE },
785 for (t = tests; t->expr; t++) {
786 gboolean matched = match_disk(t->expr, t->str);
787 if (!!matched != !!t->should_match) {
789 if (t->should_match) {
790 g_fprintf(stderr, "%s should have matched disk expr %s\n",
793 g_fprintf(stderr, "%s unexpectedly matched disk expr %s\n",
803 test_match_datestamp(void)
808 gboolean should_match;
810 /* from the amanda(8) manpage */
811 { "20001212-14", "20001212", TRUE },
812 { "20001212-14", "20001212010203", TRUE },
813 { "20001212-14", "20001213", TRUE },
814 { "20001212-14", "20001213010203", TRUE },
815 { "20001212-14", "20001214", TRUE },
816 { "20001212-14", "20001215", FALSE },
818 { "20001212-4", "20001212", TRUE },
819 { "20001212-4", "20001212010203", TRUE },
820 { "20001212-4", "20001213", TRUE },
821 { "20001212-4", "20001213010203", TRUE },
822 { "20001212-4", "20001214", TRUE },
823 { "20001212-4", "20001215", FALSE },
825 { "20001212-214", "20001212", TRUE },
826 { "20001212-214", "20001212010203", TRUE },
827 { "20001212-214", "20001213", TRUE },
828 { "20001212-214", "20001213010203", TRUE },
829 { "20001212-214", "20001214", TRUE },
830 { "20001212-214", "20001215", FALSE },
832 { "20001212-24", "20001211", FALSE },
833 { "20001212-24", "20001214010203", TRUE },
834 { "20001212-24", "20001221010203", TRUE },
835 { "20001212-24", "20001224", TRUE },
836 { "20001212-24", "20001225", FALSE },
838 { "2000121", "20001209", FALSE },
839 { "2000121", "20001210", TRUE },
840 { "2000121", "20001210012345", TRUE },
841 { "2000121", "20001219", TRUE },
842 { "2000121", "20001219012345", TRUE },
843 { "2000121", "20001220", FALSE },
845 { "2", "19991231", FALSE },
846 { "2", "20000101", TRUE },
847 { "2", "20100419", TRUE },
849 { "^2", "19991231", FALSE },
850 { "^2", "20000101", TRUE },
851 { "^2", "20100419", TRUE },
853 { "2000-2010", "19991231235959", FALSE },
854 { "2000-2010", "20001010", TRUE },
855 { "2000-2010", "20101231", TRUE },
856 { "2000-2010", "20111010", FALSE },
858 { "200010$", "200010", TRUE }, /* but it's not a real datestamp */
859 { "200010$", "20001001", FALSE },
860 { "200010$", "20001001061500", FALSE },
862 { "20000615$", "20000615", TRUE },
863 { "20000615$", "20000615000000", FALSE },
864 { "20000615$", "20000615010306", FALSE },
866 { NULL, NULL, FALSE },
869 for (t = tests; t->expr; t++) {
870 gboolean matched = match_datestamp(t->expr, t->str);
871 if (!!matched != !!t->should_match) {
873 if (t->should_match) {
874 g_fprintf(stderr, "%s should have matched datestamp expr %s\n",
877 g_fprintf(stderr, "%s unexpectedly matched datestamp expr %s\n",
887 test_match_level(void)
892 gboolean should_match;
894 /* exact matches, optionally ignoring "^" */
895 { "3$", "2", FALSE },
897 { "3$", "4", FALSE },
898 { "3$", "32", FALSE },
900 { "^3$", "2", FALSE },
901 { "^3$", "3", TRUE },
902 { "^3$", "4", FALSE },
903 { "^3$", "32", FALSE },
912 { "2-5", "1", FALSE },
913 { "2-5", "13", FALSE },
914 { "2-5", "23", FALSE },
915 { "2-5", "2", TRUE },
916 { "2-5", "4", TRUE },
917 { "2-5", "5", TRUE },
918 { "2-5", "53", FALSE },
919 { "2-5", "63", FALSE },
920 { "2-5", "6", FALSE },
922 { "9-15", "8", FALSE },
923 { "9-15", "19", FALSE },
924 { "9-15", "91", FALSE },
925 { "9-15", "9", TRUE },
926 { "9-15", "14", TRUE },
927 { "9-15", "15", TRUE },
928 { "9-15", "152", FALSE },
929 { "9-15", "16", FALSE },
931 { "19-21", "18", FALSE },
932 { "19-21", "19", TRUE },
933 { "19-21", "21", TRUE },
934 { "19-21", "22", FALSE },
936 /* single range is the same as an exact match */
937 { "99-99", "98", FALSE },
938 { "99-99", "99", TRUE },
939 { "99-99", "100", FALSE },
941 /* reversed range never matches */
942 { "21-19", "18", FALSE },
943 { "21-19", "19", FALSE },
944 { "21-19", "21", FALSE },
945 { "21-19", "22", FALSE },
947 { NULL, NULL, FALSE },
950 for (t = tests; t->expr; t++) {
951 gboolean matched = match_level(t->expr, t->str);
952 if (!!matched != !!t->should_match) {
954 if (t->should_match) {
955 g_fprintf(stderr, "%s should have matched level expr %s\n",
958 g_fprintf(stderr, "%s unexpectedly matched level expr %s\n",
973 main(int argc, char **argv)
975 static TestUtilsTest tests[] = {
976 TU_TEST(test_validate_regexp, 90),
977 TU_TEST(test_match, 90),
978 TU_TEST(test_validate_glob, 90),
979 TU_TEST(test_glob_to_regex, 90),
980 TU_TEST(test_match_glob, 90),
981 TU_TEST(test_match_tar, 90),
982 TU_TEST(test_make_exact_host_expression, 90),
983 TU_TEST(test_match_host, 90),
984 TU_TEST(test_make_exact_disk_expression, 90),
985 TU_TEST(test_match_disk, 90),
986 TU_TEST(test_match_datestamp, 90),
987 TU_TEST(test_match_level, 90),
991 return testutils_run_tests(argc, argv, tests);