f95598e27dcf222be6ef0dfe42f80e3e9f137d7c
1 /*
2 * SysDB - t/core/store_lookup_test.c
3 * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
28 #include "core/store.h"
29 #include "libsysdb_test.h"
31 #include <check.h>
32 #include <string.h>
34 static void
35 populate(void)
36 {
37 const char *hosts[] = { "a", "b", "c" };
39 struct {
40 const char *host;
41 const char *service;
42 } services[] = {
43 { "a", "s1" },
44 { "a", "s2" },
45 { "b", "s1" },
46 { "b", "s3" },
47 };
49 struct {
50 const char *host;
51 const char *name;
52 sdb_data_t value;
53 } attrs[] = {
54 { "a", "k1", { SDB_TYPE_STRING, { .string = "v1" } } },
55 };
57 size_t i;
59 for (i = 0; i < SDB_STATIC_ARRAY_LEN(hosts); ++i) {
60 int status = sdb_store_host(hosts[i], 1);
61 fail_unless(status == 0,
62 "sdb_store_host(%s, 1) = %d; expected: 0",
63 hosts[i], status);
64 }
66 for (i = 0; i < SDB_STATIC_ARRAY_LEN(services); ++i) {
67 int status = sdb_store_service(services[i].host,
68 services[i].service, 1);
69 fail_unless(status == 0,
70 "sdb_store_service(%s, %s, 1) = %d; expected: 0",
71 services[i].host, services[i].service, status);
72 }
74 for (i = 0; i < SDB_STATIC_ARRAY_LEN(attrs); ++i) {
75 int status = sdb_store_attribute(attrs[i].host,
76 attrs[i].name, &attrs[i].value, 1);
77 fail_unless(status == 0,
78 "sdb_store_attribute(%s, %s, <val>, 1) = %d; expected: 0",
79 attrs[i].host, attrs[i].name, status);
80 }
81 } /* populate */
83 START_TEST(test_store_match)
84 {
85 sdb_store_base_t *obj;
87 struct {
88 const char *hostname;
89 const char *hostname_re;
91 const char *service_name;
92 const char *service_name_re;
94 const char *attr_name;
95 const char *attr_name_re;
96 const char *attr_value;
97 const char *attr_value_re;
99 int expected;
100 } golden_data[] = {
101 {
102 /* host */ NULL, NULL,
103 /* svc */ NULL, NULL,
104 /* attr */ NULL, NULL, NULL, NULL, 1
105 },
106 {
107 /* host */ "a", NULL,
108 /* svc */ NULL, NULL,
109 /* attr */ NULL, NULL, NULL, NULL, 1
110 },
111 {
112 /* host */ "b", NULL,
113 /* svc */ NULL, NULL,
114 /* attr */ NULL, NULL, NULL, NULL, 0
115 },
116 {
117 /* host */ NULL, "^a$",
118 /* svc */ NULL, NULL,
119 /* attr */ NULL, NULL, NULL, NULL, 1
120 },
121 {
122 /* host */ NULL, "^b$",
123 /* svc */ NULL, NULL,
124 /* attr */ NULL, NULL, NULL, NULL, 0
125 },
126 {
127 /* host */ "a", "^a$",
128 /* svc */ NULL, NULL,
129 /* attr */ NULL, NULL, NULL, NULL, 1
130 },
131 {
132 /* host */ "a", "^b$",
133 /* svc */ NULL, NULL,
134 /* attr */ NULL, NULL, NULL, NULL, 0
135 },
136 {
137 /* host */ "b", "^a$",
138 /* svc */ NULL, NULL,
139 /* attr */ NULL, NULL, NULL, NULL, 0
140 },
141 {
142 /* host */ "a", "^a$",
143 /* svc */ "s1", NULL,
144 /* attr */ NULL, NULL, NULL, NULL, 1
145 },
146 {
147 /* host */ "a", "^a$",
148 /* svc */ NULL, "^s1$",
149 /* attr */ NULL, NULL, NULL, NULL, 1
150 },
151 {
152 /* host */ "a", "^a$",
153 /* svc */ "s1", "^s1$",
154 /* attr */ NULL, NULL, NULL, NULL, 1
155 },
156 {
157 /* host */ "a", "^a$",
158 /* svc */ "x1", NULL,
159 /* attr */ NULL, NULL, NULL, NULL, 0
160 },
161 {
162 /* host */ "a", "^a$",
163 /* svc */ NULL, "x",
164 /* attr */ NULL, NULL, NULL, NULL, 0
165 },
166 {
167 /* host */ "a", "^a$",
168 /* svc */ "x1", "x",
169 /* attr */ NULL, NULL, NULL, NULL, 0
170 },
171 {
172 /* host */ "a", "^a$",
173 /* svc */ "s1", "x",
174 /* attr */ NULL, NULL, NULL, NULL, 0
175 },
176 {
177 /* host */ "a", "^a$",
178 /* svc */ "x1", "s",
179 /* attr */ NULL, NULL, NULL, NULL, 0
180 },
181 {
182 /* host */ "a", "^a$",
183 /* svc */ "s1", "^s1$",
184 /* attr */ "k1", NULL, NULL, NULL, 1
185 },
186 {
187 /* host */ "a", "^a$",
188 /* svc */ "s1", "^s1$",
189 /* attr */ NULL, "^k", NULL, NULL, 1
190 },
191 {
192 /* host */ "a", "^a$",
193 /* svc */ "s1", "^s1$",
194 /* attr */ NULL, NULL, "v1", NULL, 1
195 },
196 {
197 /* host */ "a", "^a$",
198 /* svc */ "s1", "^s1$",
199 /* attr */ NULL, NULL, NULL, "^v1$", 1
200 },
201 {
202 /* host */ "a", "^a$",
203 /* svc */ "s1", "^s1$",
204 /* attr */ "k1", "1", "v1", "1", 1
205 },
206 };
208 size_t i;
210 obj = sdb_store_get_host("a");
211 fail_unless(obj != NULL,
212 "sdb_store_get_host(a) = NULL; expected: <host>");
214 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
215 sdb_store_matcher_t *h, *s, *a;
216 int status;
218 s = sdb_store_service_matcher(golden_data[i].service_name,
219 golden_data[i].service_name_re, NULL);
220 fail_unless(s != NULL,
221 "sdb_store_service_matcher() = NULL; expected: <matcher>");
223 a = sdb_store_attr_matcher(golden_data[i].attr_name,
224 golden_data[i].attr_name_re, golden_data[i].attr_value,
225 golden_data[i].attr_value_re);
226 fail_unless(a != NULL,
227 "sdb_store_attr_matcher() = NULL; expected: <matcher>");
229 h = sdb_store_host_matcher(golden_data[i].hostname,
230 golden_data[i].hostname_re, s, a);
231 fail_unless(h != NULL,
232 "sdb_store_host_matcher() = NULL: expected: <matcher>");
233 /* pass ownership to the host matcher */
234 sdb_object_deref(SDB_OBJ(s));
235 sdb_object_deref(SDB_OBJ(a));
237 status = sdb_store_matcher_matches(h, obj);
238 fail_unless(status == golden_data[i].expected,
239 "sdb_store_matcher_matches({{%s, %s},{%s, %s},"
240 "{%s, %s, %s, %s}}, <host a>) = %d; expected: %d",
241 golden_data[i].hostname, golden_data[i].hostname_re,
242 golden_data[i].service_name, golden_data[i].service_name_re,
243 golden_data[i].attr_name, golden_data[i].attr_name_re,
244 golden_data[i].attr_value, golden_data[i].attr_value_re,
245 status, golden_data[i].expected);
247 sdb_object_deref(SDB_OBJ(h));
248 }
249 }
250 END_TEST
252 START_TEST(test_store_match_op)
253 {
254 sdb_store_base_t *obj;
256 sdb_store_matcher_t *always = sdb_store_host_matcher(NULL, NULL, NULL, NULL);
257 sdb_store_matcher_t *never = sdb_store_host_matcher("a", "b", NULL, NULL);
259 struct {
260 const char *op;
261 sdb_store_matcher_t *left;
262 sdb_store_matcher_t *right;
263 int expected;
264 } golden_data[] = {
265 { "OR", always, always, 1 },
266 { "OR", always, never, 1 },
267 { "OR", never, always, 1 },
268 { "OR", never, never, 0 },
269 { "AND", always, always, 1 },
270 { "AND", always, never, 0 },
271 { "AND", never, always, 0 },
272 { "AND", never, never, 0 },
273 };
275 int status;
276 size_t i;
278 obj = sdb_store_get_host("a");
280 status = sdb_store_matcher_matches(always, obj);
281 fail_unless(status == 1,
282 "INTERNAL ERROR: 'always' did not match host");
283 status = sdb_store_matcher_matches(never, obj);
284 fail_unless(status == 0,
285 "INTERNAL ERROR: 'never' matches host");
287 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
288 sdb_store_matcher_t *m;
290 if (! strcmp(golden_data[i].op, "OR"))
291 m = sdb_store_dis_matcher(golden_data[i].left,
292 golden_data[i].right);
293 else if (! strcmp(golden_data[i].op, "AND"))
294 m = sdb_store_con_matcher(golden_data[i].left,
295 golden_data[i].right);
296 else {
297 fail("INTERNAL ERROR: unexpected operator %s", golden_data[i].op);
298 continue;
299 }
301 #define TO_NAME(v) (((v) == always) ? "always" \
302 : ((v) == never) ? "never" : "<unknown>")
304 status = sdb_store_matcher_matches(m, obj);
305 fail_unless(status == golden_data[i].expected,
306 "%s(%s, %s) = %d; expected: %d", golden_data[i].op,
307 TO_NAME(golden_data[i].left), TO_NAME(golden_data[i].right),
308 status, golden_data[i].expected);
310 #undef TO_NAME
312 sdb_object_deref(SDB_OBJ(m));
313 }
315 sdb_object_deref(SDB_OBJ(always));
316 sdb_object_deref(SDB_OBJ(never));
317 }
318 END_TEST
320 static int
321 lookup_cb(sdb_store_base_t *obj, void *user_data)
322 {
323 intptr_t *i = user_data;
325 fail_unless(obj != NULL,
326 "sdb_store_lookup callback received NULL obj; expected: "
327 "<store base obj>");
328 fail_unless(i != NULL,
329 "sdb_store_lookup callback received NULL user_data; "
330 "expected: <pointer to data>");
332 ++(*i);
333 return 0;
334 } /* lookup_cb */
336 START_TEST(test_lookup)
337 {
338 intptr_t i = 0;
339 int check;
341 check = sdb_store_lookup(NULL, lookup_cb, &i);
342 fail_unless(check == 0,
343 "sdb_store_lookup() = %d; expected: 0", check);
344 fail_unless(i == 3,
345 "sdb_store_lookup called callback %d times; expected: 3", (int)i);
346 }
347 END_TEST
349 Suite *
350 core_store_lookup_suite(void)
351 {
352 Suite *s = suite_create("core::store_lookup");
353 TCase *tc;
355 tc = tcase_create("core");
356 tcase_add_checked_fixture(tc, populate, sdb_store_clear);
357 tcase_add_test(tc, test_store_match);
358 tcase_add_test(tc, test_store_match_op);
359 tcase_add_test(tc, test_lookup);
360 suite_add_tcase(s, tc);
362 return s;
363 } /* core_store_lookup_suite */
365 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */