Code

store: Added core support for “metrics” objects.
[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 #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         }
118 END_TEST
120 START_TEST(test_store_get_host)
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         }
179 END_TEST
181 START_TEST(test_store_attr)
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         }
221 END_TEST
223 START_TEST(test_store_service)
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         }
256 END_TEST
258 START_TEST(test_store_service_attr)
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         }
304 END_TEST
306 static void
307 verify_json_output(sdb_strbuf_t *buf, const char *expected, int flags)
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)
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                                         "\"metrics\": [], "
363                                         "\"services\": []},"
364                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
365                                         "\"update_interval\": \"0s\", \"backends\": [], "
366                                         "\"attributes\": [], "
367                                         "\"metrics\": [], "
368                                         "\"services\": ["
369                                                 "{\"name\": \"s1\", "
370                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
371                                                         "\"update_interval\": \"0s\", \"backends\": [], "
372                                                         "\"attributes\": []},"
373                                                 "{\"name\": \"s2\", "
374                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
375                                                         "\"update_interval\": \"0s\", \"backends\": [], "
376                                                         "\"attributes\": ["
377                                                                 "{\"name\": \"k1\", \"value\": 123, "
378                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
379                                                                         "\"update_interval\": \"0s\", \"backends\": []},"
380                                                                 "{\"name\": \"k2\", \"value\": 4711, "
381                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
382                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
383                                                         "]}"
384                                         "]}"
385                         "]}" },
386                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_SERVICES,
387                         "{\"hosts\":["
388                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
389                                         "\"update_interval\": \"0s\", \"backends\": [], "
390                                         "\"attributes\": ["
391                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
392                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
393                                                         "\"update_interval\": \"0s\", \"backends\": []},"
394                                                 "{\"name\": \"k2\", \"value\": \"v2\", "
395                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
396                                                         "\"update_interval\": \"0s\", \"backends\": []},"
397                                                 "{\"name\": \"k3\", \"value\": \"v3\", "
398                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
399                                                         "\"update_interval\": \"0s\", \"backends\": []}"
400                                         "], "
401                                         "\"metrics\": []},"
402                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
403                                         "\"update_interval\": \"0s\", \"backends\": [], "
404                                         "\"attributes\": [], "
405                                         "\"metrics\": []}"
406                         "]}" },
407                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_METRICS,
408                         "{\"hosts\":["
409                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
410                                         "\"update_interval\": \"0s\", \"backends\": [], "
411                                         "\"attributes\": ["
412                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
413                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
414                                                         "\"update_interval\": \"0s\", \"backends\": []},"
415                                                 "{\"name\": \"k2\", \"value\": \"v2\", "
416                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
417                                                         "\"update_interval\": \"0s\", \"backends\": []},"
418                                                 "{\"name\": \"k3\", \"value\": \"v3\", "
419                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
420                                                         "\"update_interval\": \"0s\", \"backends\": []}"
421                                         "], "
422                                         "\"services\": []},"
423                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
424                                         "\"update_interval\": \"0s\", \"backends\": [], "
425                                         "\"attributes\": [], "
426                                         "\"services\": ["
427                                                 "{\"name\": \"s1\", "
428                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
429                                                         "\"update_interval\": \"0s\", \"backends\": [], "
430                                                         "\"attributes\": []},"
431                                                 "{\"name\": \"s2\", "
432                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
433                                                         "\"update_interval\": \"0s\", \"backends\": [], "
434                                                         "\"attributes\": ["
435                                                                 "{\"name\": \"k1\", \"value\": 123, "
436                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
437                                                                         "\"update_interval\": \"0s\", \"backends\": []},"
438                                                                 "{\"name\": \"k2\", \"value\": 4711, "
439                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
440                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
441                                                         "]}"
442                                         "]}"
443                         "]}" },
444                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ATTRIBUTES,
445                         "{\"hosts\":["
446                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
447                                         "\"update_interval\": \"0s\", \"backends\": [], "
448                                         "\"metrics\": [], "
449                                         "\"services\": []},"
450                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
451                                         "\"update_interval\": \"0s\", \"backends\": [], "
452                                         "\"metrics\": [], "
453                                         "\"services\": ["
454                                                 "{\"name\": \"s1\", "
455                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
456                                                         "\"update_interval\": \"0s\", \"backends\": []},"
457                                                 "{\"name\": \"s2\", "
458                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
459                                                         "\"update_interval\": \"0s\", \"backends\": []}"
460                                         "]}"
461                         "]}" },
462                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ALL,
463                         "{\"hosts\":["
464                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
465                                         "\"update_interval\": \"0s\", \"backends\": []},"
466                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
467                                         "\"update_interval\": \"0s\", \"backends\": []}"
468                         "]}" },
469                 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
470                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
471                         "{\"hosts\":["
472                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
473                                         "\"update_interval\": \"0s\", \"backends\": [], "
474                                         "\"attributes\": [], "
475                                         "\"metrics\": [], "
476                                         "\"services\": ["
477                                                 "{\"name\": \"s2\", "
478                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
479                                                         "\"update_interval\": \"0s\", \"backends\": [], "
480                                                         "\"attributes\": ["
481                                                                 "{\"name\": \"k1\", \"value\": 123, "
482                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
483                                                                         "\"update_interval\": \"0s\", \"backends\": []},"
484                                                         "]}"
485                                         "]}"
486                         "]}" },
487                 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
488                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
489                         "{\"hosts\":["
490                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
491                                         "\"update_interval\": \"0s\", \"backends\": [], "
492                                         "\"attributes\": ["
493                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
494                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
495                                                         "\"update_interval\": \"0s\", \"backends\": []},"
496                                         "], "
497                                         "\"metrics\": [], "
498                                         "\"services\": []}"
499                         "]}" },
500                 { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
501                                 { SDB_TYPE_DATETIME, { .datetime = 3 } } }, 0,
502                         "{\"hosts\":["
503                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
504                                         "\"update_interval\": \"0s\", \"backends\": [], "
505                                         "\"attributes\": [], "
506                                         "\"metrics\": [], "
507                                         "\"services\": []}"
508                         "]}" },
509         };
511         buf = sdb_strbuf_create(0);
512         fail_unless(buf != NULL, "INTERNAL ERROR: failed to create string buffer");
513         populate();
515         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
516                 sdb_store_matcher_t *filter = NULL;
517                 char filter_str[1024];
518                 int status;
520                 sdb_strbuf_clear(buf);
522                 if (golden_data[i].filter.m) {
523                         sdb_store_expr_t *expr;
524                         sdb_store_cond_t *c = NULL;
526                         expr = sdb_store_expr_constvalue(&golden_data[i].filter.value);
527                         fail_unless(expr != NULL,
528                                         "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
529                         c = sdb_store_obj_cond(golden_data[i].filter.field, expr);
530                         sdb_object_deref(SDB_OBJ(expr));
531                         fail_unless(c != NULL,
532                                         "INTERNAL ERROR: sdb_store_obj_cond() = NULL");
533                         filter = golden_data[i].filter.m(c);
534                         sdb_object_deref(SDB_OBJ(c));
535                         fail_unless(filter != NULL,
536                                         "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
537                 }
539                 if (sdb_store_matcher_tostring(filter, filter_str, sizeof(filter_str)))
540                         snprintf(filter_str, sizeof(filter_str), "ERR");
542                 status = sdb_store_tojson(buf, filter, golden_data[i].flags);
543                 fail_unless(status == 0,
544                                 "sdb_store_tojson(<buf>, %s, %x) = %d; expected: 0",
545                                 filter_str, golden_data[i].flags, status);
547                 verify_json_output(buf, golden_data[i].expected, golden_data[i].flags);
548                 sdb_object_deref(SDB_OBJ(filter));
549         }
550         sdb_strbuf_destroy(buf);
552 END_TEST
554 START_TEST(test_get_field)
556         sdb_store_obj_t *host;
557         sdb_data_t value = SDB_DATA_INIT;
558         int check;
560         sdb_store_host("host", 10);
561         sdb_store_host("host", 20);
563         host = sdb_store_get_host("host");
564         fail_unless(host != NULL,
565                         "INTERNAL ERROR: store doesn't have host after adding it");
567         check = sdb_store_get_field(NULL, 0, NULL);
568         fail_unless(check < 0,
569                         "sdb_store_get_field(NULL, 0, NULL) = %d; expected: <0");
570         check = sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, NULL);
571         fail_unless(check < 0,
572                         "sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, NULL) = %d; "
573                         "expected: <0");
574         check = sdb_store_get_field(host, SDB_FIELD_LAST_UPDATE, NULL);
575         fail_unless(check < 0,
576                         "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, NULL) = %d; "
577                         "expected: <0");
578         check = sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, &value);
579         fail_unless(check < 0,
580                         "sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, <value>) = %d; "
581                         "expected: <0");
583         check = sdb_store_get_field(host, SDB_FIELD_LAST_UPDATE, &value);
584         fail_unless(check == 0,
585                         "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, <value>) = "
586                         "%d; expected: 0");
587         fail_unless((value.type == SDB_TYPE_DATETIME)
588                         && (value.data.datetime == 20),
589                         "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, <value>) "
590                         "returned value {%d, %lu}; expected {%d, 20}",
591                         value.type, value.data.datetime, SDB_TYPE_DATETIME);
593         check = sdb_store_get_field(host, SDB_FIELD_AGE, &value);
594         fail_unless(check == 0,
595                         "sdb_store_get_field(<host>, SDB_FIELD_AGE, <value>) = "
596                         "%d; expected: 0");
597         /* let's assume we're at least in year 1980 ;-) */
598         fail_unless((value.type == SDB_TYPE_DATETIME)
599                         && (value.data.datetime > 10L * SDB_INTERVAL_YEAR),
600                         "sdb_store_get_field(<host>, SDB_FIELD_AGE, <value>) "
601                         "returned value {%d, %lu}; expected {%d, >%lu}",
602                         value.type, value.data.datetime,
603                         SDB_TYPE_DATETIME, 10L * SDB_INTERVAL_YEAR);
605         check = sdb_store_get_field(host, SDB_FIELD_INTERVAL, &value);
606         fail_unless(check == 0,
607                         "sdb_store_get_field(<host>, SDB_FIELD_INTERVAL, <value>) = "
608                         "%d; expected: 0");
609         fail_unless((value.type == SDB_TYPE_DATETIME)
610                         && (value.data.datetime == 10),
611                         "sdb_store_get_field(<host>, SDB_FIELD_INTERVAL, <value>) "
612                         "returned value {%d, %lu}; expected {%d, 10}",
613                         value.type, value.data.datetime, SDB_TYPE_DATETIME);
615 END_TEST
617 START_TEST(test_interval)
619         sdb_store_obj_t *host;
621         /* 10 us interval */
622         sdb_store_host("host", 10);
623         sdb_store_host("host", 20);
624         sdb_store_host("host", 30);
625         sdb_store_host("host", 40);
627         host = sdb_store_get_host("host");
628         fail_unless(host != NULL,
629                         "INTERNAL ERROR: store doesn't have host after adding it");
631         fail_unless(host->interval == 10,
632                         "sdb_store_host() did not calculate interval correctly: "
633                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10);
635         /* multiple updates for the same timestamp don't modify the interval */
636         sdb_store_host("host", 40);
637         sdb_store_host("host", 40);
638         sdb_store_host("host", 40);
639         sdb_store_host("host", 40);
641         fail_unless(host->interval == 10,
642                         "sdb_store_host() changed interval when doing multiple updates "
643                         "using the same timestamp; got: %"PRIsdbTIME"; "
644                         "expected: %"PRIsdbTIME, host->interval, 10);
646         /* multiple updates using an timestamp don't modify the interval */
647         sdb_store_host("host", 20);
648         sdb_store_host("host", 20);
649         sdb_store_host("host", 20);
650         sdb_store_host("host", 20);
652         fail_unless(host->interval == 10,
653                         "sdb_store_host() changed interval when doing multiple updates "
654                         "using an old timestamp; got: %"PRIsdbTIME"; expected: %"PRIsdbTIME,
655                         host->interval, 10);
657         /* new interval: 20 us */
658         sdb_store_host("host", 60);
659         fail_unless(host->interval == 11,
660                         "sdb_store_host() did not calculate interval correctly: "
661                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
663         /* new interval: 40 us */
664         sdb_store_host("host", 100);
665         fail_unless(host->interval == 13,
666                         "sdb_store_host() did not calculate interval correctly: "
667                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
669         sdb_object_deref(SDB_OBJ(host));
671 END_TEST
673 static int
674 iter_incr(sdb_store_obj_t *obj, void *user_data)
676         intptr_t *i = user_data;
678         fail_unless(obj != NULL,
679                         "sdb_store_iterate callback received NULL obj; expected: "
680                         "<store base obj>");
681         fail_unless(i != NULL,
682                         "sdb_store_iterate callback received NULL user_data; "
683                         "expected: <pointer to data>");
685         ++(*i);
686         return 0;
687 } /* iter_incr */
689 static int
690 iter_error(sdb_store_obj_t *obj, void *user_data)
692         intptr_t *i = user_data;
694         fail_unless(obj != NULL,
695                         "sdb_store_iterate callback received NULL obj; expected: "
696                         "<store base obj>");
697         fail_unless(i != NULL,
698                         "sdb_store_iterate callback received NULL user_data; "
699                         "expected: <pointer to data>");
701         ++(*i);
702         return -1;
703 } /* iter_error */
705 START_TEST(test_iterate)
707         intptr_t i = 0;
708         int check;
710         /* empty store */
711         check = sdb_store_iterate(iter_incr, &i);
712         fail_unless(check == -1,
713                         "sdb_store_iterate(), empty store = %d; expected: -1", check);
714         fail_unless(i == 0,
715                         "sdb_store_iterate called callback %d times; expected: 0", (int)i);
717         populate();
719         check = sdb_store_iterate(iter_incr, &i);
720         fail_unless(check == 0,
721                         "sdb_store_iterate() = %d; expected: 0", check);
722         fail_unless(i == 2,
723                         "sdb_store_iterate called callback %d times; expected: 1", (int)i);
725         i = 0;
726         check = sdb_store_iterate(iter_error, &i);
727         fail_unless(check == -1,
728                         "sdb_store_iterate(), error callback = %d; expected: -1", check);
729         fail_unless(i == 1,
730                         "sdb_store_iterate called callback %d times "
731                         "(callback returned error); expected: 1", (int)i);
733 END_TEST
735 Suite *
736 core_store_suite(void)
738         Suite *s = suite_create("core::store");
739         TCase *tc;
741         tc = tcase_create("core");
742         tcase_add_test(tc, test_store_tojson);
743         tcase_add_test(tc, test_store_host);
744         tcase_add_test(tc, test_store_get_host);
745         tcase_add_test(tc, test_store_attr);
746         tcase_add_test(tc, test_store_service);
747         tcase_add_test(tc, test_store_service_attr);
748         tcase_add_test(tc, test_get_field);
749         tcase_add_test(tc, test_interval);
750         tcase_add_test(tc, test_iterate);
751         tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);
752         suite_add_tcase(s, tc);
754         return s;
755 } /* core_store_suite */
757 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */