summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d65300a)
raw | patch | inline | side by side (parent: d65300a)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 23 Feb 2014 04:12:05 +0000 (20:12 -0800) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 23 Feb 2014 04:12:05 +0000 (20:12 -0800) |
src/core/store_lookup.c | patch | blob | history | |
src/include/core/store.h | patch | blob | history | |
t/core/store_lookup_test.c | patch | blob | history |
index 305a513f14dcde6d7d01b54992c5ca24ce9dc39a..d4fef03c39edc9015e37af5ad526d3e80b36c479 100644 (file)
--- a/src/core/store_lookup.c
+++ b/src/core/store_lookup.c
sdb_object_deref(SDB_OBJ(HOST_M(obj)->attr));
} /* host_matcher_destroy */
+static int
+op_matcher_init(sdb_object_t *obj, va_list ap)
+{
+ M(obj)->type = va_arg(ap, int);
+ if ((M(obj)->type != MATCHER_OR) && (M(obj)->type != MATCHER_AND))
+ return -1;
+
+ OP_M(obj)->left = va_arg(ap, sdb_store_matcher_t *);
+ sdb_object_ref(SDB_OBJ(OP_M(obj)->left));
+ OP_M(obj)->right = va_arg(ap, sdb_store_matcher_t *);
+ sdb_object_ref(SDB_OBJ(OP_M(obj)->right));
+
+ if ((! OP_M(obj)->left) || (! OP_M(obj)->right))
+ return -1;
+ return 0;
+} /* op_matcher_init */
+
+static void
+op_matcher_destroy(sdb_object_t *obj)
+{
+ if (OP_M(obj)->left)
+ sdb_object_deref(SDB_OBJ(OP_M(obj)->left));
+ if (OP_M(obj)->right)
+ sdb_object_deref(SDB_OBJ(OP_M(obj)->right));
+} /* op_matcher_destroy */
+
static sdb_type_t attr_type = {
/* size = */ sizeof(attr_matcher_t),
/* init = */ attr_matcher_init,
/* destroy = */ host_matcher_destroy,
};
+static sdb_type_t op_type = {
+ /* size = */ sizeof(op_matcher_t),
+ /* init = */ op_matcher_init,
+ /* destroy = */ op_matcher_destroy,
+};
+
/*
* public API
*/
host_name, host_name_re, service_matcher, attr_matcher));
} /* sdb_store_host_matcher */
+sdb_store_matcher_t *
+sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right)
+{
+ return M(sdb_object_create("dis-matcher", op_type, MATCHER_OR,
+ left, right));
+} /* sdb_store_dis_matcher */
+
+sdb_store_matcher_t *
+sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right)
+{
+ return M(sdb_object_create("con-matcher", op_type, MATCHER_AND,
+ left, right));
+} /* sdb_store_con_matcher */
+
int
sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_base_t *obj)
{
index a327ae9d31ebd31744e4ce6d9d0786b0d183ae29..8c46eb740065cccde034cf39cab73e6e037e9c1e 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
sdb_store_matcher_t *service_matcher,
sdb_store_matcher_t *attr_matcher);
+/*
+ * sdb_store_dis_matcher:
+ * Creates a matcher matching the disjunction (logical OR) of two matchers.
+ */
+sdb_store_matcher_t *
+sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right);
+
+/*
+ * sdb_store_con_matcher:
+ * Creates a matcher matching the conjunction (logical AND) of two matchers.
+ */
+sdb_store_matcher_t *
+sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right);
+
/*
* sdb_store_matcher_matches:
* Check whether the specified matcher matches the specified store object.
index 3d567ac606edf35d475526b19447fe1359f64043..48bb4832f4b81e723743d27cefd1c705e40e93a5 100644 (file)
}
END_TEST
+START_TEST(test_store_match_op)
+{
+ sdb_store_base_t *obj;
+
+ sdb_store_matcher_t *always = sdb_store_host_matcher(NULL, NULL, NULL, NULL);
+ sdb_store_matcher_t *never = sdb_store_host_matcher("a", "b", NULL, NULL);
+
+ struct {
+ const char *op;
+ sdb_store_matcher_t *left;
+ sdb_store_matcher_t *right;
+ int expected;
+ } golden_data[] = {
+ { "OR", always, always, 0 },
+ { "OR", always, never, 0 },
+ { "OR", never, always, 0 },
+ { "OR", never, never, -1 },
+ { "AND", always, always, 0 },
+ { "AND", always, never, -1 },
+ { "AND", never, always, -1 },
+ { "AND", never, never, -1 },
+ };
+
+ int status;
+ size_t i;
+
+ obj = sdb_store_get_host("a");
+
+ status = sdb_store_matcher_matches(always, obj);
+ fail_unless(status == 0,
+ "INTERNAL ERROR: 'always' did not match host");
+ status = sdb_store_matcher_matches(never, obj);
+ fail_unless(status < 0,
+ "INTERNAL ERROR: 'never' matches host");
+
+ for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+ sdb_store_matcher_t *m;
+
+ if (! strcmp(golden_data[i].op, "OR"))
+ m = sdb_store_dis_matcher(golden_data[i].left,
+ golden_data[i].right);
+ else if (! strcmp(golden_data[i].op, "AND"))
+ m = sdb_store_con_matcher(golden_data[i].left,
+ golden_data[i].right);
+ else
+ fail("INTERNAL ERROR: unexpected operator %s", golden_data[i].op);
+
+#define TO_NAME(v) (((v) == always) ? "always" \
+ : ((v) == never) ? "never" : "<unknown>")
+
+ status = sdb_store_matcher_matches(m, obj);
+ fail_unless(status == golden_data[i].expected,
+ "%s(%s, %s) = %d; expected: %d", golden_data[i].op,
+ TO_NAME(golden_data[i].left), TO_NAME(golden_data[i].right),
+ status, golden_data[i].expected);
+
+#undef TO_NAME
+
+ sdb_object_deref(SDB_OBJ(m));
+ }
+
+ sdb_object_deref(SDB_OBJ(always));
+ sdb_object_deref(SDB_OBJ(never));
+}
+END_TEST
+
Suite *
core_store_lookup_suite(void)
{
tc = tcase_create("core");
tcase_add_checked_fixture(tc, populate, sdb_store_clear);
tcase_add_test(tc, test_store_match);
+ tcase_add_test(tc, test_store_match_op);
suite_add_tcase(s, tc);
return s;