Imported Upstream version 3.1.0
[debian/amanda] / common-src / match-test.c
diff --git a/common-src/match-test.c b/common-src/match-test.c
new file mode 100644 (file)
index 0000000..44c8d1e
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2010 Zmanda, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
+ * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
+ */
+
+#include "amanda.h"
+#include "testutils.h"
+#include "match.h"
+
+/* NOTE: this is an incomplete set of tests for match.c */
+
+/*
+ * Tests
+ */
+
+/****
+ * Test some host expressions
+ */
+static int
+test_host_match(void)
+{
+    gboolean ok = TRUE;
+    struct { char *expr, *str; gboolean should_match; } tests[] = {
+       /* examples from amanda(8) */
+       { "hosta", "hosta", TRUE },
+       { "hosta", "foo.hosta.org", TRUE },
+       { "hosta", "hOsTA.domain.org", TRUE },
+       { "hosta", "hostb", FALSE },
+       { "host", "host", TRUE },
+       { "host", "hosta", FALSE },
+       { "host?", "hosta", TRUE },
+       { "host?", "host", FALSE },
+       { "ho*na", "hoina", TRUE },
+       { "ho*na", "ho.aina.org", FALSE },
+       { "ho**na", "hoina", TRUE },
+       { "ho**na", "ho.aina.org", TRUE },
+       { "^hosta", "hosta", TRUE },
+       { "^hosta", "hosta.foo.org", TRUE },
+       { "^hosta", "foo.hosta.org", FALSE },
+
+       { ".hosta.", "hosta", TRUE },
+       { ".hosta.", "foo.hosta", TRUE },
+       { ".hosta.", "hosta.org", TRUE },
+       { ".hosta.", "foo.hosta.org", TRUE },
+       { "/hosta", "hosta", FALSE },
+       { "/hosta", "foo.hosta", FALSE },
+       { "/hosta", "hosta.org", FALSE },
+       { "/hosta", "foo.hosta.org", FALSE },
+
+       /* additional checks */
+       { "^hosta$", "hosta", TRUE },
+       { "^hosta$", "foo.hosta", FALSE },
+       { "^hosta$", "hosta.org", FALSE },
+       { "^hosta$", "foo.hosta.org", FALSE },
+
+       { "^lu.vis.ta$", "lu.vis.ta", TRUE },
+       { "^lu.vis.ta$", "lu-vis.ta", FALSE },
+       { "^lu.vis.ta$", "luvista", FALSE },
+       { "^lu.vis.ta$", "foo.lu.vis.ta", FALSE },
+       { "^lu.vis.ta$", "lu.vis.ta.org", FALSE },
+       { "^lu.vis.ta$", "foo.lu.vis.ta.org", FALSE },
+
+       { "mo[st]a", "mota", TRUE },
+       { "mo[st]a", "mosa", TRUE },
+       { "mo[st]a", "mosta", FALSE },
+       { "mo[!st]a", "mota", FALSE },
+       { "mo[!st]a", "moma", TRUE },
+       { "mo[!st]a", "momma", FALSE },
+
+       { NULL, NULL, FALSE },
+    }, *t;
+
+    for (t = tests; t->expr; t++) {
+       gboolean matched = match_host(t->expr, t->str);
+       if (!!matched != !!t->should_match) {
+           ok = FALSE;
+           if (t->should_match) {
+               g_fprintf(stderr, "%s should have matched host expr %s\n",
+                       t->str, t->expr);
+           } else {
+               g_fprintf(stderr, "%s unexpectedly matched host expr %s\n",
+                       t->str, t->expr);
+           }
+       }
+    }
+
+    return ok;
+}
+
+/****
+ * Test some disk expressions
+ */
+static int
+test_disk_match(void)
+{
+    gboolean ok = TRUE;
+    struct { char *expr, *str; gboolean should_match; } tests[] = {
+       /* examples from amanda(8) */
+       { "sda*", "/dev/sda1", TRUE },
+       { "sda*", "/dev/sda12", TRUE },
+       { "opt", "opt", TRUE },
+       { "opt", "/opt", TRUE },
+       { "opt", "/opt/foo", TRUE },
+       { "opt", "opt/foo", TRUE },
+       { "/", "/", TRUE },
+       { "/", "/opt", FALSE },
+       { "/", "/opt/var", FALSE },
+       { "/usr", "/", FALSE },
+       { "/usr", "/usr", TRUE },
+       { "/usr", "/usr/local", TRUE },
+       { "/usr$", "/", FALSE },
+       { "/usr$", "/usr", TRUE },
+       { "/usr$", "/usr/local", FALSE },
+       { "share", "//windows1/share", TRUE },
+       { "share", "//windows2/share", TRUE },
+       { "share", "\\\\windows1\\share", TRUE },
+       { "share", "\\\\windows2\\share", TRUE },
+       { "share*", "//windows/share1", TRUE },
+       { "share*", "//windows/share2", TRUE },
+       { "share*", "\\\\windows\\share1", TRUE },
+       { "share*", "\\\\windows\\share2", TRUE },
+       { "//windows/share", "//windows/share", TRUE },
+       { "//windows/share", "\\\\windows\\share", TRUE },
+
+       /* and now things get murky */
+       { "\\\\windows\\share", "//windows/share", FALSE },
+       { "\\\\windows\\share", "\\\\windows\\share", FALSE },
+       { "\\\\\\\\windows\\\\share", "//windows/share", FALSE },
+       { "\\\\\\\\windows\\\\share", "\\\\windows\\share", TRUE },
+
+       /* longer expressions */
+       { "local/var", "/local/var", TRUE },
+       { "local/var", "/opt/local/var", TRUE },
+       { "local/var", "/local/var/lib", TRUE },
+       { "local/var", "/local/usr/var", FALSE },
+
+       /* trailing slashes */
+       { "/usr/bin", "/usr/bin", TRUE },
+       { "/usr/bin", "/usr/bin/", TRUE },
+       { "/usr/bin/", "/usr/bin", TRUE },
+       { "/usr/bin/", "/usr/bin/", TRUE },
+       { "/usr/bin", "/usr/bin//", TRUE },
+       { "/usr/bin//", "/usr/bin", FALSE },
+       { "/usr/bin//", "/usr/bin//", TRUE },
+
+       /* quoting '/' is weird: it doesn't work on the leading slash.  Note that
+        * the documentation does not specify how to quote metacharacters in a host
+        * or disk expression. */
+       { "/usr\\/bin", "/usr/bin", TRUE },
+       { "^/usr\\/bin$", "/usr/bin", TRUE },
+       { "\\/usr\\/bin", "/usr/bin", FALSE },
+       { "^\\/usr\\/bin$", "/usr/bin", FALSE },
+
+       { NULL, NULL, FALSE },
+    }, *t;
+
+    for (t = tests; t->expr; t++) {
+       gboolean matched = match_disk(t->expr, t->str);
+       if (!!matched != !!t->should_match) {
+           ok = FALSE;
+           if (t->should_match) {
+               g_fprintf(stderr, "%s should have matched disk expr %s\n",
+                       t->str, t->expr);
+           } else {
+               g_fprintf(stderr, "%s unexpectedly matched disk expr %s\n",
+                       t->str, t->expr);
+           }
+       }
+    }
+
+    return ok;
+}
+
+/****
+ * Test make_exact_host_expression
+ */
+static int
+test_make_exact_host_expression(void)
+{
+    gboolean ok = TRUE;
+    guint i, j;
+    const char *test_strs[] = {
+       "host",
+       "host.org",
+       "host.host.org",
+       /* note that these will inter-match: */
+       /*
+       ".host",
+       ".host.org",
+       ".host.host.org",
+       "host.",
+       "host.org.",
+       "host.host.org.",
+       */
+       "org",
+       "^host",
+       "host$",
+       "^host$",
+       "ho[s]t",
+       "ho[!s]t",
+       "ho\\st",
+       "ho/st",
+       "ho?t",
+       "h*t",
+       "h**t",
+    };
+
+    for (i = 0; i < G_N_ELEMENTS(test_strs); i++) {
+       for (j = 0; j < G_N_ELEMENTS(test_strs); j++) {
+           char *expr = make_exact_host_expression(test_strs[i]);
+           gboolean matched = match_host(expr, test_strs[j]);
+           if (!!matched != !!(i == j)) {
+               ok = FALSE;
+               if (matched) {
+                   g_fprintf(stderr, "expr %s for str %s unexpectedly matched %s\n",
+                           expr, test_strs[i], test_strs[j]);
+               } else {
+                   g_fprintf(stderr, "expr %s for str %s should have matched %s\n",
+                           expr, test_strs[i], test_strs[j]);
+               }
+           }
+       }
+    }
+
+    return ok;
+}
+
+/****
+ * Test make_exact_disk_expression
+ */
+static int
+test_make_exact_disk_expression(void)
+{
+    gboolean ok = TRUE;
+    guint i, j;
+    const char *test_strs[] = {
+       "/disk",
+       "/disk/disk",
+       "d[i]sk",
+       "d**k",
+       "d*k",
+       "d?sk",
+       "d.sk",
+       "d[!pqr]sk",
+       "^disk",
+       "disk$",
+       "^disk$",
+       /* these intermatch due to some special-casing */
+       /*
+       "//windows/share",
+       "\\\\windows\\share",
+       */
+    };
+
+    for (i = 0; i < G_N_ELEMENTS(test_strs); i++) {
+       for (j = 0; j < G_N_ELEMENTS(test_strs); j++) {
+           char *expr = make_exact_disk_expression(test_strs[i]);
+           gboolean matched = match_disk(expr, test_strs[j]);
+           if (!!matched != !!(i == j)) {
+               ok = FALSE;
+               if (matched) {
+                   g_fprintf(stderr, "expr %s for str %s unexpectedly matched %s\n",
+                           expr, test_strs[i], test_strs[j]);
+               } else {
+                   g_fprintf(stderr, "expr %s for str %s should have matched %s\n",
+                           expr, test_strs[i], test_strs[j]);
+               }
+           }
+       }
+    }
+
+    return ok;
+}
+
+/*
+ * Main driver
+ */
+
+int
+main(int argc, char **argv)
+{
+    static TestUtilsTest tests[] = {
+       TU_TEST(test_host_match, 90),
+       TU_TEST(test_disk_match, 90),
+       TU_TEST(test_make_exact_host_expression, 90),
+       TU_TEST(test_make_exact_disk_expression, 90),
+       TU_END()
+    };
+
+    return testutils_run_tests(argc, argv, tests);
+}
+