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)
100 {
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 }
144 }
145 END_TEST
147 START_TEST(test_store_get_host)
148 {
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 }
197 }
198 END_TEST
200 START_TEST(test_store_attr)
201 {
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 }
237 }
238 END_TEST
240 START_TEST(test_store_metric)
241 {
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);
283 }
284 }
285 END_TEST
287 START_TEST(test_store_metric_attr)
288 {
289 struct {
290 const char *host;
291 const char *metric;
292 const char *attr;
293 const sdb_data_t value;
294 sdb_time_t last_update;
295 int expected;
296 } golden_data[] = {
297 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
298 /* retry, it should still fail */
299 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
300 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
301 /* retry, it should still fail */
302 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
303 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
304 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 },
305 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
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_memstore_host(store, "m", 1, 0);
313 sdb_memstore_host(store, "l", 1, 0);
314 sdb_memstore_metric(store, "m", "m1", NULL, 1, 0);
315 sdb_memstore_metric(store, "l", "m1", NULL, 1, 0);
316 sdb_memstore_metric(store, "l", "m2", NULL, 1, 0);
318 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
319 int status;
321 status = sdb_memstore_metric_attr(store, golden_data[i].host,
322 golden_data[i].metric, golden_data[i].attr,
323 &golden_data[i].value, golden_data[i].last_update, 0);
324 fail_unless(status == golden_data[i].expected,
325 "sdb_memstore_metric_attr(%s, %s, %s, %d, %d, 0) = %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 }
330 }
331 END_TEST
333 START_TEST(test_store_service)
334 {
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", "s2", 1, 0 },
346 { "m", "s", 1, 0 },
347 };
349 size_t i;
351 sdb_memstore_host(store, "m", 1, 0);
352 sdb_memstore_host(store, "l", 1, 0);
353 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
354 int status;
356 status = sdb_memstore_service(store, golden_data[i].host,
357 golden_data[i].svc, golden_data[i].last_update, 0);
358 fail_unless(status == golden_data[i].expected,
359 "sdb_memstore_service(%s, %s, %d, 0) = %d; expected: %d",
360 golden_data[i].host, golden_data[i].svc,
361 golden_data[i].last_update, status, golden_data[i].expected);
362 }
363 }
364 END_TEST
366 START_TEST(test_store_service_attr)
367 {
368 struct {
369 const char *host;
370 const char *svc;
371 const char *attr;
372 const sdb_data_t value;
373 sdb_time_t last_update;
374 int expected;
375 } golden_data[] = {
376 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
377 /* retry, it should still fail */
378 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
379 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
380 /* retry, it should still fail */
381 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
382 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
383 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 },
384 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
385 { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
386 { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
387 };
389 size_t i;
391 sdb_memstore_host(store, "m", 1, 0);
392 sdb_memstore_host(store, "l", 1, 0);
393 sdb_memstore_service(store, "m", "s1", 1, 0);
394 sdb_memstore_service(store, "l", "s1", 1, 0);
395 sdb_memstore_service(store, "l", "s2", 1, 0);
397 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
398 int status;
400 status = sdb_memstore_service_attr(store, golden_data[i].host,
401 golden_data[i].svc, golden_data[i].attr,
402 &golden_data[i].value, golden_data[i].last_update, 0);
403 fail_unless(status == golden_data[i].expected,
404 "sdb_memstore_service_attr(%s, %s, %s, %d, %d, 0) = %d; "
405 "expected: %d", golden_data[i].host, golden_data[i].svc,
406 golden_data[i].attr, golden_data[i].value.data.integer,
407 golden_data[i].last_update, status, golden_data[i].expected);
408 }
409 }
410 END_TEST
412 static struct {
413 const char *hostname;
414 const char *attr; /* optional */
415 int field;
416 int expected;
417 sdb_data_t value;
418 } get_field_data[] = {
419 { NULL, NULL, 0, -1, { SDB_TYPE_NULL, { 0 } } },
420 { NULL, NULL, SDB_FIELD_LAST_UPDATE, -1, { SDB_TYPE_NULL, { 0 } } },
421 { NULL, NULL, SDB_FIELD_INTERVAL, -1, { SDB_TYPE_NULL, { 0 } } },
422 { NULL, NULL, SDB_FIELD_AGE, -1, { SDB_TYPE_NULL, { 0 } } },
423 { NULL, NULL, SDB_FIELD_NAME, -1, { SDB_TYPE_NULL, { 0 } } },
424 { NULL, NULL, SDB_FIELD_BACKEND, -1, { SDB_TYPE_NULL, { 0 } } },
425 { NULL, NULL, SDB_FIELD_VALUE, -1, { SDB_TYPE_NULL, { 0 } } },
426 { "host", NULL, SDB_FIELD_LAST_UPDATE, 0, { SDB_TYPE_DATETIME, { .datetime = 20 } } },
427 { "host", NULL, SDB_FIELD_INTERVAL, 0, { SDB_TYPE_DATETIME, { .datetime = 10 } } },
428 /* the test will handle AGE specially */
429 { "host", NULL, SDB_FIELD_AGE, 0, { SDB_TYPE_NULL, { 0 } } },
430 { "host", NULL, SDB_FIELD_NAME, 0, { SDB_TYPE_STRING, { .string = "host" } } },
431 { "host", NULL, SDB_FIELD_BACKEND, 0, { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } } },
432 { "host", NULL, SDB_FIELD_VALUE, -1, { SDB_TYPE_NULL, { 0 } } },
433 { "host", "attr", SDB_FIELD_LAST_UPDATE, 0, { SDB_TYPE_DATETIME, { .datetime = 20 } } },
434 { "host", "attr", SDB_FIELD_INTERVAL, 0, { SDB_TYPE_DATETIME, { .datetime = 10 } } },
435 /* the test will handle AGE specially */
436 { "host", "attr", SDB_FIELD_AGE, 0, { SDB_TYPE_NULL, { 0 } } },
437 { "host", "attr", SDB_FIELD_NAME, 0, { SDB_TYPE_STRING, { .string = "attr" } } },
438 { "host", "attr", SDB_FIELD_BACKEND, 0, { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } } },
439 { "host", "attr", SDB_FIELD_VALUE, 0, { SDB_TYPE_INTEGER, { .integer = 1 } } },
440 { "host", "attr", SDB_FIELD_VALUE, 0, { SDB_TYPE_DECIMAL, { .decimal = 2.0 } } },
441 { "host", "attr", SDB_FIELD_VALUE, 0, { SDB_TYPE_STRING, { .string = "foo" } } },
442 { "host", "attr", SDB_FIELD_VALUE, 0, { SDB_TYPE_DATETIME, { .datetime = 1234567890L } } },
443 { "host", "a", SDB_FIELD_LAST_UPDATE, -1, { SDB_TYPE_NULL, { 0 } } },
444 { "host", "a", SDB_FIELD_INTERVAL, -1, { SDB_TYPE_NULL, { 0 } } },
445 { "host", "a", SDB_FIELD_AGE, -1, { SDB_TYPE_NULL, { 0 } } },
446 { "host", "a", SDB_FIELD_NAME, -1, { SDB_TYPE_NULL, { 0 } } },
447 { "host", "a", SDB_FIELD_BACKEND, -1, { SDB_TYPE_NULL, { 0 } } },
448 { "host", "a", SDB_FIELD_VALUE, -1, { SDB_TYPE_NULL, { 0 } } },
449 { "host", "a", SDB_FIELD_VALUE, -1, { SDB_TYPE_NULL, { 0 } } },
450 { "host", "a", SDB_FIELD_VALUE, -1, { SDB_TYPE_NULL, { 0 } } },
451 { "host", "a", SDB_FIELD_VALUE, -1, { SDB_TYPE_NULL, { 0 } } },
452 };
454 /* returns a tuple <type> <name> */
455 #define OBJ_NAME(obj) \
456 (obj) ? SDB_STORE_TYPE_TO_NAME(obj->type) : "NULL", \
457 (obj) ? SDB_OBJ(obj)->name : ""
458 START_TEST(test_get_field)
459 {
460 sdb_memstore_obj_t *obj = NULL;
461 sdb_data_t value = SDB_DATA_INIT;
462 char value_str[128], expected_value_str[128];
463 sdb_time_t now = sdb_gettime();
464 int check;
466 sdb_memstore_host(store, "host", 20, 10);
467 sdb_memstore_attribute(store, "host", "attr", &get_field_data[_i].value, 20, 10);
469 if (get_field_data[_i].hostname) {
470 obj = sdb_memstore_get_host(store, get_field_data[_i].hostname);
471 ck_assert(obj != NULL);
473 if (get_field_data[_i].attr) {
474 sdb_memstore_obj_t *tmp = sdb_memstore_get_child(obj,
475 SDB_ATTRIBUTE, get_field_data[_i].attr);
476 sdb_object_deref(SDB_OBJ(obj));
477 obj = tmp;
478 }
479 }
481 check = sdb_memstore_get_field(obj, get_field_data[_i].field, NULL);
482 fail_unless(check == get_field_data[_i].expected,
483 "sdb_memstore_get_field(%s %s, %s, NULL) = %d; expected: %d",
484 OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field),
485 check, get_field_data[_i].expected);
486 check = sdb_memstore_get_field(obj, get_field_data[_i].field, &value);
487 fail_unless(check == get_field_data[_i].expected,
488 "sdb_memstore_get_field(%s %s, %s, <value>) = %d; expected: %d",
489 OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field),
490 check, get_field_data[_i].expected);
492 if (get_field_data[_i].expected) {
493 sdb_object_deref(SDB_OBJ(obj));
494 return;
495 }
497 if (get_field_data[_i].field == SDB_FIELD_AGE) {
498 get_field_data[_i].value.type = SDB_TYPE_DATETIME;
499 get_field_data[_i].value.data.datetime = now;
500 }
502 sdb_data_format(&value, value_str, sizeof(value_str), 0);
503 sdb_data_format(&get_field_data[_i].value, expected_value_str,
504 sizeof(expected_value_str), 0);
506 if (get_field_data[_i].field == SDB_FIELD_AGE) {
507 fail_unless((value.type == SDB_TYPE_DATETIME)
508 && (value.data.datetime >= now),
509 "sdb_memstore_get_field(%s %s, %s, <value>) "
510 "returned value %s; expected >=%s", OBJ_NAME(obj),
511 SDB_FIELD_TO_NAME(get_field_data[_i].field),
512 value_str, expected_value_str);
513 }
514 else {
515 fail_unless(! sdb_data_cmp(&value, &get_field_data[_i].value),
516 "sdb_memstore_get_field(%s %s, %s, <value>) "
517 "returned value %s; expected %s", OBJ_NAME(obj),
518 SDB_FIELD_TO_NAME(get_field_data[_i].field),
519 value_str, expected_value_str);
520 }
521 sdb_data_free_datum(&value);
522 sdb_object_deref(SDB_OBJ(obj));
523 }
524 END_TEST
525 #undef OBJ_NAME
527 START_TEST(test_get_child)
528 {
529 struct {
530 const char *host;
531 int parent_type;
532 const char *parent;
533 const char *name;
534 int type;
535 int expected;
536 } golden_data[] = {
537 { "h1", -1, NULL, NULL, SDB_HOST, 0 },
538 { "h1", -1, NULL, NULL, SDB_SERVICE, -1 },
539 { "h1", -1, NULL, NULL, SDB_METRIC, -1 },
540 { "h1", -1, NULL, NULL, SDB_ATTRIBUTE, -1 },
541 { "h2", -1, NULL, NULL, SDB_HOST, 0 },
542 { "h2", -1, NULL, NULL, SDB_SERVICE, -1 },
543 { "h2", -1, NULL, NULL, SDB_METRIC, -1 },
544 { "h2", -1, NULL, NULL, SDB_ATTRIBUTE, -1 },
545 { "h3", -1, NULL, NULL, SDB_HOST, -1 },
546 { "h1", -1, NULL, "k1", SDB_ATTRIBUTE, 0 },
547 { "h1", -1, NULL, "x1", SDB_ATTRIBUTE, -1 },
548 { "h2", -1, NULL, "k1", SDB_ATTRIBUTE, -1 },
549 { "h1", -1, NULL, "k1", SDB_SERVICE, -1 },
550 { "h1", -1, NULL, "k1", SDB_METRIC, -1 },
551 { "h1", -1, NULL, "s1", SDB_SERVICE, -1 },
552 { "h2", -1, NULL, "s1", SDB_SERVICE, 0 },
553 { "h1", -1, NULL, "m2", SDB_METRIC, 0 },
554 { "h2", -1, NULL, "m2", SDB_METRIC, -1 },
555 { "h1", SDB_METRIC, "m1", "k3", SDB_ATTRIBUTE, 0 },
556 { "h1", SDB_METRIC, "m1", "x1", SDB_ATTRIBUTE, -1 },
557 { "h2", SDB_SERVICE, "s2", "k1", SDB_ATTRIBUTE, 0 },
558 { "h2", SDB_SERVICE, "s2", "x1", SDB_ATTRIBUTE, -1 },
559 };
561 size_t i;
563 populate();
565 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
566 sdb_memstore_obj_t *obj;
567 const char *expected_name = golden_data[i].host;
569 obj = sdb_memstore_get_host(store, golden_data[i].host);
570 if (golden_data[i].parent) {
571 sdb_memstore_obj_t *o;
572 o = sdb_memstore_get_child(obj,
573 golden_data[i].parent_type, golden_data[i].parent);
574 sdb_object_deref(SDB_OBJ(obj));
575 obj = o;
576 }
577 if (golden_data[i].expected && (golden_data[i].type == SDB_HOST))
578 fail_unless(obj == NULL,
579 "sdb_memstore_get_host(%s) = %p; expected: NULL",
580 golden_data[i].host, obj);
581 else
582 fail_unless(obj != NULL,
583 "sdb_memstore_get_host(%s) = NULL; expected: <host>",
584 golden_data[i].host);
586 if (golden_data[i].type != SDB_HOST) {
587 sdb_memstore_obj_t *tmp;
589 expected_name = golden_data[i].name;
591 tmp = sdb_memstore_get_child(obj,
592 golden_data[i].type, golden_data[i].name);
593 if (golden_data[i].expected)
594 fail_unless(tmp == NULL,
595 "sdb_memstore_get_child(<%s>, %s, %s) = %p; "
596 "expected: NULL", golden_data[i].host,
597 SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
598 golden_data[i].name, tmp);
599 else
600 fail_unless(tmp != NULL,
601 "sdb_memstore_get_child(<%s>, %s, %s) = NULL; "
602 "expected: <obj>", golden_data[i].host,
603 SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
604 golden_data[i].name);
606 sdb_object_deref(SDB_OBJ(obj));
607 obj = tmp;
608 }
610 if (golden_data[i].expected)
611 continue;
613 fail_unless(obj->type == golden_data[i].type,
614 "sdb_memstore_get_<%s>(%s, %s) returned object of type %d; "
615 "expected: %d", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
616 golden_data[i].host, golden_data[i].name, obj->type,
617 golden_data[i].type);
618 fail_unless(! strcasecmp(SDB_OBJ(obj)->name, expected_name),
619 "sdb_memstore_get_<%s>(%s, %s) returned object named '%s'; "
620 "expected: '%s'", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
621 golden_data[i].host, golden_data[i].name, SDB_OBJ(obj)->name,
622 expected_name);
624 sdb_object_deref(SDB_OBJ(obj));
625 }
626 }
627 END_TEST
629 /* TODO: move these tests into generic store tests */
630 #if 0
631 START_TEST(test_interval)
632 {
633 sdb_memstore_obj_t *host;
635 /* 10 us interval */
636 sdb_memstore_host(store, "host", 10);
637 sdb_memstore_host(store, "host", 20);
638 sdb_memstore_host(store, "host", 30);
639 sdb_memstore_host(store, "host", 40);
641 host = sdb_memstore_get_host(store, "host");
642 fail_unless(host != NULL,
643 "INTERNAL ERROR: store doesn't have host after adding it");
645 fail_unless(host->interval == 10,
646 "sdb_memstore_host() did not calculate interval correctly: "
647 "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10);
649 /* multiple updates for the same timestamp don't modify the interval */
650 sdb_memstore_host(store, "host", 40);
651 sdb_memstore_host(store, "host", 40);
652 sdb_memstore_host(store, "host", 40);
653 sdb_memstore_host(store, "host", 40);
655 fail_unless(host->interval == 10,
656 "sdb_memstore_host() changed interval when doing multiple updates "
657 "using the same timestamp; got: %"PRIsdbTIME"; "
658 "expected: %"PRIsdbTIME, host->interval, 10);
660 /* multiple updates using an timestamp don't modify the interval */
661 sdb_memstore_host(store, "host", 20);
662 sdb_memstore_host(store, "host", 20);
663 sdb_memstore_host(store, "host", 20);
664 sdb_memstore_host(store, "host", 20);
666 fail_unless(host->interval == 10,
667 "sdb_memstore_host() changed interval when doing multiple updates "
668 "using an old timestamp; got: %"PRIsdbTIME"; expected: %"PRIsdbTIME,
669 host->interval, 10);
671 /* new interval: 20 us */
672 sdb_memstore_host(store, "host", 60);
673 fail_unless(host->interval == 11,
674 "sdb_memstore_host() did not calculate interval correctly: "
675 "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
677 /* new interval: 40 us */
678 sdb_memstore_host(store, "host", 100);
679 fail_unless(host->interval == 13,
680 "sdb_memstore_host() did not calculate interval correctly: "
681 "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
683 sdb_object_deref(SDB_OBJ(host));
684 }
685 END_TEST
686 #endif
688 static int
689 scan_count(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data)
690 {
691 intptr_t *i = user_data;
693 if (! sdb_memstore_matcher_matches(filter, obj, NULL))
694 return 0;
696 fail_unless(obj != NULL,
697 "sdb_memstore_scan callback received NULL obj; expected: "
698 "<store base obj>");
699 fail_unless(i != NULL,
700 "sdb_memstore_scan callback received NULL user_data; "
701 "expected: <pointer to data>");
703 ++(*i);
704 return 0;
705 } /* scan_count */
707 static int
708 scan_error(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data)
709 {
710 intptr_t *i = user_data;
712 if (! sdb_memstore_matcher_matches(filter, obj, NULL))
713 return 0;
715 fail_unless(obj != NULL,
716 "sdb_memstore_scan callback received NULL obj; expected: "
717 "<store base obj>");
718 fail_unless(i != NULL,
719 "sdb_memstore_scan callback received NULL user_data; "
720 "expected: <pointer to data>");
722 ++(*i);
723 return -1;
724 } /* scan_error */
726 START_TEST(test_scan)
727 {
728 intptr_t i = 0;
729 int check;
731 /* empty store */
732 check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL,
733 scan_count, &i);
734 fail_unless(check == 0,
735 "sdb_memstore_scan(HOST), empty store = %d; expected: 0", check);
736 fail_unless(i == 0,
737 "sdb_memstore_scan(HOST) called callback %d times; "
738 "expected: 0", (int)i);
740 populate();
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) = %d; expected: 0", check);
746 fail_unless(i == 2,
747 "sdb_memstore_scan(HOST) called callback %d times; "
748 "expected: 1", (int)i);
750 i = 0;
751 check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL,
752 scan_error, &i);
753 fail_unless(check == -1,
754 "sdb_memstore_scan(HOST), error callback = %d; expected: -1", check);
755 fail_unless(i == 1,
756 "sdb_memstore_scan(HOST) called callback %d times "
757 "(callback returned error); expected: 1", (int)i);
759 i = 0;
760 check = sdb_memstore_scan(store, SDB_SERVICE, /* m, filter = */ NULL, NULL,
761 scan_count, &i);
762 fail_unless(check == 0,
763 "sdb_memstore_scan(SERVICE) = %d; expected: 0", check);
764 fail_unless(i == 2,
765 "sdb_memstore_scan(SERVICE) called callback %d times; "
766 "expected: 2", (int)i);
768 i = 0;
769 check = sdb_memstore_scan(store, SDB_METRIC, /* m, filter = */ NULL, NULL,
770 scan_count, &i);
771 fail_unless(check == 0,
772 "sdb_memstore_scan(METRIC) = %d; expected: 0", check);
773 fail_unless(i == 3,
774 "sdb_memstore_scan(METRIC) called callback %d times; "
775 "expected: 3", (int)i);
776 }
777 END_TEST
779 TEST_MAIN("core::store")
780 {
781 TCase *tc = tcase_create("core");
782 tcase_add_unchecked_fixture(tc, init, turndown);
783 tcase_add_test(tc, test_store_host);
784 tcase_add_test(tc, test_store_get_host);
785 tcase_add_test(tc, test_store_attr);
786 tcase_add_test(tc, test_store_metric);
787 tcase_add_test(tc, test_store_metric_attr);
788 tcase_add_test(tc, test_store_service);
789 tcase_add_test(tc, test_store_service_attr);
790 TC_ADD_LOOP_TEST(tc, get_field);
791 tcase_add_test(tc, test_get_child);
792 tcase_add_test(tc, test_scan);
793 ADD_TCASE(tc);
794 }
795 TEST_MAIN_END
797 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */