Code

store_lookup: Added sdb_store_inv_matcher().
[sysdb.git] / t / core / store_lookup_test.c
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 "core/store-private.h"
30 #include "libsysdb_test.h"
32 #include <check.h>
33 #include <string.h>
35 static void
36 populate(void)
37 {
38         const char *hosts[] = { "a", "b", "c" };
40         struct {
41                 const char *host;
42                 const char *service;
43         } services[] = {
44                 { "a", "s1" },
45                 { "a", "s2" },
46                 { "b", "s1" },
47                 { "b", "s3" },
48         };
50         struct {
51                 const char *host;
52                 const char *name;
53                 sdb_data_t  value;
54         } attrs[] = {
55                 { "a", "k1", { SDB_TYPE_STRING, { .string = "v1" } } },
56         };
58         size_t i;
60         for (i = 0; i < SDB_STATIC_ARRAY_LEN(hosts); ++i) {
61                 int status = sdb_store_host(hosts[i], 1);
62                 fail_unless(status == 0,
63                                 "sdb_store_host(%s, 1) = %d; expected: 0",
64                                 hosts[i], status);
65         }
67         for (i = 0; i < SDB_STATIC_ARRAY_LEN(services); ++i) {
68                 int status = sdb_store_service(services[i].host,
69                                 services[i].service, 1);
70                 fail_unless(status == 0,
71                                 "sdb_store_service(%s, %s, 1) = %d; expected: 0",
72                                 services[i].host, services[i].service, status);
73         }
75         for (i = 0; i < SDB_STATIC_ARRAY_LEN(attrs); ++i) {
76                 int status = sdb_store_attribute(attrs[i].host,
77                                 attrs[i].name, &attrs[i].value, 1);
78                 fail_unless(status == 0,
79                                 "sdb_store_attribute(%s, %s, <val>, 1) = %d; expected: 0",
80                                 attrs[i].host, attrs[i].name, status);
81         }
82 } /* populate */
84 START_TEST(test_store_match)
85 {
86         sdb_store_base_t *obj;
88         struct {
89                 const char *hostname;
90                 const char *hostname_re;
92                 const char *service_name;
93                 const char *service_name_re;
95                 const char *attr_name;
96                 const char *attr_name_re;
97                 const char *attr_value;
98                 const char *attr_value_re;
100                 int expected;
101         } golden_data[] = {
102                 {
103                         /* host */ NULL, NULL,
104                         /* svc  */ NULL, NULL,
105                         /* attr */ NULL, NULL, NULL, NULL, 1
106                 },
107                 {
108                         /* host */ "a", NULL,
109                         /* svc  */ NULL, NULL,
110                         /* attr */ NULL, NULL, NULL, NULL, 1
111                 },
112                 {
113                         /* host */ "b", NULL,
114                         /* svc  */ NULL, NULL,
115                         /* attr */ NULL, NULL, NULL, NULL, 0
116                 },
117                 {
118                         /* host */ NULL, "^a$",
119                         /* svc  */ NULL, NULL,
120                         /* attr */ NULL, NULL, NULL, NULL, 1
121                 },
122                 {
123                         /* host */ NULL, "^b$",
124                         /* svc  */ NULL, NULL,
125                         /* attr */ NULL, NULL, NULL, NULL, 0
126                 },
127                 {
128                         /* host */ "a", "^a$",
129                         /* svc  */ NULL, NULL,
130                         /* attr */ NULL, NULL, NULL, NULL, 1
131                 },
132                 {
133                         /* host */ "a", "^b$",
134                         /* svc  */ NULL, NULL,
135                         /* attr */ NULL, NULL, NULL, NULL, 0
136                 },
137                 {
138                         /* host */ "b", "^a$",
139                         /* svc  */ NULL, NULL,
140                         /* attr */ NULL, NULL, NULL, NULL, 0
141                 },
142                 {
143                         /* host */ "a", "^a$",
144                         /* svc  */ "s1", NULL,
145                         /* attr */ NULL, NULL, NULL, NULL, 1
146                 },
147                 {
148                         /* host */ "a", "^a$",
149                         /* svc  */ NULL, "^s1$",
150                         /* attr */ NULL, NULL, NULL, NULL, 1
151                 },
152                 {
153                         /* host */ "a", "^a$",
154                         /* svc  */ "s1", "^s1$",
155                         /* attr */ NULL, NULL, NULL, NULL, 1
156                 },
157                 {
158                         /* host */ "a", "^a$",
159                         /* svc  */ "x1", NULL,
160                         /* attr */ NULL, NULL, NULL, NULL, 0
161                 },
162                 {
163                         /* host */ "a", "^a$",
164                         /* svc  */ NULL, "x",
165                         /* attr */ NULL, NULL, NULL, NULL, 0
166                 },
167                 {
168                         /* host */ "a", "^a$",
169                         /* svc  */ "x1", "x",
170                         /* attr */ NULL, NULL, NULL, NULL, 0
171                 },
172                 {
173                         /* host */ "a", "^a$",
174                         /* svc  */ "s1", "x",
175                         /* attr */ NULL, NULL, NULL, NULL, 0
176                 },
177                 {
178                         /* host */ "a", "^a$",
179                         /* svc  */ "x1", "s",
180                         /* attr */ NULL, NULL, NULL, NULL, 0
181                 },
182                 {
183                         /* host */ "a", "^a$",
184                         /* svc  */ "s1", "^s1$",
185                         /* attr */ "k1", NULL, NULL, NULL, 1
186                 },
187                 {
188                         /* host */ "a", "^a$",
189                         /* svc  */ "s1", "^s1$",
190                         /* attr */ NULL, "^k", NULL, NULL, 1
191                 },
192                 {
193                         /* host */ "a", "^a$",
194                         /* svc  */ "s1", "^s1$",
195                         /* attr */ NULL, NULL, "v1", NULL, 1
196                 },
197                 {
198                         /* host */ "a", "^a$",
199                         /* svc  */ "s1", "^s1$",
200                         /* attr */ NULL, NULL, NULL, "^v1$", 1
201                 },
202                 {
203                         /* host */ "a", "^a$",
204                         /* svc  */ "s1", "^s1$",
205                         /* attr */ "k1", "1", "v1", "1", 1
206                 },
207         };
209         size_t i;
211         obj = sdb_store_get_host("a");
212         fail_unless(obj != NULL,
213                         "sdb_store_get_host(a) = NULL; expected: <host>");
215         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
216                 sdb_store_matcher_t *h, *s, *a, *n;
217                 int status;
219                 s = sdb_store_service_matcher(golden_data[i].service_name,
220                                 golden_data[i].service_name_re, NULL);
221                 fail_unless(s != NULL,
222                                 "sdb_store_service_matcher() = NULL; expected: <matcher>");
224                 a = sdb_store_attr_matcher(golden_data[i].attr_name,
225                                 golden_data[i].attr_name_re, golden_data[i].attr_value,
226                                 golden_data[i].attr_value_re);
227                 fail_unless(a != NULL,
228                                 "sdb_store_attr_matcher() = NULL; expected: <matcher>");
230                 h = sdb_store_host_matcher(golden_data[i].hostname,
231                                 golden_data[i].hostname_re, s, a);
232                 fail_unless(h != NULL,
233                                 "sdb_store_host_matcher() = NULL: expected: <matcher>");
234                 /* pass ownership to the host matcher */
235                 sdb_object_deref(SDB_OBJ(s));
236                 sdb_object_deref(SDB_OBJ(a));
238                 status = sdb_store_matcher_matches(h, obj);
239                 fail_unless(status == golden_data[i].expected,
240                                 "sdb_store_matcher_matches({{%s, %s},{%s, %s},"
241                                 "{%s, %s, %s, %s}}, <host a>) = %d; expected: %d",
242                                 golden_data[i].hostname, golden_data[i].hostname_re,
243                                 golden_data[i].service_name, golden_data[i].service_name_re,
244                                 golden_data[i].attr_name, golden_data[i].attr_name_re,
245                                 golden_data[i].attr_value, golden_data[i].attr_value_re,
246                                 status, golden_data[i].expected);
248                 n = sdb_store_inv_matcher(h);
249                 fail_unless(n != NULL,
250                                 "sdb_store_inv_matcher() = NULL; expected: <matcher>");
251                 sdb_object_deref(SDB_OBJ(h));
253                 /* now match the inverted set of objects */
254                 status = sdb_store_matcher_matches(n, obj);
255                 fail_unless(status == !golden_data[i].expected,
256                                 "sdb_store_matcher_matches(NOT{{%s, %s},{%s, %s},"
257                                 "{%s, %s, %s, %s}}, <host a>) = %d; expected: %d",
258                                 golden_data[i].hostname, golden_data[i].hostname_re,
259                                 golden_data[i].service_name, golden_data[i].service_name_re,
260                                 golden_data[i].attr_name, golden_data[i].attr_name_re,
261                                 golden_data[i].attr_value, golden_data[i].attr_value_re,
262                                 status, !golden_data[i].expected);
264                 sdb_object_deref(SDB_OBJ(n));
265         }
267 END_TEST
269 START_TEST(test_store_match_op)
271         sdb_store_base_t *obj;
273         sdb_store_matcher_t *always = sdb_store_host_matcher(NULL, NULL, NULL, NULL);
274         sdb_store_matcher_t *never = sdb_store_host_matcher("a", "b", NULL, NULL);
276         struct {
277                 const char *op;
278                 sdb_store_matcher_t *left;
279                 sdb_store_matcher_t *right;
280                 int expected;
281         } golden_data[] = {
282                 { "OR",  always, always, 1 },
283                 { "OR",  always, never,  1 },
284                 { "OR",  never,  always, 1 },
285                 { "OR",  never,  never,  0 },
286                 { "AND", always, always, 1 },
287                 { "AND", always, never,  0 },
288                 { "AND", never,  always, 0 },
289                 { "AND", never,  never,  0 },
290         };
292         int status;
293         size_t i;
295         obj = sdb_store_get_host("a");
297         status = sdb_store_matcher_matches(always, obj);
298         fail_unless(status == 1,
299                         "INTERNAL ERROR: 'always' did not match host");
300         status = sdb_store_matcher_matches(never, obj);
301         fail_unless(status == 0,
302                         "INTERNAL ERROR: 'never' matches host");
304         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
305                 sdb_store_matcher_t *m;
307                 if (! strcmp(golden_data[i].op, "OR"))
308                         m = sdb_store_dis_matcher(golden_data[i].left,
309                                         golden_data[i].right);
310                 else if (! strcmp(golden_data[i].op, "AND"))
311                         m = sdb_store_con_matcher(golden_data[i].left,
312                                         golden_data[i].right);
313                 else {
314                         fail("INTERNAL ERROR: unexpected operator %s", golden_data[i].op);
315                         continue;
316                 }
318 #define TO_NAME(v) (((v) == always) ? "always" \
319                 : ((v) == never) ? "never" : "<unknown>")
321                 status = sdb_store_matcher_matches(m, obj);
322                 fail_unless(status == golden_data[i].expected,
323                                 "%s(%s, %s) = %d; expected: %d", golden_data[i].op,
324                                 TO_NAME(golden_data[i].left), TO_NAME(golden_data[i].right),
325                                 status, golden_data[i].expected);
327 #undef TO_NAME
329                 sdb_object_deref(SDB_OBJ(m));
330         }
332         sdb_object_deref(SDB_OBJ(always));
333         sdb_object_deref(SDB_OBJ(never));
335 END_TEST
337 START_TEST(test_parse_cmp)
339         sdb_store_matcher_t *check;
341         size_t i;
343         struct {
344                 const char *obj_type;
345                 const char *attr;
346                 const char *op;
347                 const char *value;
348                 int expected;
349         } golden_data[] = {
350                 { "host",      "name", "=",  "hostname", MATCHER_HOST },
351                 { "host",      "name", "=~", "hostname", MATCHER_HOST },
352                 { "host",      "attr", "=",  "hostname", -1 },
353                 { "host",      "name", "&^", "hostname", -1 },
354                 { "service",   "name", "=",  "srvname",  MATCHER_SERVICE },
355                 { "service",   "name", "=",  "srvname",  MATCHER_SERVICE },
356                 { "service",   "attr", "=",  "srvname",  -1 },
357                 { "service",   "name", "&^", "srvname",  -1 },
358                 { "attribute", "name", "=",  "attrname", MATCHER_ATTR },
359                 { "attribute", "name", "=~", "attrname", MATCHER_ATTR },
360                 { "attribute", "attr", "=",  "attrname", MATCHER_ATTR },
361                 { "attribute", "attr", "=~", "attrname", MATCHER_ATTR },
362                 { "attribute", "attr", "&^", "attrname", -1 },
363         };
365         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
366                 check = sdb_store_matcher_parse_cmp(golden_data[i].obj_type,
367                                 golden_data[i].attr, golden_data[i].op, golden_data[i].value);
369                 if (golden_data[i].expected == -1) {
370                         fail_unless(check == NULL,
371                                         "sdb_store_matcher_parse_cmp(%s, %s, %s, %s) = %p; "
372                                         "expected: NULL", golden_data[i].obj_type,
373                                         golden_data[i].attr, golden_data[i].op,
374                                         golden_data[i].value, check);
375                         continue;
376                 }
378                 fail_unless(check != NULL,
379                                 "sdb_store_matcher_parse_cmp(%s, %s, %s, %s) = %p; "
380                                 "expected: NULL", golden_data[i].obj_type,
381                                 golden_data[i].attr, golden_data[i].op,
382                                 golden_data[i].value, check);
383                 fail_unless(M(check)->type == golden_data[i].expected,
384                                 "sdb_store_matcher_parse_cmp(%s, %s, %s, %s) returned matcher "
385                                 "of type %d; expected: %d", golden_data[i].obj_type,
386                                 golden_data[i].attr, golden_data[i].op, golden_data[i].value,
387                                 M(check)->type, golden_data[i].expected);
389                 sdb_object_deref(SDB_OBJ(check));
390         }
392 END_TEST
394 static int
395 lookup_cb(sdb_store_base_t *obj, void *user_data)
397         intptr_t *i = user_data;
399         fail_unless(obj != NULL,
400                         "sdb_store_lookup callback received NULL obj; expected: "
401                         "<store base obj>");
402         fail_unless(i != NULL,
403                         "sdb_store_lookup callback received NULL user_data; "
404                         "expected: <pointer to data>");
406         ++(*i);
407         return 0;
408 } /* lookup_cb */
410 START_TEST(test_lookup)
412         intptr_t i = 0;
413         int check;
415         check = sdb_store_lookup(NULL, lookup_cb, &i);
416         fail_unless(check == 0,
417                         "sdb_store_lookup() = %d; expected: 0", check);
418         fail_unless(i == 3,
419                         "sdb_store_lookup called callback %d times; expected: 3", (int)i);
421 END_TEST
423 Suite *
424 core_store_lookup_suite(void)
426         Suite *s = suite_create("core::store_lookup");
427         TCase *tc;
429         tc = tcase_create("core");
430         tcase_add_checked_fixture(tc, populate, sdb_store_clear);
431         tcase_add_test(tc, test_store_match);
432         tcase_add_test(tc, test_store_match_op);
433         tcase_add_test(tc, test_parse_cmp);
434         tcase_add_test(tc, test_lookup);
435         suite_add_tcase(s, tc);
437         return s;
438 } /* core_store_lookup_suite */
440 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */