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_service("h2", "s1", 1);
57 sdb_store_service("h2", "s2", 2);
59 datum.type = SDB_TYPE_INTEGER;
60 datum.data.integer = 123;
61 sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
62 datum.data.integer = 4711;
63 sdb_store_service_attr("h2", "s2", "k2", &datum, 1);
65 /* don't overwrite k1 */
66 datum.data.integer = 666;
67 sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
68 } /* populate */
70 START_TEST(test_store_host)
71 {
72 struct {
73 const char *name;
74 sdb_time_t last_update;
75 int expected;
76 } golden_data[] = {
77 { "a", 1, 0 },
78 { "a", 2, 0 },
79 { "a", 1, 1 },
80 { "b", 1, 0 },
81 { "b", 1, 1 },
82 { "A", 1, 1 }, /* case-insensitive */
83 { "A", 3, 0 },
84 };
86 struct {
87 const char *name;
88 _Bool has;
89 } golden_hosts[] = {
90 { "a", 1 == 1 },
91 { "b", 1 == 1 },
92 { "c", 0 == 1 },
93 { "A", 1 == 1 },
94 };
96 size_t i;
98 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
99 int status;
101 status = sdb_store_host(golden_data[i].name,
102 golden_data[i].last_update);
103 fail_unless(status == golden_data[i].expected,
104 "sdb_store_host(%s, %d) = %d; expected: %d",
105 golden_data[i].name, (int)golden_data[i].last_update,
106 status, golden_data[i].expected);
107 }
109 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
110 _Bool has;
112 has = sdb_store_has_host(golden_hosts[i].name);
113 fail_unless(has == golden_hosts[i].has,
114 "sdb_store_has_host(%s) = %d; expected: %d",
115 golden_hosts[i].name, has, golden_hosts[i].has);
116 }
117 }
118 END_TEST
120 START_TEST(test_store_get_host)
121 {
122 char *golden_hosts[] = { "a", "b", "c" };
123 char *unknown_hosts[] = { "x", "y", "z" };
124 size_t i;
126 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
127 int status = sdb_store_host(golden_hosts[i], 1);
128 fail_unless(status >= 0,
129 "sdb_store_host(%s) = %d; expected: >=0",
130 golden_hosts[i], status);
131 }
133 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
134 sdb_store_obj_t *sobj1, *sobj2;
135 int ref_cnt;
137 fail_unless(sdb_store_has_host(golden_hosts[i]),
138 "sdb_store_has_host(%s) = FALSE; expected: TRUE",
139 golden_hosts[i]);
141 sobj1 = sdb_store_get_host(golden_hosts[i]);
142 fail_unless(sobj1 != NULL,
143 "sdb_store_get_host(%s) = NULL; expected: <host>",
144 golden_hosts[i]);
145 ref_cnt = SDB_OBJ(sobj1)->ref_cnt;
147 fail_unless(ref_cnt > 1,
148 "sdb_store_get_host(%s) did not increment ref count: "
149 "got: %d; expected: >1", golden_hosts[i], ref_cnt);
151 sobj2 = sdb_store_get_host(golden_hosts[i]);
152 fail_unless(sobj2 != NULL,
153 "sdb_store_get_host(%s) = NULL; expected: <host>",
154 golden_hosts[i]);
156 fail_unless(sobj1 == sobj2,
157 "sdb_store_get_host(%s) returned different objects "
158 "in successive calls", golden_hosts[i]);
159 fail_unless(SDB_OBJ(sobj2)->ref_cnt == ref_cnt + 1,
160 "sdb_store_get_hosts(%s) did not increment ref count "
161 "(first call: %d; second call: %d)",
162 golden_hosts[i], ref_cnt, SDB_OBJ(sobj2)->ref_cnt);
164 sdb_object_deref(SDB_OBJ(sobj1));
165 sdb_object_deref(SDB_OBJ(sobj2));
166 }
167 for (i = 0; i < SDB_STATIC_ARRAY_LEN(unknown_hosts); ++i) {
168 sdb_store_obj_t *sobj;
170 fail_unless(!sdb_store_has_host(unknown_hosts[i]),
171 "sdb_store_has_host(%s) = TRUE; expected: FALSE",
172 unknown_hosts[i]);
174 sobj = sdb_store_get_host(unknown_hosts[i]);
175 fail_unless(!sobj, "sdb_store_get_host(%s) = <host:%s>; expected: NULL",
176 unknown_hosts[i], sobj ? SDB_OBJ(sobj)->name : "NULL");
177 }
178 }
179 END_TEST
181 START_TEST(test_store_attr)
182 {
183 struct {
184 const char *host;
185 const char *key;
186 char *value;
187 sdb_time_t last_update;
188 int expected;
189 } golden_data[] = {
190 { "k", "k", "v", 1, -1 },
191 { "k", "k", "v", 1, -1 }, /* retry to ensure the host is not created */
192 { "l", "k1", "v1", 1, 0 },
193 { "l", "k1", "v2", 2, 0 },
194 { "l", "k1", "v3", 2, 1 },
195 { "l", "k2", "v1", 1, 0 },
196 { "m", "k", "v1", 1, 0 },
197 { "m", "k", "v2", 1, 1 },
198 };
200 size_t i;
202 sdb_store_host("l", 1);
203 sdb_store_host("m", 1);
204 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
205 sdb_data_t datum;
206 int status;
208 /* XXX: test other types as well */
209 datum.type = SDB_TYPE_STRING;
210 datum.data.string = golden_data[i].value;
212 status = sdb_store_attribute(golden_data[i].host,
213 golden_data[i].key, &datum,
214 golden_data[i].last_update);
215 fail_unless(status == golden_data[i].expected,
216 "sdb_store_attribute(%s, %s, %s, %d) = %d; expected: %d",
217 golden_data[i].host, golden_data[i].key, golden_data[i].value,
218 golden_data[i].last_update, status, golden_data[i].expected);
219 }
220 }
221 END_TEST
223 START_TEST(test_store_service)
224 {
225 struct {
226 const char *host;
227 const char *svc;
228 sdb_time_t last_update;
229 int expected;
230 } golden_data[] = {
231 { "k", "s", 1, -1 },
232 { "k", "s", 1, -1 }, /* retry to ensure the host is not created */
233 { "l", "s1", 1, 0 },
234 { "l", "s1", 2, 0 },
235 { "l", "s1", 2, 1 },
236 { "l", "s2", 1, 0 },
237 { "m", "s", 1, 0 },
238 { "m", "s", 1, 1 },
239 };
241 size_t i;
243 sdb_store_host("m", 1);
244 sdb_store_host("l", 1);
245 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
246 int status;
248 status = sdb_store_service(golden_data[i].host,
249 golden_data[i].svc, golden_data[i].last_update);
250 fail_unless(status == golden_data[i].expected,
251 "sdb_store_service(%s, %s, %d) = %d; expected: %d",
252 golden_data[i].host, golden_data[i].svc,
253 golden_data[i].last_update, status, golden_data[i].expected);
254 }
255 }
256 END_TEST
258 START_TEST(test_store_service_attr)
259 {
260 struct {
261 const char *host;
262 const char *svc;
263 const char *attr;
264 const sdb_data_t value;
265 sdb_time_t last_update;
266 int expected;
267 } golden_data[] = {
268 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
269 /* retry, it should still fail */
270 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
271 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
272 /* retry, it should still fail */
273 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
274 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
275 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
276 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 },
277 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
278 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
279 { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
280 { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
281 };
283 size_t i;
285 sdb_store_host("m", 1);
286 sdb_store_host("l", 1);
287 sdb_store_service("m", "s1", 1);
288 sdb_store_service("l", "s1", 1);
289 sdb_store_service("l", "s2", 1);
291 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
292 int status;
294 status = sdb_store_service_attr(golden_data[i].host,
295 golden_data[i].svc, golden_data[i].attr,
296 &golden_data[i].value, golden_data[i].last_update);
297 fail_unless(status == golden_data[i].expected,
298 "sdb_store_service_attr(%s, %s, %s, %d, %d) = %d; "
299 "expected: %d", golden_data[i].host, golden_data[i].svc,
300 golden_data[i].attr, golden_data[i].value.data.integer,
301 golden_data[i].last_update, status, golden_data[i].expected);
302 }
303 }
304 END_TEST
306 static void
307 verify_json_output(sdb_strbuf_t *buf, const char *expected, int flags)
308 {
309 int pos;
310 size_t len1, len2;
311 size_t i;
313 len1 = strlen(sdb_strbuf_string(buf));
314 len2 = strlen(expected);
316 pos = -1;
317 if (len1 != len2)
318 pos = (int)(len1 <= len2 ? len1 : len2);
320 for (i = 0; i < (len1 <= len2 ? len1 : len2); ++i) {
321 if (sdb_strbuf_string(buf)[i] != expected[i]) {
322 pos = (int)i;
323 break;
324 }
325 }
327 fail_unless(pos == -1,
328 "sdb_store_tojson(%x) returned unexpected result\n"
329 " got: %s\n %*s\n expected: %s",
330 flags, sdb_strbuf_string(buf), pos + 1, "^", expected);
331 } /* verify_json_output */
333 START_TEST(test_store_tojson)
334 {
335 sdb_strbuf_t *buf;
336 size_t i;
338 struct {
339 struct {
340 sdb_store_matcher_t *(*m)(sdb_store_cond_t *);
341 int field;
342 sdb_data_t value;
343 } filter;
344 int flags;
345 const char *expected;
346 } golden_data[] = {
347 { { NULL, 0, SDB_DATA_INIT }, 0,
348 "{\"hosts\":["
349 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
350 "\"update_interval\": \"0s\", \"backends\": [], "
351 "\"attributes\": ["
352 "{\"name\": \"k1\", \"value\": \"v1\", "
353 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
354 "\"update_interval\": \"0s\", \"backends\": []},"
355 "{\"name\": \"k2\", \"value\": \"v2\", "
356 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
357 "\"update_interval\": \"0s\", \"backends\": []},"
358 "{\"name\": \"k3\", \"value\": \"v3\", "
359 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
360 "\"update_interval\": \"0s\", \"backends\": []}"
361 "], "
362 "\"services\": []},"
363 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
364 "\"update_interval\": \"0s\", \"backends\": [], "
365 "\"attributes\": [], "
366 "\"services\": ["
367 "{\"name\": \"s1\", "
368 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
369 "\"update_interval\": \"0s\", \"backends\": [], "
370 "\"attributes\": []},"
371 "{\"name\": \"s2\", "
372 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
373 "\"update_interval\": \"0s\", \"backends\": [], "
374 "\"attributes\": ["
375 "{\"name\": \"k1\", \"value\": 123, "
376 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
377 "\"update_interval\": \"0s\", \"backends\": []},"
378 "{\"name\": \"k2\", \"value\": 4711, "
379 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
380 "\"update_interval\": \"0s\", \"backends\": []}"
381 "]}"
382 "]}"
383 "]}" },
384 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_SERVICES,
385 "{\"hosts\":["
386 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
387 "\"update_interval\": \"0s\", \"backends\": [], "
388 "\"attributes\": ["
389 "{\"name\": \"k1\", \"value\": \"v1\", "
390 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
391 "\"update_interval\": \"0s\", \"backends\": []},"
392 "{\"name\": \"k2\", \"value\": \"v2\", "
393 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
394 "\"update_interval\": \"0s\", \"backends\": []},"
395 "{\"name\": \"k3\", \"value\": \"v3\", "
396 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
397 "\"update_interval\": \"0s\", \"backends\": []}"
398 "]},"
399 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
400 "\"update_interval\": \"0s\", \"backends\": [], "
401 "\"attributes\": []}"
402 "]}" },
403 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ATTRIBUTES,
404 "{\"hosts\":["
405 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
406 "\"update_interval\": \"0s\", \"backends\": [], "
407 "\"services\": []},"
408 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
409 "\"update_interval\": \"0s\", \"backends\": [], "
410 "\"services\": ["
411 "{\"name\": \"s1\", "
412 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
413 "\"update_interval\": \"0s\", \"backends\": []},"
414 "{\"name\": \"s2\", "
415 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
416 "\"update_interval\": \"0s\", \"backends\": []}"
417 "]}"
418 "]}" },
419 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_SERVICES | SDB_SKIP_ATTRIBUTES,
420 "{\"hosts\":["
421 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
422 "\"update_interval\": \"0s\", \"backends\": []},"
423 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
424 "\"update_interval\": \"0s\", \"backends\": []}"
425 "]}" },
426 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
427 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
428 "{\"hosts\":["
429 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
430 "\"update_interval\": \"0s\", \"backends\": [], "
431 "\"attributes\": [], "
432 "\"services\": ["
433 "{\"name\": \"s2\", "
434 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
435 "\"update_interval\": \"0s\", \"backends\": [], "
436 "\"attributes\": ["
437 "{\"name\": \"k1\", \"value\": 123, "
438 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
439 "\"update_interval\": \"0s\", \"backends\": []},"
440 "]}"
441 "]}"
442 "]}" },
443 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
444 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
445 "{\"hosts\":["
446 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
447 "\"update_interval\": \"0s\", \"backends\": [], "
448 "\"attributes\": ["
449 "{\"name\": \"k1\", \"value\": \"v1\", "
450 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
451 "\"update_interval\": \"0s\", \"backends\": []},"
452 "], "
453 "\"services\": []}"
454 "]}" },
455 { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
456 { SDB_TYPE_DATETIME, { .datetime = 3 } } }, 0,
457 "{\"hosts\":["
458 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
459 "\"update_interval\": \"0s\", \"backends\": [], "
460 "\"attributes\": [], "
461 "\"services\": []}"
462 "]}" },
463 };
465 buf = sdb_strbuf_create(0);
466 fail_unless(buf != NULL, "INTERNAL ERROR: failed to create string buffer");
467 populate();
469 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
470 sdb_store_matcher_t *filter = NULL;
471 int status;
473 sdb_strbuf_clear(buf);
475 if (golden_data[i].filter.m) {
476 sdb_store_expr_t *expr;
477 sdb_store_cond_t *c = NULL;
479 expr = sdb_store_expr_constvalue(&golden_data[i].filter.value);
480 fail_unless(expr != NULL,
481 "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
482 c = sdb_store_obj_cond(golden_data[i].filter.field, expr);
483 sdb_object_deref(SDB_OBJ(expr));
484 fail_unless(c != NULL,
485 "INTERNAL ERROR: sdb_store_obj_cond() = NULL");
486 filter = golden_data[i].filter.m(c);
487 sdb_object_deref(SDB_OBJ(c));
488 fail_unless(filter != NULL,
489 "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
490 }
492 status = sdb_store_tojson(buf, filter, golden_data[i].flags);
493 fail_unless(status == 0,
494 "sdb_store_tojson(%x) = %d; expected: 0",
495 golden_data[i].flags, status);
497 verify_json_output(buf, golden_data[i].expected, golden_data[i].flags);
498 sdb_object_deref(SDB_OBJ(filter));
499 }
500 sdb_strbuf_destroy(buf);
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 iter_incr(sdb_store_obj_t *obj, void *user_data)
562 {
563 intptr_t *i = user_data;
565 fail_unless(obj != NULL,
566 "sdb_store_iterate callback received NULL obj; expected: "
567 "<store base obj>");
568 fail_unless(i != NULL,
569 "sdb_store_iterate callback received NULL user_data; "
570 "expected: <pointer to data>");
572 ++(*i);
573 return 0;
574 } /* iter_incr */
576 static int
577 iter_error(sdb_store_obj_t *obj, void *user_data)
578 {
579 intptr_t *i = user_data;
581 fail_unless(obj != NULL,
582 "sdb_store_iterate callback received NULL obj; expected: "
583 "<store base obj>");
584 fail_unless(i != NULL,
585 "sdb_store_iterate callback received NULL user_data; "
586 "expected: <pointer to data>");
588 ++(*i);
589 return -1;
590 } /* iter_error */
592 START_TEST(test_iterate)
593 {
594 intptr_t i = 0;
595 int check;
597 /* empty store */
598 check = sdb_store_iterate(iter_incr, &i);
599 fail_unless(check == -1,
600 "sdb_store_iterate(), empty store = %d; expected: -1", check);
601 fail_unless(i == 0,
602 "sdb_store_iterate called callback %d times; expected: 0", (int)i);
604 populate();
606 check = sdb_store_iterate(iter_incr, &i);
607 fail_unless(check == 0,
608 "sdb_store_iterate() = %d; expected: 0", check);
609 fail_unless(i == 2,
610 "sdb_store_iterate called callback %d times; expected: 1", (int)i);
612 i = 0;
613 check = sdb_store_iterate(iter_error, &i);
614 fail_unless(check == -1,
615 "sdb_store_iterate(), error callback = %d; expected: -1", check);
616 fail_unless(i == 1,
617 "sdb_store_iterate called callback %d times "
618 "(callback returned error); expected: 1", (int)i);
619 }
620 END_TEST
622 Suite *
623 core_store_suite(void)
624 {
625 Suite *s = suite_create("core::store");
626 TCase *tc;
628 tc = tcase_create("core");
629 tcase_add_test(tc, test_store_tojson);
630 tcase_add_test(tc, test_store_host);
631 tcase_add_test(tc, test_store_get_host);
632 tcase_add_test(tc, test_store_attr);
633 tcase_add_test(tc, test_store_service);
634 tcase_add_test(tc, test_store_service_attr);
635 tcase_add_test(tc, test_interval);
636 tcase_add_test(tc, test_iterate);
637 tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);
638 suite_add_tcase(s, tc);
640 return s;
641 } /* core_store_suite */
643 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */