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 #include "core/store.h"
29 #include "core/store-private.h"
30 #include "libsysdb_test.h"
32 #include <check.h>
33 #include <string.h>
35 static void
36 populate(void)
37 {
38 sdb_data_t datum;
40 sdb_store_host("h1", 1);
41 sdb_store_host("h2", 3);
43 datum.type = SDB_TYPE_STRING;
44 datum.data.string = "v1";
45 sdb_store_attribute("h1", "k1", &datum, 1);
46 datum.data.string = "v2";
47 sdb_store_attribute("h1", "k2", &datum, 2);
48 datum.data.string = "v3";
49 sdb_store_attribute("h1", "k3", &datum, 2);
51 /* make sure that older updates don't overwrite existing values */
52 datum.data.string = "fail";
53 sdb_store_attribute("h1", "k2", &datum, 1);
54 sdb_store_attribute("h1", "k3", &datum, 2);
56 sdb_store_metric("h1", "m1", /* store */ NULL, 2);
57 sdb_store_metric("h1", "m2", /* store */ NULL, 1);
58 sdb_store_metric("h2", "m1", /* store */ NULL, 1);
60 sdb_store_service("h2", "s1", 1);
61 sdb_store_service("h2", "s2", 2);
63 datum.type = SDB_TYPE_INTEGER;
64 datum.data.integer = 42;
65 sdb_store_metric_attr("h1", "m1", "k3", &datum, 2);
67 datum.data.integer = 123;
68 sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
69 datum.data.integer = 4711;
70 sdb_store_service_attr("h2", "s2", "k2", &datum, 1);
72 /* don't overwrite k1 */
73 datum.data.integer = 666;
74 sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
75 } /* populate */
77 START_TEST(test_store_host)
78 {
79 struct {
80 const char *name;
81 sdb_time_t last_update;
82 int expected;
83 } golden_data[] = {
84 { "a", 1, 0 },
85 { "a", 2, 0 },
86 { "a", 1, 1 },
87 { "b", 1, 0 },
88 { "b", 1, 1 },
89 { "A", 1, 1 }, /* case-insensitive */
90 { "A", 3, 0 },
91 };
93 struct {
94 const char *name;
95 _Bool has;
96 } golden_hosts[] = {
97 { "a", 1 == 1 },
98 { "b", 1 == 1 },
99 { "c", 0 == 1 },
100 { "A", 1 == 1 },
101 };
103 size_t i;
105 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
106 int status;
108 status = sdb_store_host(golden_data[i].name,
109 golden_data[i].last_update);
110 fail_unless(status == golden_data[i].expected,
111 "sdb_store_host(%s, %d) = %d; expected: %d",
112 golden_data[i].name, (int)golden_data[i].last_update,
113 status, golden_data[i].expected);
114 }
116 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
117 _Bool has;
119 has = sdb_store_has_host(golden_hosts[i].name);
120 fail_unless(has == golden_hosts[i].has,
121 "sdb_store_has_host(%s) = %d; expected: %d",
122 golden_hosts[i].name, has, golden_hosts[i].has);
123 }
124 }
125 END_TEST
127 START_TEST(test_store_get_host)
128 {
129 char *golden_hosts[] = { "a", "b", "c" };
130 char *unknown_hosts[] = { "x", "y", "z" };
131 size_t i;
133 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
134 int status = sdb_store_host(golden_hosts[i], 1);
135 fail_unless(status >= 0,
136 "sdb_store_host(%s) = %d; expected: >=0",
137 golden_hosts[i], status);
138 }
140 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
141 sdb_store_obj_t *sobj1, *sobj2;
142 int ref_cnt;
144 fail_unless(sdb_store_has_host(golden_hosts[i]),
145 "sdb_store_has_host(%s) = FALSE; expected: TRUE",
146 golden_hosts[i]);
148 sobj1 = sdb_store_get_host(golden_hosts[i]);
149 fail_unless(sobj1 != NULL,
150 "sdb_store_get_host(%s) = NULL; expected: <host>",
151 golden_hosts[i]);
152 ref_cnt = SDB_OBJ(sobj1)->ref_cnt;
154 fail_unless(ref_cnt > 1,
155 "sdb_store_get_host(%s) did not increment ref count: "
156 "got: %d; expected: >1", golden_hosts[i], ref_cnt);
158 sobj2 = sdb_store_get_host(golden_hosts[i]);
159 fail_unless(sobj2 != NULL,
160 "sdb_store_get_host(%s) = NULL; expected: <host>",
161 golden_hosts[i]);
163 fail_unless(sobj1 == sobj2,
164 "sdb_store_get_host(%s) returned different objects "
165 "in successive calls", golden_hosts[i]);
166 fail_unless(SDB_OBJ(sobj2)->ref_cnt == ref_cnt + 1,
167 "sdb_store_get_hosts(%s) did not increment ref count "
168 "(first call: %d; second call: %d)",
169 golden_hosts[i], ref_cnt, SDB_OBJ(sobj2)->ref_cnt);
171 sdb_object_deref(SDB_OBJ(sobj1));
172 sdb_object_deref(SDB_OBJ(sobj2));
173 }
174 for (i = 0; i < SDB_STATIC_ARRAY_LEN(unknown_hosts); ++i) {
175 sdb_store_obj_t *sobj;
177 fail_unless(!sdb_store_has_host(unknown_hosts[i]),
178 "sdb_store_has_host(%s) = TRUE; expected: FALSE",
179 unknown_hosts[i]);
181 sobj = sdb_store_get_host(unknown_hosts[i]);
182 fail_unless(!sobj, "sdb_store_get_host(%s) = <host:%s>; expected: NULL",
183 unknown_hosts[i], sobj ? SDB_OBJ(sobj)->name : "NULL");
184 }
185 }
186 END_TEST
188 START_TEST(test_store_attr)
189 {
190 struct {
191 const char *host;
192 const char *key;
193 char *value;
194 sdb_time_t last_update;
195 int expected;
196 } golden_data[] = {
197 { "k", "k", "v", 1, -1 },
198 { "k", "k", "v", 1, -1 }, /* retry to ensure the host is not created */
199 { "l", "k1", "v1", 1, 0 },
200 { "l", "k1", "v2", 2, 0 },
201 { "l", "k1", "v3", 2, 1 },
202 { "l", "k2", "v1", 1, 0 },
203 { "m", "k", "v1", 1, 0 },
204 { "m", "k", "v2", 1, 1 },
205 };
207 size_t i;
209 sdb_store_host("l", 1);
210 sdb_store_host("m", 1);
211 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
212 sdb_data_t datum;
213 int status;
215 /* XXX: test other types as well */
216 datum.type = SDB_TYPE_STRING;
217 datum.data.string = golden_data[i].value;
219 status = sdb_store_attribute(golden_data[i].host,
220 golden_data[i].key, &datum,
221 golden_data[i].last_update);
222 fail_unless(status == golden_data[i].expected,
223 "sdb_store_attribute(%s, %s, %s, %d) = %d; expected: %d",
224 golden_data[i].host, golden_data[i].key, golden_data[i].value,
225 golden_data[i].last_update, status, golden_data[i].expected);
226 }
227 }
228 END_TEST
230 START_TEST(test_store_metric)
231 {
232 sdb_metric_store_t store1 = { "dummy-type1", "dummy-id1" };
233 sdb_metric_store_t store2 = { "dummy-type2", "dummy-id2" };
235 struct {
236 const char *host;
237 const char *metric;
238 sdb_metric_store_t *store;
239 sdb_time_t last_update;
240 int expected;
241 } golden_data[] = {
242 { "k", "m", NULL, 1, -1 },
243 { "k", "m", NULL, 1, -1 }, /* retry to ensure the host is not created */
244 { "k", "m", &store1, 1, -1 },
245 { "l", "m1", NULL, 1, 0 },
246 { "l", "m1", &store1, 2, 0 },
247 { "l", "m1", &store1, 3, 0 },
248 { "l", "m1", NULL, 3, 1 },
249 { "l", "m2", &store1, 1, 0 },
250 { "l", "m2", &store2, 2, 0 },
251 { "l", "m2", NULL, 3, 0 },
252 { "m", "m", &store1, 1, 0 },
253 { "m", "m", NULL, 2, 0 },
254 { "m", "m", NULL, 2, 1 },
255 { "m", "m", &store1, 3, 0 },
256 { "m", "m", &store2, 4, 0 },
257 { "m", "m", NULL, 5, 0 },
258 };
260 size_t i;
262 sdb_store_host("m", 1);
263 sdb_store_host("l", 1);
264 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
265 int status;
267 status = sdb_store_metric(golden_data[i].host,
268 golden_data[i].metric, golden_data[i].store,
269 golden_data[i].last_update);
270 fail_unless(status == golden_data[i].expected,
271 "sdb_store_metric(%s, %s, %p, %d) = %d; expected: %d",
272 golden_data[i].host, golden_data[i].metric,
273 golden_data[i].store, golden_data[i].last_update,
274 status, golden_data[i].expected);
275 }
276 }
277 END_TEST
279 START_TEST(test_store_metric_attr)
280 {
281 struct {
282 const char *host;
283 const char *metric;
284 const char *attr;
285 const sdb_data_t value;
286 sdb_time_t last_update;
287 int expected;
288 } golden_data[] = {
289 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
290 /* retry, it should still fail */
291 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
292 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
293 /* retry, it should still fail */
294 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
295 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
296 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
297 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 },
298 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
299 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
300 { "l", "m2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
301 { "m", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
302 };
304 size_t i;
306 sdb_store_host("m", 1);
307 sdb_store_host("l", 1);
308 sdb_store_metric("m", "m1", NULL, 1);
309 sdb_store_metric("l", "m1", NULL, 1);
310 sdb_store_metric("l", "m2", NULL, 1);
312 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
313 int status;
315 status = sdb_store_metric_attr(golden_data[i].host,
316 golden_data[i].metric, golden_data[i].attr,
317 &golden_data[i].value, golden_data[i].last_update);
318 fail_unless(status == golden_data[i].expected,
319 "sdb_store_metric_attr(%s, %s, %s, %d, %d) = %d; "
320 "expected: %d", golden_data[i].host, golden_data[i].metric,
321 golden_data[i].attr, golden_data[i].value.data.integer,
322 golden_data[i].last_update, status, golden_data[i].expected);
323 }
324 }
325 END_TEST
327 START_TEST(test_store_service)
328 {
329 struct {
330 const char *host;
331 const char *svc;
332 sdb_time_t last_update;
333 int expected;
334 } golden_data[] = {
335 { "k", "s", 1, -1 },
336 { "k", "s", 1, -1 }, /* retry to ensure the host is not created */
337 { "l", "s1", 1, 0 },
338 { "l", "s1", 2, 0 },
339 { "l", "s1", 2, 1 },
340 { "l", "s2", 1, 0 },
341 { "m", "s", 1, 0 },
342 { "m", "s", 1, 1 },
343 };
345 size_t i;
347 sdb_store_host("m", 1);
348 sdb_store_host("l", 1);
349 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
350 int status;
352 status = sdb_store_service(golden_data[i].host,
353 golden_data[i].svc, golden_data[i].last_update);
354 fail_unless(status == golden_data[i].expected,
355 "sdb_store_service(%s, %s, %d) = %d; expected: %d",
356 golden_data[i].host, golden_data[i].svc,
357 golden_data[i].last_update, status, golden_data[i].expected);
358 }
359 }
360 END_TEST
362 START_TEST(test_store_service_attr)
363 {
364 struct {
365 const char *host;
366 const char *svc;
367 const char *attr;
368 const sdb_data_t value;
369 sdb_time_t last_update;
370 int expected;
371 } golden_data[] = {
372 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
373 /* retry, it should still fail */
374 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
375 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
376 /* retry, it should still fail */
377 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
378 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
379 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
380 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 },
381 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
382 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
383 { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
384 { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
385 };
387 size_t i;
389 sdb_store_host("m", 1);
390 sdb_store_host("l", 1);
391 sdb_store_service("m", "s1", 1);
392 sdb_store_service("l", "s1", 1);
393 sdb_store_service("l", "s2", 1);
395 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
396 int status;
398 status = sdb_store_service_attr(golden_data[i].host,
399 golden_data[i].svc, golden_data[i].attr,
400 &golden_data[i].value, golden_data[i].last_update);
401 fail_unless(status == golden_data[i].expected,
402 "sdb_store_service_attr(%s, %s, %s, %d, %d) = %d; "
403 "expected: %d", golden_data[i].host, golden_data[i].svc,
404 golden_data[i].attr, golden_data[i].value.data.integer,
405 golden_data[i].last_update, status, golden_data[i].expected);
406 }
407 }
408 END_TEST
410 START_TEST(test_get_field)
411 {
412 sdb_store_obj_t *host;
413 sdb_data_t value = SDB_DATA_INIT;
414 int check;
416 sdb_store_host("host", 10);
417 sdb_store_host("host", 20);
419 host = sdb_store_get_host("host");
420 fail_unless(host != NULL,
421 "INTERNAL ERROR: store doesn't have host after adding it");
423 check = sdb_store_get_field(NULL, 0, NULL);
424 fail_unless(check < 0,
425 "sdb_store_get_field(NULL, 0, NULL) = %d; expected: <0");
426 check = sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, NULL);
427 fail_unless(check < 0,
428 "sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, NULL) = %d; "
429 "expected: <0");
430 check = sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, &value);
431 fail_unless(check < 0,
432 "sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, <value>) = %d; "
433 "expected: <0");
435 check = sdb_store_get_field(host, SDB_FIELD_LAST_UPDATE, NULL);
436 fail_unless(check == 0,
437 "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, NULL) = %d; "
438 "expected: 0");
439 /* 'name' is dynamically allocated; make sure it's not leaked even
440 * if there is no result parameter */
441 check = sdb_store_get_field(host, SDB_FIELD_NAME, NULL);
442 fail_unless(check == 0,
443 "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, NULL) = %d; "
444 "expected: 0");
446 check = sdb_store_get_field(host, SDB_FIELD_NAME, &value);
447 fail_unless(check == 0,
448 "sdb_store_get_field(<host>, SDB_FIELD_NAME, <value>) = "
449 "%d; expected: 0");
450 fail_unless((value.type == SDB_TYPE_STRING)
451 && (! strcmp(value.data.string, "host")),
452 "sdb_store_get_field(<host>, SDB_FIELD_NAME, <value>) "
453 "returned value {%d, %s}; expected {%d, host}",
454 value.type, value.data.string, SDB_TYPE_STRING);
455 sdb_data_free_datum(&value);
457 check = sdb_store_get_field(host, SDB_FIELD_LAST_UPDATE, &value);
458 fail_unless(check == 0,
459 "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, <value>) = "
460 "%d; expected: 0");
461 fail_unless((value.type == SDB_TYPE_DATETIME)
462 && (value.data.datetime == 20),
463 "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, <value>) "
464 "returned value {%d, %lu}; expected {%d, 20}",
465 value.type, value.data.datetime, SDB_TYPE_DATETIME);
467 check = sdb_store_get_field(host, SDB_FIELD_AGE, &value);
468 fail_unless(check == 0,
469 "sdb_store_get_field(<host>, SDB_FIELD_AGE, <value>) = "
470 "%d; expected: 0");
471 /* let's assume we're at least in year 1980 ;-) */
472 fail_unless((value.type == SDB_TYPE_DATETIME)
473 && (value.data.datetime > 10L * SDB_INTERVAL_YEAR),
474 "sdb_store_get_field(<host>, SDB_FIELD_AGE, <value>) "
475 "returned value {%d, %lu}; expected {%d, >%lu}",
476 value.type, value.data.datetime,
477 SDB_TYPE_DATETIME, 10L * SDB_INTERVAL_YEAR);
479 check = sdb_store_get_field(host, SDB_FIELD_INTERVAL, &value);
480 fail_unless(check == 0,
481 "sdb_store_get_field(<host>, SDB_FIELD_INTERVAL, <value>) = "
482 "%d; expected: 0");
483 fail_unless((value.type == SDB_TYPE_DATETIME)
484 && (value.data.datetime == 10),
485 "sdb_store_get_field(<host>, SDB_FIELD_INTERVAL, <value>) "
486 "returned value {%d, %lu}; expected {%d, 10}",
487 value.type, value.data.datetime, SDB_TYPE_DATETIME);
489 check = sdb_store_get_field(host, SDB_FIELD_BACKEND, &value);
490 fail_unless(check == 0,
491 "sdb_store_get_field(<host>, SDB_FIELD_BACKEND, <value>) = "
492 "%d; expected: 0");
493 /* there are no backends in this test */
494 fail_unless((value.type == (SDB_TYPE_ARRAY | SDB_TYPE_STRING))
495 && (value.data.array.length == 0)
496 && (value.data.array.values == NULL),
497 "sdb_store_get_field(<host>, SDB_FIELD_BACKEND, <value>) "
498 "returned value {%d, %lu, %p}; expected {%d, 0, NULL}",
499 value.type, value.data.array.length, value.data.array.values,
500 SDB_TYPE_ARRAY | SDB_TYPE_STRING);
501 }
502 END_TEST
504 START_TEST(test_interval)
505 {
506 sdb_store_obj_t *host;
508 /* 10 us interval */
509 sdb_store_host("host", 10);
510 sdb_store_host("host", 20);
511 sdb_store_host("host", 30);
512 sdb_store_host("host", 40);
514 host = sdb_store_get_host("host");
515 fail_unless(host != NULL,
516 "INTERNAL ERROR: store doesn't have host after adding it");
518 fail_unless(host->interval == 10,
519 "sdb_store_host() did not calculate interval correctly: "
520 "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10);
522 /* multiple updates for the same timestamp don't modify the interval */
523 sdb_store_host("host", 40);
524 sdb_store_host("host", 40);
525 sdb_store_host("host", 40);
526 sdb_store_host("host", 40);
528 fail_unless(host->interval == 10,
529 "sdb_store_host() changed interval when doing multiple updates "
530 "using the same timestamp; got: %"PRIsdbTIME"; "
531 "expected: %"PRIsdbTIME, host->interval, 10);
533 /* multiple updates using an timestamp don't modify the interval */
534 sdb_store_host("host", 20);
535 sdb_store_host("host", 20);
536 sdb_store_host("host", 20);
537 sdb_store_host("host", 20);
539 fail_unless(host->interval == 10,
540 "sdb_store_host() changed interval when doing multiple updates "
541 "using an old timestamp; got: %"PRIsdbTIME"; expected: %"PRIsdbTIME,
542 host->interval, 10);
544 /* new interval: 20 us */
545 sdb_store_host("host", 60);
546 fail_unless(host->interval == 11,
547 "sdb_store_host() did not calculate interval correctly: "
548 "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
550 /* new interval: 40 us */
551 sdb_store_host("host", 100);
552 fail_unless(host->interval == 13,
553 "sdb_store_host() did not calculate interval correctly: "
554 "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
556 sdb_object_deref(SDB_OBJ(host));
557 }
558 END_TEST
560 static int
561 scan_count(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data)
562 {
563 intptr_t *i = user_data;
565 if (! sdb_store_matcher_matches(filter, obj, NULL))
566 return 0;
568 fail_unless(obj != NULL,
569 "sdb_store_scan callback received NULL obj; expected: "
570 "<store base obj>");
571 fail_unless(i != NULL,
572 "sdb_store_scan callback received NULL user_data; "
573 "expected: <pointer to data>");
575 ++(*i);
576 return 0;
577 } /* scan_count */
579 static int
580 scan_error(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data)
581 {
582 intptr_t *i = user_data;
584 if (! sdb_store_matcher_matches(filter, obj, NULL))
585 return 0;
587 fail_unless(obj != NULL,
588 "sdb_store_scan callback received NULL obj; expected: "
589 "<store base obj>");
590 fail_unless(i != NULL,
591 "sdb_store_scan callback received NULL user_data; "
592 "expected: <pointer to data>");
594 ++(*i);
595 return -1;
596 } /* scan_error */
598 START_TEST(test_scan)
599 {
600 intptr_t i = 0;
601 int check;
603 /* empty store */
604 check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL,
605 scan_count, &i);
606 fail_unless(check == -1,
607 "sdb_store_scan(HOST), empty store = %d; expected: -1", check);
608 fail_unless(i == 0,
609 "sdb_store_scan(HOST) called callback %d times; "
610 "expected: 0", (int)i);
612 populate();
614 check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL,
615 scan_count, &i);
616 fail_unless(check == 0,
617 "sdb_store_scan(HOST) = %d; expected: 0", check);
618 fail_unless(i == 2,
619 "sdb_store_scan(HOST) called callback %d times; "
620 "expected: 1", (int)i);
622 i = 0;
623 check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL,
624 scan_error, &i);
625 fail_unless(check == -1,
626 "sdb_store_scan(HOST), error callback = %d; expected: -1", check);
627 fail_unless(i == 1,
628 "sdb_store_scan(HOST) called callback %d times "
629 "(callback returned error); expected: 1", (int)i);
631 i = 0;
632 check = sdb_store_scan(SDB_SERVICE, /* m, filter = */ NULL, NULL,
633 scan_count, &i);
634 fail_unless(check == 0,
635 "sdb_store_scan(SERVICE) = %d; expected: 0", check);
636 fail_unless(i == 2,
637 "sdb_store_scan(SERVICE) called callback %d times; "
638 "expected: 2", (int)i);
640 i = 0;
641 check = sdb_store_scan(SDB_METRIC, /* m, filter = */ NULL, NULL,
642 scan_count, &i);
643 fail_unless(check == 0,
644 "sdb_store_scan(METRIC) = %d; expected: 0", check);
645 fail_unless(i == 3,
646 "sdb_store_scan(METRIC) called callback %d times; "
647 "expected: 3", (int)i);
648 }
649 END_TEST
651 Suite *
652 core_store_suite(void)
653 {
654 Suite *s = suite_create("core::store");
655 TCase *tc;
657 tc = tcase_create("core");
658 tcase_add_test(tc, test_store_host);
659 tcase_add_test(tc, test_store_get_host);
660 tcase_add_test(tc, test_store_attr);
661 tcase_add_test(tc, test_store_metric);
662 tcase_add_test(tc, test_store_metric_attr);
663 tcase_add_test(tc, test_store_service);
664 tcase_add_test(tc, test_store_service_attr);
665 tcase_add_test(tc, test_get_field);
666 tcase_add_test(tc, test_interval);
667 tcase_add_test(tc, test_scan);
668 tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);
669 suite_add_tcase(s, tc);
671 return s;
672 } /* core_store_suite */
674 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */