Code

15a67b10a7809ac5f92d4a534a99f3600fd1cf65
[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;
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                 sdb_object_deref(SDB_OBJ(h));
249         }
251 END_TEST
253 START_TEST(test_store_match_op)
255         sdb_store_base_t *obj;
257         sdb_store_matcher_t *always = sdb_store_host_matcher(NULL, NULL, NULL, NULL);
258         sdb_store_matcher_t *never = sdb_store_host_matcher("a", "b", NULL, NULL);
260         struct {
261                 const char *op;
262                 sdb_store_matcher_t *left;
263                 sdb_store_matcher_t *right;
264                 int expected;
265         } golden_data[] = {
266                 { "OR",  always, always, 1 },
267                 { "OR",  always, never,  1 },
268                 { "OR",  never,  always, 1 },
269                 { "OR",  never,  never,  0 },
270                 { "AND", always, always, 1 },
271                 { "AND", always, never,  0 },
272                 { "AND", never,  always, 0 },
273                 { "AND", never,  never,  0 },
274         };
276         int status;
277         size_t i;
279         obj = sdb_store_get_host("a");
281         status = sdb_store_matcher_matches(always, obj);
282         fail_unless(status == 1,
283                         "INTERNAL ERROR: 'always' did not match host");
284         status = sdb_store_matcher_matches(never, obj);
285         fail_unless(status == 0,
286                         "INTERNAL ERROR: 'never' matches host");
288         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
289                 sdb_store_matcher_t *m;
291                 if (! strcmp(golden_data[i].op, "OR"))
292                         m = sdb_store_dis_matcher(golden_data[i].left,
293                                         golden_data[i].right);
294                 else if (! strcmp(golden_data[i].op, "AND"))
295                         m = sdb_store_con_matcher(golden_data[i].left,
296                                         golden_data[i].right);
297                 else {
298                         fail("INTERNAL ERROR: unexpected operator %s", golden_data[i].op);
299                         continue;
300                 }
302 #define TO_NAME(v) (((v) == always) ? "always" \
303                 : ((v) == never) ? "never" : "<unknown>")
305                 status = sdb_store_matcher_matches(m, obj);
306                 fail_unless(status == golden_data[i].expected,
307                                 "%s(%s, %s) = %d; expected: %d", golden_data[i].op,
308                                 TO_NAME(golden_data[i].left), TO_NAME(golden_data[i].right),
309                                 status, golden_data[i].expected);
311 #undef TO_NAME
313                 sdb_object_deref(SDB_OBJ(m));
314         }
316         sdb_object_deref(SDB_OBJ(always));
317         sdb_object_deref(SDB_OBJ(never));
319 END_TEST
321 START_TEST(test_parse_cmp)
323         sdb_store_matcher_t *check;
325         size_t i;
327         struct {
328                 const char *obj_type;
329                 const char *attr;
330                 const char *op;
331                 const char *value;
332                 int expected;
333         } golden_data[] = {
334                 { "host",      "name", "=",  "hostname", MATCHER_HOST },
335                 { "host",      "name", "=~", "hostname", MATCHER_HOST },
336                 { "host",      "attr", "=",  "hostname", -1 },
337                 { "host",      "name", "&^", "hostname", -1 },
338                 { "service",   "name", "=",  "srvname",  MATCHER_SERVICE },
339                 { "service",   "name", "=",  "srvname",  MATCHER_SERVICE },
340                 { "service",   "attr", "=",  "srvname",  -1 },
341                 { "service",   "name", "&^", "srvname",  -1 },
342                 { "attribute", "name", "=",  "attrname", MATCHER_ATTR },
343                 { "attribute", "name", "=~", "attrname", MATCHER_ATTR },
344                 { "attribute", "attr", "=",  "attrname", MATCHER_ATTR },
345                 { "attribute", "attr", "=~", "attrname", MATCHER_ATTR },
346                 { "attribute", "attr", "&^", "attrname", -1 },
347         };
349         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
350                 check = sdb_store_matcher_parse_cmp(golden_data[i].obj_type,
351                                 golden_data[i].attr, golden_data[i].op, golden_data[i].value);
353                 if (golden_data[i].expected == -1) {
354                         fail_unless(check == NULL,
355                                         "sdb_store_matcher_parse_cmp(%s, %s, %s, %s) = %p; "
356                                         "expected: NULL", golden_data[i].obj_type,
357                                         golden_data[i].attr, golden_data[i].op,
358                                         golden_data[i].value, check);
359                         continue;
360                 }
362                 fail_unless(check != NULL,
363                                 "sdb_store_matcher_parse_cmp(%s, %s, %s, %s) = %p; "
364                                 "expected: NULL", golden_data[i].obj_type,
365                                 golden_data[i].attr, golden_data[i].op,
366                                 golden_data[i].value, check);
367                 fail_unless(M(check)->type == golden_data[i].expected,
368                                 "sdb_store_matcher_parse_cmp(%s, %s, %s, %s) returned matcher "
369                                 "of type %d; expected: %d", golden_data[i].obj_type,
370                                 golden_data[i].attr, golden_data[i].op, golden_data[i].value,
371                                 M(check)->type, golden_data[i].expected);
373                 sdb_object_deref(SDB_OBJ(check));
374         }
376 END_TEST
378 static int
379 lookup_cb(sdb_store_base_t *obj, void *user_data)
381         intptr_t *i = user_data;
383         fail_unless(obj != NULL,
384                         "sdb_store_lookup callback received NULL obj; expected: "
385                         "<store base obj>");
386         fail_unless(i != NULL,
387                         "sdb_store_lookup callback received NULL user_data; "
388                         "expected: <pointer to data>");
390         ++(*i);
391         return 0;
392 } /* lookup_cb */
394 START_TEST(test_lookup)
396         intptr_t i = 0;
397         int check;
399         check = sdb_store_lookup(NULL, lookup_cb, &i);
400         fail_unless(check == 0,
401                         "sdb_store_lookup() = %d; expected: 0", check);
402         fail_unless(i == 3,
403                         "sdb_store_lookup called callback %d times; expected: 3", (int)i);
405 END_TEST
407 Suite *
408 core_store_lookup_suite(void)
410         Suite *s = suite_create("core::store_lookup");
411         TCase *tc;
413         tc = tcase_create("core");
414         tcase_add_checked_fixture(tc, populate, sdb_store_clear);
415         tcase_add_test(tc, test_store_match);
416         tcase_add_test(tc, test_store_match_op);
417         tcase_add_test(tc, test_parse_cmp);
418         tcase_add_test(tc, test_lookup);
419         suite_add_tcase(s, tc);
421         return s;
422 } /* core_store_lookup_suite */
424 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */