Code

store: Added support for different data-types for attributes.
[sysdb.git] / t / core / store_test.c
1 /*
2  * SysDB - t/core/store_test.c
3  * Copyright (C) 2013 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 START_TEST(test_store_host)
35 {
36         struct {
37                 const char *name;
38                 sdb_time_t  last_update;
39                 int         expected;
40         } golden_data[] = {
41                 { "a", 2, 0 },
42                 { "a", 3, 0 },
43                 { "a", 1, 1 },
44                 { "b", 2, 0 },
45                 { "b", 1, 1 },
46                 { "A", 1, 1 }, /* case-insensitive */
47                 { "A", 4, 0 },
48         };
50         struct {
51                 const char *name;
52                 _Bool       has;
53         } golden_hosts[] = {
54                 { "a", 1 == 1 },
55                 { "b", 1 == 1 },
56                 { "c", 0 == 1 },
57                 { "A", 1 == 1 },
58         };
60         size_t i;
62         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
63                 int status;
65                 status = sdb_store_host(golden_data[i].name,
66                                 golden_data[i].last_update);
67                 fail_unless(status == golden_data[i].expected,
68                                 "sdb_store_host(%s, %d) = %d; expected: %d",
69                                 golden_data[i].name, (int)golden_data[i].last_update,
70                                 status, golden_data[i].expected);
71         }
73         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
74                 _Bool has;
76                 has = sdb_store_has_host(golden_hosts[i].name);
77                 fail_unless(has == golden_hosts[i].has,
78                                 "sdb_store_has_host(%s) = %d; expected: %d",
79                                 golden_hosts[i].name, has, golden_hosts[i].has);
80         }
81 }
82 END_TEST
84 START_TEST(test_store_get_host)
85 {
86         char *golden_hosts[] = { "a", "b", "c" };
87         char *unknown_hosts[] = { "x", "y", "z" };
88         size_t i;
90         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
91                 int status = sdb_store_host(golden_hosts[i], 1);
92                 fail_unless(status >= 0,
93                                 "sdb_store_host(%s) = %d; expected: >=0",
94                                 golden_hosts[i], status);
95         }
97         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
98                 sdb_store_base_t *sobj1, *sobj2;
99                 int ref_cnt;
101                 fail_unless(sdb_store_has_host(golden_hosts[i]),
102                                 "sdb_store_has_host(%s) = FALSE; expected: TRUE",
103                                 golden_hosts[i]);
105                 sobj1 = sdb_store_get_host(golden_hosts[i]);
106                 fail_unless(sobj1 != NULL,
107                                 "sdb_store_get_host(%s) = NULL; expected: <host>",
108                                 golden_hosts[i]);
109                 ref_cnt = SDB_OBJ(sobj1)->ref_cnt;
111                 fail_unless(ref_cnt > 1,
112                                 "sdb_store_get_host(%s) did not increment ref count: "
113                                 "got: %d; expected: >1", golden_hosts[i], ref_cnt);
115                 sobj2 = sdb_store_get_host(golden_hosts[i]);
116                 fail_unless(sobj2 != NULL,
117                                 "sdb_store_get_host(%s) = NULL; expected: <host>",
118                                 golden_hosts[i]);
120                 fail_unless(sobj1 == sobj2,
121                                 "sdb_store_get_host(%s) returned different objects "
122                                 "in successive calls", golden_hosts[i]);
123                 fail_unless(SDB_OBJ(sobj2)->ref_cnt == ref_cnt + 1,
124                                 "sdb_store_get_hosts(%s) did not increment ref count "
125                                 "(first call: %d; second call: %d)",
126                                 golden_hosts[i], ref_cnt, SDB_OBJ(sobj2)->ref_cnt);
128                 sdb_object_deref(SDB_OBJ(sobj1));
129                 sdb_object_deref(SDB_OBJ(sobj2));
130         }
131         for (i = 0; i < SDB_STATIC_ARRAY_LEN(unknown_hosts); ++i) {
132                 sdb_store_base_t *sobj;
134                 fail_unless(!sdb_store_has_host(unknown_hosts[i]),
135                                 "sdb_store_has_host(%s) = TRUE; expected: FALSE",
136                                 unknown_hosts[i]);
138                 sobj = sdb_store_get_host(unknown_hosts[i]);
139                 fail_unless(!sobj, "sdb_store_get_host(%s) = <host:%s>; expected: NULL",
140                                 unknown_hosts[i], sobj ? SDB_OBJ(sobj)->name : "NULL");
141         }
143 END_TEST
145 START_TEST(test_store_attr)
147         struct {
148                 const char *host;
149                 const char *key;
150                 char       *value;
151                 sdb_time_t  last_update;
152                 int         expected;
153         } golden_data[] = {
154                 { "k", "k", "v", 1, -1 },
155                 { "k", "k", "v", 1, -1 }, /* retry to ensure the host is not created */
156                 { "l", "k1", "v1", 1, 0 },
157                 { "l", "k1", "v2", 2, 0 },
158                 { "l", "k1", "v3", 1, 1 },
159                 { "l", "k2", "v1", 1, 0 },
160                 { "m", "k", "v1", 2, 0 },
161                 { "m", "k", "v2", 1, 1 },
162         };
164         size_t i;
166         sdb_store_host("l", 1);
167         sdb_store_host("m", 1);
168         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
169                 sdb_data_t datum;
170                 int status;
172                 /* XXX: test other types as well */
173                 datum.type = SDB_TYPE_STRING;
174                 datum.data.string = golden_data[i].value;
176                 status = sdb_store_attribute(golden_data[i].host,
177                                 golden_data[i].key, &datum,
178                                 golden_data[i].last_update);
179                 fail_unless(status == golden_data[i].expected,
180                                 "sdb_store_attribute(%s, %s, %s, %d) = %d; expected: %d",
181                                 golden_data[i].host, golden_data[i].key, golden_data[i].value,
182                                 golden_data[i].last_update, status, golden_data[i].expected);
183         }
185 END_TEST
187 START_TEST(test_store_service)
189         struct {
190                 const char *host;
191                 const char *svc;
192                 sdb_time_t  last_update;
193                 int         expected;
194         } golden_data[] = {
195                 { "k", "s", 1, -1 },
196                 { "k", "s", 1, -1 }, /* retry to ensure the host is not created */
197                 { "l", "s1", 1, 0 },
198                 { "l", "s1", 2, 0 },
199                 { "l", "s1", 1, 1 },
200                 { "l", "s2", 1, 0 },
201                 { "m", "s", 2, 0 },
202                 { "m", "s", 1, 1 },
203         };
205         size_t i;
207         sdb_store_host("m", 1);
208         sdb_store_host("l", 1);
209         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
210                 int status;
212                 status = sdb_store_service(golden_data[i].host,
213                                 golden_data[i].svc, golden_data[i].last_update);
214                 fail_unless(status == golden_data[i].expected,
215                                 "sdb_store_attribute(%s, %s, %d) = %d; expected: %d",
216                                 golden_data[i].host, golden_data[i].svc,
217                                 golden_data[i].last_update, status, golden_data[i].expected);
218         }
220 END_TEST
222 static void
223 verify_json_output(sdb_strbuf_t *buf, const char *expected, int flags)
225         int pos;
226         size_t len1, len2;
227         size_t i;
229         len1 = strlen(sdb_strbuf_string(buf));
230         len2 = strlen(expected);
232         pos = -1;
233         if (len1 != len2)
234                 pos = (int)(len1 <= len2 ? len1 : len2);
236         for (i = 0; i < (len1 <= len2 ? len1 : len2); ++i) {
237                 if (sdb_strbuf_string(buf)[i] != expected[i]) {
238                         pos = (int)i;
239                         break;
240                 }
241         }
243         fail_unless(pos == -1,
244                         "sdb_store_tojson(%x) returned unexpected result\n"
245                         "         got: %s\n              %*s\n    expected: %s",
246                         flags, sdb_strbuf_string(buf), pos + 1, "^", expected);
247 } /* verify_json_output */
249 START_TEST(test_store_tojson)
251         sdb_strbuf_t *buf;
252         sdb_data_t datum;
253         size_t i;
255         struct {
256                 int flags;
257                 const char *expected;
258         } golden_data[] = {
259                 { 0, "{\"hosts\":["
260                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
261                                         "\"attributes\": ["
262                                                 "{\"name\": \"k1\", \"value\": \"v1\", \"last_update\": \"1970-01-01 00:00:00 +0000\"},"
263                                                 "{\"name\": \"k2\", \"value\": \"v2\", \"last_update\": \"1970-01-01 00:00:00 +0000\"},"
264                                                 "{\"name\": \"k3\", \"value\": \"v3\", \"last_update\": \"1970-01-01 00:00:00 +0000\"}"
265                                         "], "
266                                         "\"services\": []},"
267                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
268                                         "\"attributes\": [], "
269                                         "\"services\": ["
270                                                 "{\"name\": \"s1\", \"last_update\": \"1970-01-01 00:00:00 +0000\"},"
271                                                 "{\"name\": \"s2\", \"last_update\": \"1970-01-01 00:00:00 +0000\"}"
272                                         "]}"
273                         "]}" },
274                 { SDB_SKIP_SERVICES,
275                         "{\"hosts\":["
276                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
277                                         "\"attributes\": ["
278                                                 "{\"name\": \"k1\", \"value\": \"v1\", \"last_update\": \"1970-01-01 00:00:00 +0000\"},"
279                                                 "{\"name\": \"k2\", \"value\": \"v2\", \"last_update\": \"1970-01-01 00:00:00 +0000\"},"
280                                                 "{\"name\": \"k3\", \"value\": \"v3\", \"last_update\": \"1970-01-01 00:00:00 +0000\"}"
281                                         "]},"
282                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
283                                         "\"attributes\": []}"
284                         "]}" },
285                 { SDB_SKIP_ATTRIBUTES,
286                         "{\"hosts\":["
287                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
288                                         "\"services\": []},"
289                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
290                                         "\"services\": ["
291                                                 "{\"name\": \"s1\", \"last_update\": \"1970-01-01 00:00:00 +0000\"},"
292                                                 "{\"name\": \"s2\", \"last_update\": \"1970-01-01 00:00:00 +0000\"}"
293                                         "]}"
294                         "]}" },
295                 { SDB_SKIP_SERVICES | SDB_SKIP_ATTRIBUTES,
296                         "{\"hosts\":["
297                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\"},"
298                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\"}"
299                         "]}" },
300         };
302         sdb_store_host("h1", 1);
303         sdb_store_host("h2", 1);
305         datum.type = SDB_TYPE_STRING;
306         datum.data.string = "v1";
307         sdb_store_attribute("h1", "k1", &datum, 1);
308         datum.data.string = "v2";
309         sdb_store_attribute("h1", "k2", &datum, 1);
310         datum.data.string = "v3";
311         sdb_store_attribute("h1", "k3", &datum, 1);
313         sdb_store_service("h2", "s1", 1);
314         sdb_store_service("h2", "s2", 1);
316         buf = sdb_strbuf_create(0);
318         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
319                 int status;
321                 sdb_strbuf_clear(buf);
323                 status = sdb_store_tojson(buf, golden_data[i].flags);
324                 fail_unless(status == 0,
325                                 "sdb_store_tojson(%x) = %d; expected: 0",
326                                 golden_data[i].flags, status);
328                 verify_json_output(buf, golden_data[i].expected, golden_data[i].flags);
329         }
330         sdb_strbuf_destroy(buf);
332 END_TEST
334 Suite *
335 core_store_suite(void)
337         Suite *s = suite_create("core::store");
338         TCase *tc;
340         tc = tcase_create("core");
341         /* test this first to ensure the store is empty
342          * even when using CK_NOFORK */
343         tcase_add_test(tc, test_store_tojson);
344         tcase_add_test(tc, test_store_host);
345         tcase_add_test(tc, test_store_get_host);
346         tcase_add_test(tc, test_store_attr);
347         tcase_add_test(tc, test_store_service);
348         suite_add_tcase(s, tc);
350         return s;
351 } /* core_store_suite */
353 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */