Code

96ac0c1d67356eabbb59d885a75d2be6f1b48398
[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/memstore-private.h"
35 #include "testutils.h"
37 #include <check.h>
38 #include <string.h>
39 #include <strings.h>
41 static sdb_memstore_t *store;
43 static void
44 init(void)
45 {
46         store = sdb_memstore_create();
47         ck_assert(store != NULL);
48 }
50 static void
51 populate(void)
52 {
53         sdb_data_t datum;
55         sdb_memstore_host(store, "h1", 1, 0);
56         sdb_memstore_host(store, "h2", 3, 0);
58         datum.type = SDB_TYPE_STRING;
59         datum.data.string = "v1";
60         sdb_memstore_attribute(store, "h1", "k1", &datum, 1, 0);
61         datum.data.string = "v2";
62         sdb_memstore_attribute(store, "h1", "k2", &datum, 2, 0);
63         datum.data.string = "v3";
64         sdb_memstore_attribute(store, "h1", "k3", &datum, 2, 0);
66         /* make sure that older updates don't overwrite existing values */
67         datum.data.string = "fail";
68         sdb_memstore_attribute(store, "h1", "k2", &datum, 1, 0);
69         sdb_memstore_attribute(store, "h1", "k3", &datum, 2, 0);
71         sdb_memstore_metric(store, "h1", "m1", /* store */ NULL, 2, 0);
72         sdb_memstore_metric(store, "h1", "m2", /* store */ NULL, 1, 0);
73         sdb_memstore_metric(store, "h2", "m1", /* store */ NULL, 1, 0);
75         sdb_memstore_service(store, "h2", "s1", 1, 0);
76         sdb_memstore_service(store, "h2", "s2", 2, 0);
78         datum.type = SDB_TYPE_INTEGER;
79         datum.data.integer = 42;
80         sdb_memstore_metric_attr(store, "h1", "m1", "k3", &datum, 2, 0);
82         datum.data.integer = 123;
83         sdb_memstore_service_attr(store, "h2", "s2", "k1", &datum, 2, 0);
84         datum.data.integer = 4711;
85         sdb_memstore_service_attr(store, "h2", "s2", "k2", &datum, 1, 0);
87         /* don't overwrite k1 */
88         datum.data.integer = 666;
89         sdb_memstore_service_attr(store, "h2", "s2", "k1", &datum, 2, 0);
90 } /* populate */
92 static void
93 turndown(void)
94 {
95         sdb_object_deref(SDB_OBJ(store));
96         store = NULL;
97 } /* turndown */
99 START_TEST(test_store_host)
101         struct {
102                 const char *name;
103                 sdb_time_t  last_update;
104                 int         expected;
105         } golden_data[] = {
106                 { "a", 1, 0 },
107                 { "a", 2, 0 },
108                 { "b", 1, 0 },
109         };
111         struct {
112                 const char *name;
113                 bool        have;
114         } golden_hosts[] = {
115                 { "a", 1 },
116                 { "b", 1 },
117                 { "c", 0 },
118                 { "A", 1 },
119         };
121         size_t i;
123         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
124                 int status;
126                 status = sdb_memstore_host(store, golden_data[i].name,
127                                 golden_data[i].last_update, 0);
128                 fail_unless(status == golden_data[i].expected,
129                                 "sdb_memstore_host(%s, %d, 0) = %d; expected: %d",
130                                 golden_data[i].name, (int)golden_data[i].last_update,
131                                 status, golden_data[i].expected);
132         }
134         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
135                 sdb_memstore_obj_t *have;
137                 have = sdb_memstore_get_host(store, golden_hosts[i].name);
138                 fail_unless((have != NULL) == golden_hosts[i].have,
139                                 "sdb_memstore_get_host(%s) = %p; expected: %s",
140                                 golden_hosts[i].name, have,
141                                 golden_hosts[i].have ? "<host>" : "NULL");
142                 sdb_object_deref(SDB_OBJ(have));
143         }
145 END_TEST
147 START_TEST(test_store_get_host)
149         char *golden_hosts[] = { "a", "b", "c" };
150         char *unknown_hosts[] = { "x", "y", "z" };
151         size_t i;
153         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
154                 int status = sdb_memstore_host(store, golden_hosts[i], 1, 0);
155                 fail_unless(status >= 0,
156                                 "sdb_memstore_host(%s) = %d; expected: >=0",
157                                 golden_hosts[i], status);
158         }
160         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
161                 sdb_memstore_obj_t *sobj1, *sobj2;
162                 int ref_cnt;
164                 sobj1 = sdb_memstore_get_host(store, golden_hosts[i]);
165                 fail_unless(sobj1 != NULL,
166                                 "sdb_memstore_get_host(%s) = NULL; expected: <host>",
167                                 golden_hosts[i]);
168                 ref_cnt = SDB_OBJ(sobj1)->ref_cnt;
170                 fail_unless(ref_cnt > 1,
171                                 "sdb_memstore_get_host(%s) did not increment ref count: "
172                                 "got: %d; expected: >1", golden_hosts[i], ref_cnt);
174                 sobj2 = sdb_memstore_get_host(store, golden_hosts[i]);
175                 fail_unless(sobj2 != NULL,
176                                 "sdb_memstore_get_host(%s) = NULL; expected: <host>",
177                                 golden_hosts[i]);
179                 fail_unless(sobj1 == sobj2,
180                                 "sdb_memstore_get_host(%s) returned different objects "
181                                 "in successive calls", golden_hosts[i]);
182                 fail_unless(SDB_OBJ(sobj2)->ref_cnt == ref_cnt + 1,
183                                 "sdb_memstore_get_hosts(%s) did not increment ref count "
184                                 "(first call: %d; second call: %d)",
185                                 golden_hosts[i], ref_cnt, SDB_OBJ(sobj2)->ref_cnt);
187                 sdb_object_deref(SDB_OBJ(sobj1));
188                 sdb_object_deref(SDB_OBJ(sobj2));
189         }
190         for (i = 0; i < SDB_STATIC_ARRAY_LEN(unknown_hosts); ++i) {
191                 sdb_memstore_obj_t *sobj;
193                 sobj = sdb_memstore_get_host(store, unknown_hosts[i]);
194                 fail_unless(!sobj, "sdb_memstore_get_host(%s) = <host:%s>; expected: NULL",
195                                 unknown_hosts[i], sobj ? SDB_OBJ(sobj)->name : "NULL");
196         }
198 END_TEST
200 START_TEST(test_store_attr)
202         struct {
203                 const char *host;
204                 const char *key;
205                 char       *value;
206                 sdb_time_t  last_update;
207                 int         expected;
208         } golden_data[] = {
209                 { "k", "k",  "v",  1, -1 },
210                 { "k", "k",  "v",  1, -1 }, /* retry to ensure the host is not created */
211                 { "l", "k1", "v1", 1,  0 },
212                 { "l", "k1", "v2", 2,  0 },
213                 { "l", "k2", "v1", 1,  0 },
214                 { "m", "k",  "v1", 1,  0 },
215         };
217         size_t i;
219         sdb_memstore_host(store, "l", 1, 0);
220         sdb_memstore_host(store, "m", 1, 0);
221         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
222                 sdb_data_t datum;
223                 int status;
225                 /* XXX: test other types as well */
226                 datum.type = SDB_TYPE_STRING;
227                 datum.data.string = golden_data[i].value;
229                 status = sdb_memstore_attribute(store, golden_data[i].host,
230                                 golden_data[i].key, &datum,
231                                 golden_data[i].last_update, 0);
232                 fail_unless(status == golden_data[i].expected,
233                                 "sdb_memstore_attribute(%s, %s, %s, %d) = %d; expected: %d",
234                                 golden_data[i].host, golden_data[i].key, golden_data[i].value,
235                                 golden_data[i].last_update, status, golden_data[i].expected, 0);
236         }
238 END_TEST
240 START_TEST(test_store_metric)
242         sdb_metric_store_t store1 = { "dummy-type1", "dummy-id1", 0 };
243         sdb_metric_store_t store2 = { "dummy-type2", "dummy-id2", 0 };
245         struct {
246                 const char *host;
247                 const char *metric;
248                 sdb_metric_store_t *store;
249                 sdb_time_t  last_update;
250                 int         expected;
251         } golden_data[] = {
252                 { "k", "m",  NULL,    1, -1 },
253                 { "k", "m",  NULL,    1, -1 }, /* retry to ensure the host is not created */
254                 { "k", "m",  &store1, 1, -1 },
255                 { "l", "m1", NULL,    1,  0 },
256                 { "l", "m1", &store1, 2,  0 },
257                 { "l", "m1", &store1, 3,  0 },
258                 { "l", "m2", &store1, 1,  0 },
259                 { "l", "m2", &store2, 2,  0 },
260                 { "l", "m2", NULL,    3,  0 },
261                 { "m", "m",  &store1, 1,  0 },
262                 { "m", "m",  NULL,    2,  0 },
263                 { "m", "m",  &store1, 3,  0 },
264                 { "m", "m",  &store2, 4,  0 },
265                 { "m", "m",  NULL,    5,  0 },
266         };
268         size_t i;
270         sdb_memstore_host(store, "m", 1, 0);
271         sdb_memstore_host(store, "l", 1, 0);
272         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
273                 int status;
275                 status = sdb_memstore_metric(store, golden_data[i].host,
276                                 golden_data[i].metric, golden_data[i].store,
277                                 golden_data[i].last_update, 0);
278                 fail_unless(status == golden_data[i].expected,
279                                 "sdb_memstore_metric(%s, %s, %p, %d, 0) = %d; expected: %d",
280                                 golden_data[i].host, golden_data[i].metric,
281                                 golden_data[i].store, golden_data[i].last_update,
282                                 status, golden_data[i].expected);
284                 if (status < 0)
285                         continue;
287                 if (golden_data[i].store != NULL)
288                         fail_unless(golden_data[i].store->last_update > 0,
289                                         "sdb_memstore_metric(%s, %s, %p, %d, 0) did not update "
290                                         "store->last_update",
291                                         golden_data[i].host, golden_data[i].metric,
292                                         golden_data[i].store, golden_data[i].last_update);
293         }
295 END_TEST
297 START_TEST(test_store_metric_attr)
299         struct {
300                 const char *host;
301                 const char *metric;
302                 const char *attr;
303                 const sdb_data_t value;
304                 sdb_time_t  last_update;
305                 int expected;
306         } golden_data[] = {
307                 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
308                 /* retry, it should still fail */
309                 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
310                 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
311                 /* retry, it should still fail */
312                 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
313                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
314                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2,  0 },
315                 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
316                 { "l", "m2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
317                 { "m", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
318         };
320         size_t i;
322         sdb_memstore_host(store, "m", 1, 0);
323         sdb_memstore_host(store, "l", 1, 0);
324         sdb_memstore_metric(store, "m", "m1", NULL, 1, 0);
325         sdb_memstore_metric(store, "l", "m1", NULL, 1, 0);
326         sdb_memstore_metric(store, "l", "m2", NULL, 1, 0);
328         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
329                 int status;
331                 status = sdb_memstore_metric_attr(store, golden_data[i].host,
332                                 golden_data[i].metric, golden_data[i].attr,
333                                 &golden_data[i].value, golden_data[i].last_update, 0);
334                 fail_unless(status == golden_data[i].expected,
335                                 "sdb_memstore_metric_attr(%s, %s, %s, %d, %d, 0) = %d; "
336                                 "expected: %d", golden_data[i].host, golden_data[i].metric,
337                                 golden_data[i].attr, golden_data[i].value.data.integer,
338                                 golden_data[i].last_update, status, golden_data[i].expected);
339         }
341 END_TEST
343 START_TEST(test_store_service)
345         struct {
346                 const char *host;
347                 const char *svc;
348                 sdb_time_t  last_update;
349                 int         expected;
350         } golden_data[] = {
351                 { "k", "s",  1, -1 },
352                 { "k", "s",  1, -1 }, /* retry to ensure the host is not created */
353                 { "l", "s1", 1,  0 },
354                 { "l", "s1", 2,  0 },
355                 { "l", "s2", 1,  0 },
356                 { "m", "s",  1,  0 },
357         };
359         size_t i;
361         sdb_memstore_host(store, "m", 1, 0);
362         sdb_memstore_host(store, "l", 1, 0);
363         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
364                 int status;
366                 status = sdb_memstore_service(store, golden_data[i].host,
367                                 golden_data[i].svc, golden_data[i].last_update, 0);
368                 fail_unless(status == golden_data[i].expected,
369                                 "sdb_memstore_service(%s, %s, %d, 0) = %d; expected: %d",
370                                 golden_data[i].host, golden_data[i].svc,
371                                 golden_data[i].last_update, status, golden_data[i].expected);
372         }
374 END_TEST
376 START_TEST(test_store_service_attr)
378         struct {
379                 const char *host;
380                 const char *svc;
381                 const char *attr;
382                 const sdb_data_t value;
383                 sdb_time_t  last_update;
384                 int expected;
385         } golden_data[] = {
386                 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
387                 /* retry, it should still fail */
388                 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
389                 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
390                 /* retry, it should still fail */
391                 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
392                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
393                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2,  0 },
394                 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
395                 { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
396                 { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
397         };
399         size_t i;
401         sdb_memstore_host(store, "m", 1, 0);
402         sdb_memstore_host(store, "l", 1, 0);
403         sdb_memstore_service(store, "m", "s1", 1, 0);
404         sdb_memstore_service(store, "l", "s1", 1, 0);
405         sdb_memstore_service(store, "l", "s2", 1, 0);
407         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
408                 int status;
410                 status = sdb_memstore_service_attr(store, golden_data[i].host,
411                                 golden_data[i].svc, golden_data[i].attr,
412                                 &golden_data[i].value, golden_data[i].last_update, 0);
413                 fail_unless(status == golden_data[i].expected,
414                                 "sdb_memstore_service_attr(%s, %s, %s, %d, %d, 0) = %d; "
415                                 "expected: %d", golden_data[i].host, golden_data[i].svc,
416                                 golden_data[i].attr, golden_data[i].value.data.integer,
417                                 golden_data[i].last_update, status, golden_data[i].expected);
418         }
420 END_TEST
422 static struct {
423         const char *hostname;
424         const char *attr; /* optional */
425         int field;
426         int expected;
427         sdb_data_t value;
428 } get_field_data[] = {
429         { NULL,   NULL, 0, -1, { SDB_TYPE_NULL, { 0 } } },
430         { NULL,   NULL,   SDB_FIELD_LAST_UPDATE, -1, { SDB_TYPE_NULL, { 0 } } },
431         { NULL,   NULL,   SDB_FIELD_INTERVAL,    -1, { SDB_TYPE_NULL, { 0 } } },
432         { NULL,   NULL,   SDB_FIELD_AGE,         -1, { SDB_TYPE_NULL, { 0 } } },
433         { NULL,   NULL,   SDB_FIELD_NAME,        -1, { SDB_TYPE_NULL, { 0 } } },
434         { NULL,   NULL,   SDB_FIELD_BACKEND,     -1, { SDB_TYPE_NULL, { 0 } } },
435         { NULL,   NULL,   SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
436         { "host", NULL,   SDB_FIELD_LAST_UPDATE,  0, { SDB_TYPE_DATETIME, { .datetime = 20 } } },
437         { "host", NULL,   SDB_FIELD_INTERVAL,     0, { SDB_TYPE_DATETIME, { .datetime = 10 } } },
438         /* the test will handle AGE specially */
439         { "host", NULL,   SDB_FIELD_AGE,          0, { SDB_TYPE_NULL, { 0 } } },
440         { "host", NULL,   SDB_FIELD_NAME,         0, { SDB_TYPE_STRING, { .string = "host" } } },
441         { "host", NULL,   SDB_FIELD_BACKEND,      0, { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } } },
442         { "host", NULL,   SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
443         { "host", "attr", SDB_FIELD_LAST_UPDATE,  0, { SDB_TYPE_DATETIME, { .datetime = 20 } } },
444         { "host", "attr", SDB_FIELD_INTERVAL,     0, { SDB_TYPE_DATETIME, { .datetime = 10 } } },
445         /* the test will handle AGE specially */
446         { "host", "attr", SDB_FIELD_AGE,          0, { SDB_TYPE_NULL, { 0 } } },
447         { "host", "attr", SDB_FIELD_NAME,         0, { SDB_TYPE_STRING, { .string = "attr" } } },
448         { "host", "attr", SDB_FIELD_BACKEND,      0, { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } } },
449         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_INTEGER, { .integer = 1 } } },
450         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_DECIMAL, { .decimal = 2.0 } } },
451         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_STRING, { .string = "foo" } } },
452         { "host", "attr", SDB_FIELD_VALUE,        0, { SDB_TYPE_DATETIME, { .datetime = 1234567890L } } },
453         { "host", "a",    SDB_FIELD_LAST_UPDATE, -1, { SDB_TYPE_NULL, { 0 } } },
454         { "host", "a",    SDB_FIELD_INTERVAL,    -1, { SDB_TYPE_NULL, { 0 } } },
455         { "host", "a",    SDB_FIELD_AGE,         -1, { SDB_TYPE_NULL, { 0 } } },
456         { "host", "a",    SDB_FIELD_NAME,        -1, { SDB_TYPE_NULL, { 0 } } },
457         { "host", "a",    SDB_FIELD_BACKEND,     -1, { SDB_TYPE_NULL, { 0 } } },
458         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
459         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
460         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
461         { "host", "a",    SDB_FIELD_VALUE,       -1, { SDB_TYPE_NULL, { 0 } } },
462 };
464 /* returns a tuple <type> <name> */
465 #define OBJ_NAME(obj) \
466         (obj) ? SDB_STORE_TYPE_TO_NAME(obj->type) : "NULL", \
467         (obj) ? SDB_OBJ(obj)->name : ""
468 START_TEST(test_get_field)
470         sdb_memstore_obj_t *obj = NULL;
471         sdb_data_t value = SDB_DATA_INIT;
472         char value_str[128], expected_value_str[128];
473         sdb_time_t now = sdb_gettime();
474         int check;
476         sdb_memstore_host(store, "host", 20, 10);
477         sdb_memstore_attribute(store, "host", "attr", &get_field_data[_i].value, 20, 10);
479         if (get_field_data[_i].hostname) {
480                 obj = sdb_memstore_get_host(store, get_field_data[_i].hostname);
481                 ck_assert(obj != NULL);
483                 if (get_field_data[_i].attr) {
484                         sdb_memstore_obj_t *tmp = sdb_memstore_get_child(obj,
485                                         SDB_ATTRIBUTE, get_field_data[_i].attr);
486                         sdb_object_deref(SDB_OBJ(obj));
487                         obj = tmp;
488                 }
489         }
491         check = sdb_memstore_get_field(obj, get_field_data[_i].field, NULL);
492         fail_unless(check == get_field_data[_i].expected,
493                         "sdb_memstore_get_field(%s %s, %s, NULL) = %d; expected: %d",
494                         OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field),
495                         check, get_field_data[_i].expected);
496         check = sdb_memstore_get_field(obj, get_field_data[_i].field, &value);
497         fail_unless(check == get_field_data[_i].expected,
498                         "sdb_memstore_get_field(%s %s, %s, <value>) = %d; expected: %d",
499                         OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field),
500                         check, get_field_data[_i].expected);
502         if (get_field_data[_i].expected) {
503                 sdb_object_deref(SDB_OBJ(obj));
504                 return;
505         }
507         if (get_field_data[_i].field == SDB_FIELD_AGE) {
508                 get_field_data[_i].value.type = SDB_TYPE_DATETIME;
509                 get_field_data[_i].value.data.datetime = now;
510         }
512         sdb_data_format(&value, value_str, sizeof(value_str), 0);
513         sdb_data_format(&get_field_data[_i].value, expected_value_str,
514                         sizeof(expected_value_str), 0);
516         if (get_field_data[_i].field == SDB_FIELD_AGE) {
517                 fail_unless((value.type == SDB_TYPE_DATETIME)
518                                 && (value.data.datetime >= now),
519                                 "sdb_memstore_get_field(%s %s, %s, <value>) "
520                                 "returned value %s; expected >=%s", OBJ_NAME(obj),
521                                 SDB_FIELD_TO_NAME(get_field_data[_i].field),
522                                 value_str, expected_value_str);
523         }
524         else {
525                 fail_unless(! sdb_data_cmp(&value, &get_field_data[_i].value),
526                                 "sdb_memstore_get_field(%s %s, %s, <value>) "
527                                 "returned value %s; expected %s", OBJ_NAME(obj),
528                                 SDB_FIELD_TO_NAME(get_field_data[_i].field),
529                                 value_str, expected_value_str);
530         }
531         sdb_data_free_datum(&value);
532         sdb_object_deref(SDB_OBJ(obj));
534 END_TEST
535 #undef OBJ_NAME
537 START_TEST(test_get_child)
539         struct {
540                 const char *host;
541                 int parent_type;
542                 const char *parent;
543                 const char *name;
544                 int type;
545                 int expected;
546         } golden_data[] = {
547                 { "h1",          -1, NULL, NULL, SDB_HOST,       0 },
548                 { "h1",          -1, NULL, NULL, SDB_SERVICE,   -1 },
549                 { "h1",          -1, NULL, NULL, SDB_METRIC,    -1 },
550                 { "h1",          -1, NULL, NULL, SDB_ATTRIBUTE, -1 },
551                 { "h2",          -1, NULL, NULL, SDB_HOST,       0 },
552                 { "h2",          -1, NULL, NULL, SDB_SERVICE,   -1 },
553                 { "h2",          -1, NULL, NULL, SDB_METRIC,    -1 },
554                 { "h2",          -1, NULL, NULL, SDB_ATTRIBUTE, -1 },
555                 { "h3",          -1, NULL, NULL, SDB_HOST,      -1 },
556                 { "h1",          -1, NULL, "k1", SDB_ATTRIBUTE,  0 },
557                 { "h1",          -1, NULL, "x1", SDB_ATTRIBUTE, -1 },
558                 { "h2",          -1, NULL, "k1", SDB_ATTRIBUTE, -1 },
559                 { "h1",          -1, NULL, "k1", SDB_SERVICE,   -1 },
560                 { "h1",          -1, NULL, "k1", SDB_METRIC,    -1 },
561                 { "h1",          -1, NULL, "s1", SDB_SERVICE,   -1 },
562                 { "h2",          -1, NULL, "s1", SDB_SERVICE,    0 },
563                 { "h1",          -1, NULL, "m2", SDB_METRIC,     0 },
564                 { "h2",          -1, NULL, "m2", SDB_METRIC,    -1 },
565                 { "h1",  SDB_METRIC, "m1", "k3", SDB_ATTRIBUTE,  0 },
566                 { "h1",  SDB_METRIC, "m1", "x1", SDB_ATTRIBUTE, -1 },
567                 { "h2", SDB_SERVICE, "s2", "k1", SDB_ATTRIBUTE,  0 },
568                 { "h2", SDB_SERVICE, "s2", "x1", SDB_ATTRIBUTE, -1 },
569         };
571         size_t i;
573         populate();
575         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
576                 sdb_memstore_obj_t *obj;
577                 const char *expected_name = golden_data[i].host;
579                 obj = sdb_memstore_get_host(store, golden_data[i].host);
580                 if (golden_data[i].parent) {
581                         sdb_memstore_obj_t *o;
582                         o = sdb_memstore_get_child(obj,
583                                         golden_data[i].parent_type, golden_data[i].parent);
584                         sdb_object_deref(SDB_OBJ(obj));
585                         obj = o;
586                 }
587                 if (golden_data[i].expected && (golden_data[i].type == SDB_HOST))
588                         fail_unless(obj == NULL,
589                                         "sdb_memstore_get_host(%s) = %p; expected: NULL",
590                                         golden_data[i].host, obj);
591                 else
592                         fail_unless(obj != NULL,
593                                         "sdb_memstore_get_host(%s) = NULL; expected: <host>",
594                                         golden_data[i].host);
596                 if (golden_data[i].type != SDB_HOST) {
597                         sdb_memstore_obj_t *tmp;
599                         expected_name = golden_data[i].name;
601                         tmp = sdb_memstore_get_child(obj,
602                                         golden_data[i].type, golden_data[i].name);
603                         if (golden_data[i].expected)
604                                 fail_unless(tmp == NULL,
605                                                 "sdb_memstore_get_child(<%s>, %s, %s) = %p; "
606                                                 "expected: NULL", golden_data[i].host,
607                                                 SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
608                                                 golden_data[i].name, tmp);
609                         else
610                                 fail_unless(tmp != NULL,
611                                                 "sdb_memstore_get_child(<%s>, %s, %s) = NULL; "
612                                                 "expected: <obj>", golden_data[i].host,
613                                                 SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
614                                                 golden_data[i].name);
616                         sdb_object_deref(SDB_OBJ(obj));
617                         obj = tmp;
618                 }
620                 if (golden_data[i].expected)
621                         continue;
623                 fail_unless(obj->type == golden_data[i].type,
624                                 "sdb_memstore_get_<%s>(%s, %s) returned object of type %d; "
625                                 "expected: %d", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
626                                 golden_data[i].host, golden_data[i].name, obj->type,
627                                 golden_data[i].type);
628                 fail_unless(! strcasecmp(SDB_OBJ(obj)->name, expected_name),
629                                 "sdb_memstore_get_<%s>(%s, %s) returned object named '%s'; "
630                                 "expected: '%s'", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
631                                 golden_data[i].host, golden_data[i].name, SDB_OBJ(obj)->name,
632                                 expected_name);
634                 sdb_object_deref(SDB_OBJ(obj));
635         }
637 END_TEST
639 /* TODO: move these tests into generic store tests */
640 #if 0
641 START_TEST(test_interval)
643         sdb_memstore_obj_t *host;
645         /* 10 us interval */
646         sdb_memstore_host(store, "host", 10);
647         sdb_memstore_host(store, "host", 20);
648         sdb_memstore_host(store, "host", 30);
649         sdb_memstore_host(store, "host", 40);
651         host = sdb_memstore_get_host(store, "host");
652         fail_unless(host != NULL,
653                         "INTERNAL ERROR: store doesn't have host after adding it");
655         fail_unless(host->interval == 10,
656                         "sdb_memstore_host() did not calculate interval correctly: "
657                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10);
659         /* multiple updates for the same timestamp don't modify the interval */
660         sdb_memstore_host(store, "host", 40);
661         sdb_memstore_host(store, "host", 40);
662         sdb_memstore_host(store, "host", 40);
663         sdb_memstore_host(store, "host", 40);
665         fail_unless(host->interval == 10,
666                         "sdb_memstore_host() changed interval when doing multiple updates "
667                         "using the same timestamp; got: %"PRIsdbTIME"; "
668                         "expected: %"PRIsdbTIME, host->interval, 10);
670         /* multiple updates using an timestamp don't modify the interval */
671         sdb_memstore_host(store, "host", 20);
672         sdb_memstore_host(store, "host", 20);
673         sdb_memstore_host(store, "host", 20);
674         sdb_memstore_host(store, "host", 20);
676         fail_unless(host->interval == 10,
677                         "sdb_memstore_host() changed interval when doing multiple updates "
678                         "using an old timestamp; got: %"PRIsdbTIME"; expected: %"PRIsdbTIME,
679                         host->interval, 10);
681         /* new interval: 20 us */
682         sdb_memstore_host(store, "host", 60);
683         fail_unless(host->interval == 11,
684                         "sdb_memstore_host() did not calculate interval correctly: "
685                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
687         /* new interval: 40 us */
688         sdb_memstore_host(store, "host", 100);
689         fail_unless(host->interval == 13,
690                         "sdb_memstore_host() did not calculate interval correctly: "
691                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
693         sdb_object_deref(SDB_OBJ(host));
695 END_TEST
696 #endif
698 static int
699 scan_count(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data)
701         intptr_t *i = user_data;
703         if (! sdb_memstore_matcher_matches(filter, obj, NULL))
704                 return 0;
706         fail_unless(obj != NULL,
707                         "sdb_memstore_scan callback received NULL obj; expected: "
708                         "<store base obj>");
709         fail_unless(i != NULL,
710                         "sdb_memstore_scan callback received NULL user_data; "
711                         "expected: <pointer to data>");
713         ++(*i);
714         return 0;
715 } /* scan_count */
717 static int
718 scan_error(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data)
720         intptr_t *i = user_data;
722         if (! sdb_memstore_matcher_matches(filter, obj, NULL))
723                 return 0;
725         fail_unless(obj != NULL,
726                         "sdb_memstore_scan callback received NULL obj; expected: "
727                         "<store base obj>");
728         fail_unless(i != NULL,
729                         "sdb_memstore_scan callback received NULL user_data; "
730                         "expected: <pointer to data>");
732         ++(*i);
733         return -1;
734 } /* scan_error */
736 START_TEST(test_scan)
738         intptr_t i = 0;
739         int check;
741         /* empty store */
742         check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL,
743                         scan_count, &i);
744         fail_unless(check == 0,
745                         "sdb_memstore_scan(HOST), empty store = %d; expected: 0", check);
746         fail_unless(i == 0,
747                         "sdb_memstore_scan(HOST) called callback %d times; "
748                         "expected: 0", (int)i);
750         populate();
752         check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL,
753                         scan_count, &i);
754         fail_unless(check == 0,
755                         "sdb_memstore_scan(HOST) = %d; expected: 0", check);
756         fail_unless(i == 2,
757                         "sdb_memstore_scan(HOST) called callback %d times; "
758                         "expected: 1", (int)i);
760         i = 0;
761         check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL,
762                         scan_error, &i);
763         fail_unless(check == -1,
764                         "sdb_memstore_scan(HOST), error callback = %d; expected: -1", check);
765         fail_unless(i == 1,
766                         "sdb_memstore_scan(HOST) called callback %d times "
767                         "(callback returned error); expected: 1", (int)i);
769         i = 0;
770         check = sdb_memstore_scan(store, SDB_SERVICE, /* m, filter = */ NULL, NULL,
771                         scan_count, &i);
772         fail_unless(check == 0,
773                         "sdb_memstore_scan(SERVICE) = %d; expected: 0", check);
774         fail_unless(i == 2,
775                         "sdb_memstore_scan(SERVICE) called callback %d times; "
776                         "expected: 2", (int)i);
778         i = 0;
779         check = sdb_memstore_scan(store, SDB_METRIC, /* m, filter = */ NULL, NULL,
780                         scan_count, &i);
781         fail_unless(check == 0,
782                         "sdb_memstore_scan(METRIC) = %d; expected: 0", check);
783         fail_unless(i == 3,
784                         "sdb_memstore_scan(METRIC) called callback %d times; "
785                         "expected: 3", (int)i);
787 END_TEST
789 TEST_MAIN("core::store")
791         TCase *tc = tcase_create("core");
792         tcase_add_unchecked_fixture(tc, init, turndown);
793         tcase_add_test(tc, test_store_host);
794         tcase_add_test(tc, test_store_get_host);
795         tcase_add_test(tc, test_store_attr);
796         tcase_add_test(tc, test_store_metric);
797         tcase_add_test(tc, test_store_metric_attr);
798         tcase_add_test(tc, test_store_service);
799         tcase_add_test(tc, test_store_service_attr);
800         TC_ADD_LOOP_TEST(tc, get_field);
801         tcase_add_test(tc, test_get_child);
802         tcase_add_test(tc, test_scan);
803         ADD_TCASE(tc);
805 TEST_MAIN_END
807 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */