Code

Drop sdb_store_get_host() from tests.
[sysdb.git] / t / unit / core / store_test.c
1 /*
2  * SysDB - t/unit/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 #if HAVE_CONFIG_H
29 #       include "config.h"
30 #endif
32 #include "core/plugin.h"
33 #include "core/store.h"
34 #include "core/store-private.h"
35 #include "testutils.h"
37 #include <check.h>
38 #include <string.h>
39 #include <strings.h>
41 static void
42 init(void)
43 {
44         sdb_store_init();
45 }
47 static void
48 populate(void)
49 {
50         sdb_data_t datum;
52         sdb_plugin_store_host("h1", 1);
53         sdb_plugin_store_host("h2", 3);
55         datum.type = SDB_TYPE_STRING;
56         datum.data.string = "v1";
57         sdb_plugin_store_attribute("h1", "k1", &datum, 1);
58         datum.data.string = "v2";
59         sdb_plugin_store_attribute("h1", "k2", &datum, 2);
60         datum.data.string = "v3";
61         sdb_plugin_store_attribute("h1", "k3", &datum, 2);
63         /* make sure that older updates don't overwrite existing values */
64         datum.data.string = "fail";
65         sdb_plugin_store_attribute("h1", "k2", &datum, 1);
66         sdb_plugin_store_attribute("h1", "k3", &datum, 2);
68         sdb_plugin_store_metric("h1", "m1", /* store */ NULL, 2);
69         sdb_plugin_store_metric("h1", "m2", /* store */ NULL, 1);
70         sdb_plugin_store_metric("h2", "m1", /* store */ NULL, 1);
72         sdb_plugin_store_service("h2", "s1", 1);
73         sdb_plugin_store_service("h2", "s2", 2);
75         datum.type = SDB_TYPE_INTEGER;
76         datum.data.integer = 42;
77         sdb_plugin_store_metric_attribute("h1", "m1", "k3", &datum, 2);
79         datum.data.integer = 123;
80         sdb_plugin_store_service_attribute("h2", "s2", "k1", &datum, 2);
81         datum.data.integer = 4711;
82         sdb_plugin_store_service_attribute("h2", "s2", "k2", &datum, 1);
84         /* don't overwrite k1 */
85         datum.data.integer = 666;
86         sdb_plugin_store_service_attribute("h2", "s2", "k1", &datum, 2);
87 } /* populate */
89 START_TEST(test_store_host)
90 {
91         struct {
92                 const char *name;
93                 sdb_time_t  last_update;
94                 int         expected;
95         } golden_data[] = {
96                 { "a", 1, 0 },
97                 { "a", 2, 0 },
98                 { "a", 1, 1 },
99                 { "b", 1, 0 },
100                 { "b", 1, 1 },
101                 { "A", 1, 1 }, /* case-insensitive */
102                 { "A", 3, 0 },
103         };
105         struct {
106                 const char *name;
107                 bool        have;
108         } golden_hosts[] = {
109                 { "a", 1 == 1 },
110                 { "b", 1 == 1 },
111                 { "c", 0 == 1 },
112                 { "A", 1 == 1 },
113         };
115         size_t i;
117         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
118                 int status;
120                 status = sdb_plugin_store_host(golden_data[i].name,
121                                 golden_data[i].last_update);
122                 fail_unless(status == golden_data[i].expected,
123                                 "sdb_plugin_store_host(%s, %d) = %d; expected: %d",
124                                 golden_data[i].name, (int)golden_data[i].last_update,
125                                 status, golden_data[i].expected);
126         }
128         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
129                 sdb_store_obj_t *have;
131                 have = sdb_store_get_host(golden_hosts[i].name);
132                 fail_unless((have != NULL) == golden_hosts[i].have,
133                                 "sdb_store_get_host(%s) = %p; expected: %s",
134                                 golden_hosts[i].name, have,
135                                 golden_hosts[i].have ? "<host>" : "NULL");
136                 sdb_object_deref(SDB_OBJ(have));
137         }
139 END_TEST
141 START_TEST(test_store_get_host)
143         char *golden_hosts[] = { "a", "b", "c" };
144         char *unknown_hosts[] = { "x", "y", "z" };
145         size_t i;
147         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
148                 int status = sdb_plugin_store_host(golden_hosts[i], 1);
149                 fail_unless(status >= 0,
150                                 "sdb_plugin_store_host(%s) = %d; expected: >=0",
151                                 golden_hosts[i], status);
152         }
154         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
155                 sdb_store_obj_t *sobj1, *sobj2;
156                 int ref_cnt;
158                 sobj1 = sdb_store_get_host(golden_hosts[i]);
159                 fail_unless(sobj1 != NULL,
160                                 "sdb_store_get_host(%s) = NULL; expected: <host>",
161                                 golden_hosts[i]);
162                 ref_cnt = SDB_OBJ(sobj1)->ref_cnt;
164                 fail_unless(ref_cnt > 1,
165                                 "sdb_store_get_host(%s) did not increment ref count: "
166                                 "got: %d; expected: >1", golden_hosts[i], ref_cnt);
168                 sobj2 = sdb_store_get_host(golden_hosts[i]);
169                 fail_unless(sobj2 != NULL,
170                                 "sdb_store_get_host(%s) = NULL; expected: <host>",
171                                 golden_hosts[i]);
173                 fail_unless(sobj1 == sobj2,
174                                 "sdb_store_get_host(%s) returned different objects "
175                                 "in successive calls", golden_hosts[i]);
176                 fail_unless(SDB_OBJ(sobj2)->ref_cnt == ref_cnt + 1,
177                                 "sdb_store_get_hosts(%s) did not increment ref count "
178                                 "(first call: %d; second call: %d)",
179                                 golden_hosts[i], ref_cnt, SDB_OBJ(sobj2)->ref_cnt);
181                 sdb_object_deref(SDB_OBJ(sobj1));
182                 sdb_object_deref(SDB_OBJ(sobj2));
183         }
184         for (i = 0; i < SDB_STATIC_ARRAY_LEN(unknown_hosts); ++i) {
185                 sdb_store_obj_t *sobj;
187                 sobj = sdb_store_get_host(unknown_hosts[i]);
188                 fail_unless(!sobj, "sdb_store_get_host(%s) = <host:%s>; expected: NULL",
189                                 unknown_hosts[i], sobj ? SDB_OBJ(sobj)->name : "NULL");
190         }
192 END_TEST
194 START_TEST(test_store_attr)
196         struct {
197                 const char *host;
198                 const char *key;
199                 char       *value;
200                 sdb_time_t  last_update;
201                 int         expected;
202         } golden_data[] = {
203                 { "k", "k",  "v",  1, -1 },
204                 { "k", "k",  "v",  1, -1 }, /* retry to ensure the host is not created */
205                 { "l", "k1", "v1", 1,  0 },
206                 { "l", "k1", "v2", 2,  0 },
207                 { "l", "k1", "v3", 2,  1 },
208                 { "l", "k2", "v1", 1,  0 },
209                 { "m", "k",  "v1", 1,  0 },
210                 { "m", "k",  "v2", 1,  1 },
211         };
213         size_t i;
215         sdb_plugin_store_host("l", 1);
216         sdb_plugin_store_host("m", 1);
217         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
218                 sdb_data_t datum;
219                 int status;
221                 /* XXX: test other types as well */
222                 datum.type = SDB_TYPE_STRING;
223                 datum.data.string = golden_data[i].value;
225                 status = sdb_plugin_store_attribute(golden_data[i].host,
226                                 golden_data[i].key, &datum,
227                                 golden_data[i].last_update);
228                 fail_unless(status == golden_data[i].expected,
229                                 "sdb_plugin_store_attribute(%s, %s, %s, %d) = %d; expected: %d",
230                                 golden_data[i].host, golden_data[i].key, golden_data[i].value,
231                                 golden_data[i].last_update, status, golden_data[i].expected);
232         }
234 END_TEST
236 START_TEST(test_store_metric)
238         sdb_metric_store_t store1 = { "dummy-type1", "dummy-id1" };
239         sdb_metric_store_t store2 = { "dummy-type2", "dummy-id2" };
241         struct {
242                 const char *host;
243                 const char *metric;
244                 sdb_metric_store_t *store;
245                 sdb_time_t  last_update;
246                 int         expected;
247         } golden_data[] = {
248                 { "k", "m",  NULL,    1, -1 },
249                 { "k", "m",  NULL,    1, -1 }, /* retry to ensure the host is not created */
250                 { "k", "m",  &store1, 1, -1 },
251                 { "l", "m1", NULL,    1,  0 },
252                 { "l", "m1", &store1, 2,  0 },
253                 { "l", "m1", &store1, 3,  0 },
254                 { "l", "m1", NULL,    3,  1 },
255                 { "l", "m2", &store1, 1,  0 },
256                 { "l", "m2", &store2, 2,  0 },
257                 { "l", "m2", NULL,    3,  0 },
258                 { "m", "m",  &store1, 1,  0 },
259                 { "m", "m",  NULL,    2,  0 },
260                 { "m", "m",  NULL,    2,  1 },
261                 { "m", "m",  &store1, 3,  0 },
262                 { "m", "m",  &store2, 4,  0 },
263                 { "m", "m",  NULL,    5,  0 },
264         };
266         size_t i;
268         sdb_plugin_store_host("m", 1);
269         sdb_plugin_store_host("l", 1);
270         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
271                 int status;
273                 status = sdb_plugin_store_metric(golden_data[i].host,
274                                 golden_data[i].metric, golden_data[i].store,
275                                 golden_data[i].last_update);
276                 fail_unless(status == golden_data[i].expected,
277                                 "sdb_plugin_store_metric(%s, %s, %p, %d) = %d; expected: %d",
278                                 golden_data[i].host, golden_data[i].metric,
279                                 golden_data[i].store, golden_data[i].last_update,
280                                 status, golden_data[i].expected);
281         }
283 END_TEST
285 START_TEST(test_store_metric_attr)
287         struct {
288                 const char *host;
289                 const char *metric;
290                 const char *attr;
291                 const sdb_data_t value;
292                 sdb_time_t  last_update;
293                 int expected;
294         } golden_data[] = {
295                 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
296                 /* retry, it should still fail */
297                 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
298                 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
299                 /* retry, it should still fail */
300                 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
301                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
302                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
303                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2,  0 },
304                 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
305                 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
306                 { "l", "m2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
307                 { "m", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
308         };
310         size_t i;
312         sdb_plugin_store_host("m", 1);
313         sdb_plugin_store_host("l", 1);
314         sdb_plugin_store_metric("m", "m1", NULL, 1);
315         sdb_plugin_store_metric("l", "m1", NULL, 1);
316         sdb_plugin_store_metric("l", "m2", NULL, 1);
318         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
319                 int status;
321                 status = sdb_plugin_store_metric_attribute(golden_data[i].host,
322                                 golden_data[i].metric, golden_data[i].attr,
323                                 &golden_data[i].value, golden_data[i].last_update);
324                 fail_unless(status == golden_data[i].expected,
325                                 "sdb_plugin_store_metric_attribute(%s, %s, %s, %d, %d) = %d; "
326                                 "expected: %d", golden_data[i].host, golden_data[i].metric,
327                                 golden_data[i].attr, golden_data[i].value.data.integer,
328                                 golden_data[i].last_update, status, golden_data[i].expected);
329         }
331 END_TEST
333 START_TEST(test_store_service)
335         struct {
336                 const char *host;
337                 const char *svc;
338                 sdb_time_t  last_update;
339                 int         expected;
340         } golden_data[] = {
341                 { "k", "s",  1, -1 },
342                 { "k", "s",  1, -1 }, /* retry to ensure the host is not created */
343                 { "l", "s1", 1,  0 },
344                 { "l", "s1", 2,  0 },
345                 { "l", "s1", 2,  1 },
346                 { "l", "s2", 1,  0 },
347                 { "m", "s",  1,  0 },
348                 { "m", "s",  1,  1 },
349         };
351         size_t i;
353         sdb_plugin_store_host("m", 1);
354         sdb_plugin_store_host("l", 1);
355         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
356                 int status;
358                 status = sdb_plugin_store_service(golden_data[i].host,
359                                 golden_data[i].svc, golden_data[i].last_update);
360                 fail_unless(status == golden_data[i].expected,
361                                 "sdb_plugin_store_service(%s, %s, %d) = %d; expected: %d",
362                                 golden_data[i].host, golden_data[i].svc,
363                                 golden_data[i].last_update, status, golden_data[i].expected);
364         }
366 END_TEST
368 START_TEST(test_store_service_attr)
370         struct {
371                 const char *host;
372                 const char *svc;
373                 const char *attr;
374                 const sdb_data_t value;
375                 sdb_time_t  last_update;
376                 int expected;
377         } golden_data[] = {
378                 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
379                 /* retry, it should still fail */
380                 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
381                 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
382                 /* retry, it should still fail */
383                 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
384                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
385                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
386                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2,  0 },
387                 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
388                 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
389                 { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
390                 { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
391         };
393         size_t i;
395         sdb_plugin_store_host("m", 1);
396         sdb_plugin_store_host("l", 1);
397         sdb_plugin_store_service("m", "s1", 1);
398         sdb_plugin_store_service("l", "s1", 1);
399         sdb_plugin_store_service("l", "s2", 1);
401         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
402                 int status;
404                 status = sdb_plugin_store_service_attribute(golden_data[i].host,
405                                 golden_data[i].svc, golden_data[i].attr,
406                                 &golden_data[i].value, golden_data[i].last_update);
407                 fail_unless(status == golden_data[i].expected,
408                                 "sdb_plugin_store_service_attribute(%s, %s, %s, %d, %d) = %d; "
409                                 "expected: %d", golden_data[i].host, golden_data[i].svc,
410                                 golden_data[i].attr, golden_data[i].value.data.integer,
411                                 golden_data[i].last_update, status, golden_data[i].expected);
412         }
414 END_TEST
416 static struct {
417         const char *hostname;
418         const char *attr; /* optional */
419         int field;
420         int expected;
421         sdb_data_t value;
422 } get_field_data[] = {
423         { NULL,   NULL, 0, -1, { SDB_TYPE_NULL, { 0 } } },
424         { NULL,   NULL,   SDB_FIELD_LAST_UPDATE, -1, { SDB_TYPE_NULL, { 0 } } },
425         { NULL,   NULL,   SDB_FIELD_INTERVAL,    -1, { SDB_TYPE_NULL, { 0 } } },
426         { NULL,   NULL,   SDB_FIELD_AGE,         -1, { SDB_TYPE_NULL, { 0 } } },
427         { NULL,   NULL,   SDB_FIELD_NAME,        -1, { SDB_TYPE_NULL, { 0 } } },
428         { NULL,   NULL,   SDB_FIELD_BACKEND,     -1, { SDB_TYPE_NULL, { 0 } } },
429         { NULL,   NULL,   SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
430         { "host", NULL,   SDB_FIELD_LAST_UPDATE,  0, { SDB_TYPE_DATETIME, { .datetime = 20 } } },
431         { "host", NULL,   SDB_FIELD_INTERVAL,     0, { SDB_TYPE_DATETIME, { .datetime = 10 } } },
432         /* the test will handle AGE specially */
433         { "host", NULL,   SDB_FIELD_AGE,          0, { SDB_TYPE_NULL, { 0 } } },
434         { "host", NULL,   SDB_FIELD_NAME,         0, { SDB_TYPE_STRING, { .string = "host" } } },
435         { "host", NULL,   SDB_FIELD_BACKEND,      0, { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } } },
436         { "host", NULL,   SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
437         { "host", "attr", SDB_FIELD_LAST_UPDATE,  0, { SDB_TYPE_DATETIME, { .datetime = 20 } } },
438         { "host", "attr", SDB_FIELD_INTERVAL,     0, { SDB_TYPE_DATETIME, { .datetime = 10 } } },
439         /* the test will handle AGE specially */
440         { "host", "attr", SDB_FIELD_AGE,          0, { SDB_TYPE_NULL, { 0 } } },
441         { "host", "attr", SDB_FIELD_NAME,         0, { SDB_TYPE_STRING, { .string = "attr" } } },
442         { "host", "attr", SDB_FIELD_BACKEND,      0, { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } } },
443         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_INTEGER, { .integer = 1 } } },
444         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_DECIMAL, { .decimal = 2.0 } } },
445         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_STRING, { .string = "foo" } } },
446         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_DATETIME, { .datetime = 1234567890L } } },
447         { "host", "a",    SDB_FIELD_LAST_UPDATE, -1, { SDB_TYPE_NULL, { 0 } } },
448         { "host", "a",    SDB_FIELD_INTERVAL,    -1, { SDB_TYPE_NULL, { 0 } } },
449         { "host", "a",    SDB_FIELD_AGE,         -1, { SDB_TYPE_NULL, { 0 } } },
450         { "host", "a",    SDB_FIELD_NAME,        -1, { SDB_TYPE_NULL, { 0 } } },
451         { "host", "a",    SDB_FIELD_BACKEND,     -1, { SDB_TYPE_NULL, { 0 } } },
452         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
453         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
454         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
455         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
456 };
458 /* returns a tuple <type> <name> */
459 #define OBJ_NAME(obj) \
460         (obj) ? SDB_STORE_TYPE_TO_NAME(obj->type) : "NULL", \
461         (obj) ? SDB_OBJ(obj)->name : ""
462 START_TEST(test_get_field)
464         sdb_store_obj_t *obj = NULL;
465         sdb_data_t value = SDB_DATA_INIT;
466         char value_str[128], expected_value_str[128];
467         sdb_time_t now = sdb_gettime();
468         int check;
470         sdb_plugin_store_host("host", 10);
471         sdb_plugin_store_host("host", 20);
472         sdb_plugin_store_attribute("host", "attr", &get_field_data[_i].value, 10);
473         sdb_plugin_store_attribute("host", "attr", &get_field_data[_i].value, 20);
475         if (get_field_data[_i].hostname) {
476                 obj = sdb_store_get_host(get_field_data[_i].hostname);
477                 ck_assert(obj != NULL);
479                 if (get_field_data[_i].attr) {
480                         sdb_store_obj_t *tmp = sdb_store_get_child(obj,
481                                         SDB_ATTRIBUTE, get_field_data[_i].attr);
482                         sdb_object_deref(SDB_OBJ(obj));
483                         obj = tmp;
484                 }
485         }
487         check = sdb_store_get_field(obj, get_field_data[_i].field, NULL);
488         fail_unless(check == get_field_data[_i].expected,
489                         "sdb_store_get_field(%s %s, %s, NULL) = %d; expected: %d",
490                         OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field),
491                         check, get_field_data[_i].expected);
492         check = sdb_store_get_field(obj, get_field_data[_i].field, &value);
493         fail_unless(check == get_field_data[_i].expected,
494                         "sdb_store_get_field(%s %s, %s, <value>) = %d; expected: %d",
495                         OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field),
496                         check, get_field_data[_i].expected);
498         if (get_field_data[_i].expected) {
499                 sdb_object_deref(SDB_OBJ(obj));
500                 return;
501         }
503         if (get_field_data[_i].field == SDB_FIELD_AGE) {
504                 get_field_data[_i].value.type = SDB_TYPE_DATETIME;
505                 get_field_data[_i].value.data.datetime = now;
506         }
508         sdb_data_format(&value, value_str, sizeof(value_str), 0);
509         sdb_data_format(&get_field_data[_i].value, expected_value_str,
510                         sizeof(expected_value_str), 0);
512         if (get_field_data[_i].field == SDB_FIELD_AGE) {
513                 fail_unless((value.type == SDB_TYPE_DATETIME)
514                                 && (value.data.datetime >= now),
515                                 "sdb_store_get_field(%s %s, %s, <value>) "
516                                 "returned value %s; expected >=%s", OBJ_NAME(obj),
517                                 SDB_FIELD_TO_NAME(get_field_data[_i].field),
518                                 value_str, expected_value_str);
519         }
520         else {
521                 fail_unless(! sdb_data_cmp(&value, &get_field_data[_i].value),
522                                 "sdb_store_get_field(%s %s, %s, <value>) "
523                                 "returned value %s; expected %s", OBJ_NAME(obj),
524                                 SDB_FIELD_TO_NAME(get_field_data[_i].field),
525                                 value_str, expected_value_str);
526         }
527         sdb_data_free_datum(&value);
528         sdb_object_deref(SDB_OBJ(obj));
530 END_TEST
531 #undef OBJ_NAME
533 START_TEST(test_get_child)
535         struct {
536                 const char *host;
537                 const char *name;
538                 int type;
539                 int expected;
540         } golden_data[] = {
541                 { "h1", NULL, SDB_HOST,       0 },
542                 { "h1", NULL, SDB_SERVICE,   -1 },
543                 { "h1", NULL, SDB_METRIC,    -1 },
544                 { "h1", NULL, SDB_ATTRIBUTE, -1 },
545                 { "h2", NULL, SDB_HOST,       0 },
546                 { "h2", NULL, SDB_SERVICE,   -1 },
547                 { "h2", NULL, SDB_METRIC,    -1 },
548                 { "h2", NULL, SDB_ATTRIBUTE, -1 },
549                 { "h3", NULL, SDB_HOST,      -1 },
550                 { "h1", "k1", SDB_ATTRIBUTE,  0 },
551                 { "h1", "x1", SDB_ATTRIBUTE, -1 },
552                 { "h2", "k1", SDB_ATTRIBUTE, -1 },
553                 { "h1", "k1", SDB_SERVICE,   -1 },
554                 { "h1", "k1", SDB_METRIC,    -1 },
555                 { "h1", "s1", SDB_SERVICE,   -1 },
556                 { "h2", "s1", SDB_SERVICE,    0 },
557                 { "h1", "m2", SDB_METRIC,     0 },
558                 { "h2", "m2", SDB_METRIC,    -1 },
559         };
561         size_t i;
563         populate();
565         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
566                 sdb_store_obj_t *obj;
567                 const char *expected_name = golden_data[i].host;
569                 obj = sdb_store_get_host(golden_data[i].host);
570                 if (golden_data[i].expected && (golden_data[i].type == SDB_HOST))
571                         fail_unless(obj == NULL,
572                                         "sdb_store_get_host(%s) = %p; expected: NULL",
573                                         golden_data[i].host, obj);
574                 else
575                         fail_unless(obj != NULL,
576                                         "sdb_store_get_host(%s) = NULL; expected: <host>",
577                                         golden_data[i].host);
579                 if (golden_data[i].type != SDB_HOST) {
580                         sdb_store_obj_t *tmp;
582                         expected_name = golden_data[i].name;
584                         tmp = sdb_store_get_child(obj,
585                                         golden_data[i].type, golden_data[i].name);
586                         if (golden_data[i].expected)
587                                 fail_unless(tmp == NULL,
588                                                 "sdb_store_get_child(<%s>, %s, %s) = %p; "
589                                                 "expected: NULL", golden_data[i].host,
590                                                 SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
591                                                 golden_data[i].name, tmp);
592                         else
593                                 fail_unless(tmp != NULL,
594                                                 "sdb_store_get_child(<%s>, %s, %s) = NULL; "
595                                                 "expected: <obj>", golden_data[i].host,
596                                                 SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
597                                                 golden_data[i].name);
599                         sdb_object_deref(SDB_OBJ(obj));
600                         obj = tmp;
601                 }
603                 if (golden_data[i].expected)
604                         continue;
606                 fail_unless(obj->type == golden_data[i].type,
607                                 "sdb_store_get_<%s>(%s, %s) returned object of type %d; "
608                                 "expected: %d", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
609                                 golden_data[i].host, golden_data[i].name, obj->type,
610                                 golden_data[i].type);
611                 fail_unless(! strcasecmp(SDB_OBJ(obj)->name, expected_name),
612                                 "sdb_store_get_<%s>(%s, %s) returned object named '%s'; "
613                                 "expected: '%s'", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
614                                 golden_data[i].host, golden_data[i].name, SDB_OBJ(obj)->name,
615                                 expected_name);
617                 sdb_object_deref(SDB_OBJ(obj));
618         }
620 END_TEST
622 START_TEST(test_interval)
624         sdb_store_obj_t *host;
626         /* 10 us interval */
627         sdb_plugin_store_host("host", 10);
628         sdb_plugin_store_host("host", 20);
629         sdb_plugin_store_host("host", 30);
630         sdb_plugin_store_host("host", 40);
632         host = sdb_store_get_host("host");
633         fail_unless(host != NULL,
634                         "INTERNAL ERROR: store doesn't have host after adding it");
636         fail_unless(host->interval == 10,
637                         "sdb_plugin_store_host() did not calculate interval correctly: "
638                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10);
640         /* multiple updates for the same timestamp don't modify the interval */
641         sdb_plugin_store_host("host", 40);
642         sdb_plugin_store_host("host", 40);
643         sdb_plugin_store_host("host", 40);
644         sdb_plugin_store_host("host", 40);
646         fail_unless(host->interval == 10,
647                         "sdb_plugin_store_host() changed interval when doing multiple updates "
648                         "using the same timestamp; got: %"PRIsdbTIME"; "
649                         "expected: %"PRIsdbTIME, host->interval, 10);
651         /* multiple updates using an timestamp don't modify the interval */
652         sdb_plugin_store_host("host", 20);
653         sdb_plugin_store_host("host", 20);
654         sdb_plugin_store_host("host", 20);
655         sdb_plugin_store_host("host", 20);
657         fail_unless(host->interval == 10,
658                         "sdb_plugin_store_host() changed interval when doing multiple updates "
659                         "using an old timestamp; got: %"PRIsdbTIME"; expected: %"PRIsdbTIME,
660                         host->interval, 10);
662         /* new interval: 20 us */
663         sdb_plugin_store_host("host", 60);
664         fail_unless(host->interval == 11,
665                         "sdb_plugin_store_host() did not calculate interval correctly: "
666                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
668         /* new interval: 40 us */
669         sdb_plugin_store_host("host", 100);
670         fail_unless(host->interval == 13,
671                         "sdb_plugin_store_host() did not calculate interval correctly: "
672                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
674         sdb_object_deref(SDB_OBJ(host));
676 END_TEST
678 static int
679 scan_count(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data)
681         intptr_t *i = user_data;
683         if (! sdb_store_matcher_matches(filter, obj, NULL))
684                 return 0;
686         fail_unless(obj != NULL,
687                         "sdb_store_scan callback received NULL obj; expected: "
688                         "<store base obj>");
689         fail_unless(i != NULL,
690                         "sdb_store_scan callback received NULL user_data; "
691                         "expected: <pointer to data>");
693         ++(*i);
694         return 0;
695 } /* scan_count */
697 static int
698 scan_error(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data)
700         intptr_t *i = user_data;
702         if (! sdb_store_matcher_matches(filter, obj, NULL))
703                 return 0;
705         fail_unless(obj != NULL,
706                         "sdb_store_scan callback received NULL obj; expected: "
707                         "<store base obj>");
708         fail_unless(i != NULL,
709                         "sdb_store_scan callback received NULL user_data; "
710                         "expected: <pointer to data>");
712         ++(*i);
713         return -1;
714 } /* scan_error */
716 START_TEST(test_scan)
718         intptr_t i = 0;
719         int check;
721         /* empty store */
722         check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL,
723                         scan_count, &i);
724         fail_unless(check == 0,
725                         "sdb_store_scan(HOST), empty store = %d; expected: 0", check);
726         fail_unless(i == 0,
727                         "sdb_store_scan(HOST) called callback %d times; "
728                         "expected: 0", (int)i);
730         populate();
732         check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL,
733                         scan_count, &i);
734         fail_unless(check == 0,
735                         "sdb_store_scan(HOST) = %d; expected: 0", check);
736         fail_unless(i == 2,
737                         "sdb_store_scan(HOST) called callback %d times; "
738                         "expected: 1", (int)i);
740         i = 0;
741         check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL,
742                         scan_error, &i);
743         fail_unless(check == -1,
744                         "sdb_store_scan(HOST), error callback = %d; expected: -1", check);
745         fail_unless(i == 1,
746                         "sdb_store_scan(HOST) called callback %d times "
747                         "(callback returned error); expected: 1", (int)i);
749         i = 0;
750         check = sdb_store_scan(SDB_SERVICE, /* m, filter = */ NULL, NULL,
751                         scan_count, &i);
752         fail_unless(check == 0,
753                         "sdb_store_scan(SERVICE) = %d; expected: 0", check);
754         fail_unless(i == 2,
755                         "sdb_store_scan(SERVICE) called callback %d times; "
756                         "expected: 2", (int)i);
758         i = 0;
759         check = sdb_store_scan(SDB_METRIC, /* m, filter = */ NULL, NULL,
760                         scan_count, &i);
761         fail_unless(check == 0,
762                         "sdb_store_scan(METRIC) = %d; expected: 0", check);
763         fail_unless(i == 3,
764                         "sdb_store_scan(METRIC) called callback %d times; "
765                         "expected: 3", (int)i);
767 END_TEST
769 TEST_MAIN("core::store")
771         TCase *tc = tcase_create("core");
772         tcase_add_test(tc, test_store_host);
773         tcase_add_test(tc, test_store_get_host);
774         tcase_add_test(tc, test_store_attr);
775         tcase_add_test(tc, test_store_metric);
776         tcase_add_test(tc, test_store_metric_attr);
777         tcase_add_test(tc, test_store_service);
778         tcase_add_test(tc, test_store_service_attr);
779         TC_ADD_LOOP_TEST(tc, get_field);
780         tcase_add_test(tc, test_get_child);
781         tcase_add_test(tc, test_interval);
782         tcase_add_test(tc, test_scan);
783         tcase_add_unchecked_fixture(tc, init, sdb_store_clear);
784         ADD_TCASE(tc);
786 TEST_MAIN_END
788 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */