Code

store: Added support for storing metric 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_metric("h1", "m1", 2);
57         sdb_store_metric("h1", "m2", 1);
59         sdb_store_service("h2", "s1", 1);
60         sdb_store_service("h2", "s2", 2);
62         datum.type = SDB_TYPE_INTEGER;
63         datum.data.integer = 42;
64         sdb_store_metric_attr("h1", "m1", "k3", &datum, 2);
66         datum.data.integer = 123;
67         sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
68         datum.data.integer = 4711;
69         sdb_store_service_attr("h2", "s2", "k2", &datum, 1);
71         /* don't overwrite k1 */
72         datum.data.integer = 666;
73         sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
74 } /* populate */
76 START_TEST(test_store_host)
77 {
78         struct {
79                 const char *name;
80                 sdb_time_t  last_update;
81                 int         expected;
82         } golden_data[] = {
83                 { "a", 1, 0 },
84                 { "a", 2, 0 },
85                 { "a", 1, 1 },
86                 { "b", 1, 0 },
87                 { "b", 1, 1 },
88                 { "A", 1, 1 }, /* case-insensitive */
89                 { "A", 3, 0 },
90         };
92         struct {
93                 const char *name;
94                 _Bool       has;
95         } golden_hosts[] = {
96                 { "a", 1 == 1 },
97                 { "b", 1 == 1 },
98                 { "c", 0 == 1 },
99                 { "A", 1 == 1 },
100         };
102         size_t i;
104         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
105                 int status;
107                 status = sdb_store_host(golden_data[i].name,
108                                 golden_data[i].last_update);
109                 fail_unless(status == golden_data[i].expected,
110                                 "sdb_store_host(%s, %d) = %d; expected: %d",
111                                 golden_data[i].name, (int)golden_data[i].last_update,
112                                 status, golden_data[i].expected);
113         }
115         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
116                 _Bool has;
118                 has = sdb_store_has_host(golden_hosts[i].name);
119                 fail_unless(has == golden_hosts[i].has,
120                                 "sdb_store_has_host(%s) = %d; expected: %d",
121                                 golden_hosts[i].name, has, golden_hosts[i].has);
122         }
124 END_TEST
126 START_TEST(test_store_get_host)
128         char *golden_hosts[] = { "a", "b", "c" };
129         char *unknown_hosts[] = { "x", "y", "z" };
130         size_t i;
132         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
133                 int status = sdb_store_host(golden_hosts[i], 1);
134                 fail_unless(status >= 0,
135                                 "sdb_store_host(%s) = %d; expected: >=0",
136                                 golden_hosts[i], status);
137         }
139         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) {
140                 sdb_store_obj_t *sobj1, *sobj2;
141                 int ref_cnt;
143                 fail_unless(sdb_store_has_host(golden_hosts[i]),
144                                 "sdb_store_has_host(%s) = FALSE; expected: TRUE",
145                                 golden_hosts[i]);
147                 sobj1 = sdb_store_get_host(golden_hosts[i]);
148                 fail_unless(sobj1 != NULL,
149                                 "sdb_store_get_host(%s) = NULL; expected: <host>",
150                                 golden_hosts[i]);
151                 ref_cnt = SDB_OBJ(sobj1)->ref_cnt;
153                 fail_unless(ref_cnt > 1,
154                                 "sdb_store_get_host(%s) did not increment ref count: "
155                                 "got: %d; expected: >1", golden_hosts[i], ref_cnt);
157                 sobj2 = sdb_store_get_host(golden_hosts[i]);
158                 fail_unless(sobj2 != NULL,
159                                 "sdb_store_get_host(%s) = NULL; expected: <host>",
160                                 golden_hosts[i]);
162                 fail_unless(sobj1 == sobj2,
163                                 "sdb_store_get_host(%s) returned different objects "
164                                 "in successive calls", golden_hosts[i]);
165                 fail_unless(SDB_OBJ(sobj2)->ref_cnt == ref_cnt + 1,
166                                 "sdb_store_get_hosts(%s) did not increment ref count "
167                                 "(first call: %d; second call: %d)",
168                                 golden_hosts[i], ref_cnt, SDB_OBJ(sobj2)->ref_cnt);
170                 sdb_object_deref(SDB_OBJ(sobj1));
171                 sdb_object_deref(SDB_OBJ(sobj2));
172         }
173         for (i = 0; i < SDB_STATIC_ARRAY_LEN(unknown_hosts); ++i) {
174                 sdb_store_obj_t *sobj;
176                 fail_unless(!sdb_store_has_host(unknown_hosts[i]),
177                                 "sdb_store_has_host(%s) = TRUE; expected: FALSE",
178                                 unknown_hosts[i]);
180                 sobj = sdb_store_get_host(unknown_hosts[i]);
181                 fail_unless(!sobj, "sdb_store_get_host(%s) = <host:%s>; expected: NULL",
182                                 unknown_hosts[i], sobj ? SDB_OBJ(sobj)->name : "NULL");
183         }
185 END_TEST
187 START_TEST(test_store_attr)
189         struct {
190                 const char *host;
191                 const char *key;
192                 char       *value;
193                 sdb_time_t  last_update;
194                 int         expected;
195         } golden_data[] = {
196                 { "k", "k",  "v",  1, -1 },
197                 { "k", "k",  "v",  1, -1 }, /* retry to ensure the host is not created */
198                 { "l", "k1", "v1", 1,  0 },
199                 { "l", "k1", "v2", 2,  0 },
200                 { "l", "k1", "v3", 2,  1 },
201                 { "l", "k2", "v1", 1,  0 },
202                 { "m", "k",  "v1", 1,  0 },
203                 { "m", "k",  "v2", 1,  1 },
204         };
206         size_t i;
208         sdb_store_host("l", 1);
209         sdb_store_host("m", 1);
210         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
211                 sdb_data_t datum;
212                 int status;
214                 /* XXX: test other types as well */
215                 datum.type = SDB_TYPE_STRING;
216                 datum.data.string = golden_data[i].value;
218                 status = sdb_store_attribute(golden_data[i].host,
219                                 golden_data[i].key, &datum,
220                                 golden_data[i].last_update);
221                 fail_unless(status == golden_data[i].expected,
222                                 "sdb_store_attribute(%s, %s, %s, %d) = %d; expected: %d",
223                                 golden_data[i].host, golden_data[i].key, golden_data[i].value,
224                                 golden_data[i].last_update, status, golden_data[i].expected);
225         }
227 END_TEST
229 START_TEST(test_store_metric)
231         struct {
232                 const char *host;
233                 const char *metric;
234                 sdb_time_t  last_update;
235                 int         expected;
236         } golden_data[] = {
237                 { "k", "m",  1, -1 },
238                 { "k", "m",  1, -1 }, /* retry to ensure the host is not created */
239                 { "l", "m1", 1,  0 },
240                 { "l", "m1", 2,  0 },
241                 { "l", "m1", 2,  1 },
242                 { "l", "m2", 1,  0 },
243                 { "m", "m",  1,  0 },
244                 { "m", "m",  1,  1 },
245         };
247         size_t i;
249         sdb_store_host("m", 1);
250         sdb_store_host("l", 1);
251         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
252                 int status;
254                 status = sdb_store_metric(golden_data[i].host,
255                                 golden_data[i].metric, golden_data[i].last_update);
256                 fail_unless(status == golden_data[i].expected,
257                                 "sdb_store_metric(%s, %s, %d) = %d; expected: %d",
258                                 golden_data[i].host, golden_data[i].metric,
259                                 golden_data[i].last_update, status, golden_data[i].expected);
260         }
262 END_TEST
264 START_TEST(test_store_metric_attr)
266         struct {
267                 const char *host;
268                 const char *metric;
269                 const char *attr;
270                 const sdb_data_t value;
271                 sdb_time_t  last_update;
272                 int expected;
273         } golden_data[] = {
274                 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
275                 /* retry, it should still fail */
276                 { "k", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
277                 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
278                 /* retry, it should still fail */
279                 { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
280                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
281                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
282                 { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2,  0 },
283                 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
284                 { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
285                 { "l", "m2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
286                 { "m", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
287         };
289         size_t i;
291         sdb_store_host("m", 1);
292         sdb_store_host("l", 1);
293         sdb_store_metric("m", "m1", 1);
294         sdb_store_metric("l", "m1", 1);
295         sdb_store_metric("l", "m2", 1);
297         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
298                 int status;
300                 status = sdb_store_metric_attr(golden_data[i].host,
301                                 golden_data[i].metric, golden_data[i].attr,
302                                 &golden_data[i].value, golden_data[i].last_update);
303                 fail_unless(status == golden_data[i].expected,
304                                 "sdb_store_metric_attr(%s, %s, %s, %d, %d) = %d; "
305                                 "expected: %d", golden_data[i].host, golden_data[i].metric,
306                                 golden_data[i].attr, golden_data[i].value.data.integer,
307                                 golden_data[i].last_update, status, golden_data[i].expected);
308         }
310 END_TEST
312 START_TEST(test_store_service)
314         struct {
315                 const char *host;
316                 const char *svc;
317                 sdb_time_t  last_update;
318                 int         expected;
319         } golden_data[] = {
320                 { "k", "s",  1, -1 },
321                 { "k", "s",  1, -1 }, /* retry to ensure the host is not created */
322                 { "l", "s1", 1,  0 },
323                 { "l", "s1", 2,  0 },
324                 { "l", "s1", 2,  1 },
325                 { "l", "s2", 1,  0 },
326                 { "m", "s",  1,  0 },
327                 { "m", "s",  1,  1 },
328         };
330         size_t i;
332         sdb_store_host("m", 1);
333         sdb_store_host("l", 1);
334         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
335                 int status;
337                 status = sdb_store_service(golden_data[i].host,
338                                 golden_data[i].svc, golden_data[i].last_update);
339                 fail_unless(status == golden_data[i].expected,
340                                 "sdb_store_service(%s, %s, %d) = %d; expected: %d",
341                                 golden_data[i].host, golden_data[i].svc,
342                                 golden_data[i].last_update, status, golden_data[i].expected);
343         }
345 END_TEST
347 START_TEST(test_store_service_attr)
349         struct {
350                 const char *host;
351                 const char *svc;
352                 const char *attr;
353                 const sdb_data_t value;
354                 sdb_time_t  last_update;
355                 int expected;
356         } golden_data[] = {
357                 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
358                 /* retry, it should still fail */
359                 { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
360                 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
361                 /* retry, it should still fail */
362                 { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
363                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
364                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
365                 { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2,  0 },
366                 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
367                 { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
368                 { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
369                 { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
370         };
372         size_t i;
374         sdb_store_host("m", 1);
375         sdb_store_host("l", 1);
376         sdb_store_service("m", "s1", 1);
377         sdb_store_service("l", "s1", 1);
378         sdb_store_service("l", "s2", 1);
380         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
381                 int status;
383                 status = sdb_store_service_attr(golden_data[i].host,
384                                 golden_data[i].svc, golden_data[i].attr,
385                                 &golden_data[i].value, golden_data[i].last_update);
386                 fail_unless(status == golden_data[i].expected,
387                                 "sdb_store_service_attr(%s, %s, %s, %d, %d) = %d; "
388                                 "expected: %d", golden_data[i].host, golden_data[i].svc,
389                                 golden_data[i].attr, golden_data[i].value.data.integer,
390                                 golden_data[i].last_update, status, golden_data[i].expected);
391         }
393 END_TEST
395 static void
396 verify_json_output(sdb_strbuf_t *buf, const char *expected,
397                 const char *filter_str, int flags)
399         int pos;
400         size_t len1, len2;
401         size_t i;
403         len1 = strlen(sdb_strbuf_string(buf));
404         len2 = strlen(expected);
406         pos = -1;
407         if (len1 != len2)
408                 pos = (int)(len1 <= len2 ? len1 : len2);
410         for (i = 0; i < (len1 <= len2 ? len1 : len2); ++i) {
411                 if (sdb_strbuf_string(buf)[i] != expected[i]) {
412                         pos = (int)i;
413                         break;
414                 }
415         }
417         fail_unless(pos == -1,
418                         "sdb_store_tojson(<buf>, %s, %x) returned unexpected result\n"
419                         "         got: %s\n              %*s\n    expected: %s",
420                         filter_str, flags, sdb_strbuf_string(buf), pos + 1, "^",
421                         expected);
422 } /* verify_json_output */
424 START_TEST(test_store_tojson)
426         sdb_strbuf_t *buf;
427         size_t i;
429         struct {
430                 struct {
431                         sdb_store_matcher_t *(*m)(sdb_store_cond_t *);
432                         int field;
433                         sdb_data_t value;
434                 } filter;
435                 int flags;
436                 const char *expected;
437         } golden_data[] = {
438                 { { NULL, 0, SDB_DATA_INIT }, 0,
439                         "{\"hosts\":["
440                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
441                                         "\"update_interval\": \"0s\", \"backends\": [], "
442                                         "\"attributes\": ["
443                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
444                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
445                                                         "\"update_interval\": \"0s\", \"backends\": []},"
446                                                 "{\"name\": \"k2\", \"value\": \"v2\", "
447                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
448                                                         "\"update_interval\": \"0s\", \"backends\": []},"
449                                                 "{\"name\": \"k3\", \"value\": \"v3\", "
450                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
451                                                         "\"update_interval\": \"0s\", \"backends\": []}"
452                                         "], "
453                                         "\"metrics\": ["
454                                                 "{\"name\": \"m1\", "
455                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
456                                                         "\"update_interval\": \"0s\", \"backends\": [], "
457                                                         "\"attributes\": ["
458                                                                 "{\"name\": \"k3\", \"value\": 42, "
459                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
460                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
461                                                         "]},"
462                                                 "{\"name\": \"m2\", "
463                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
464                                                         "\"update_interval\": \"0s\", \"backends\": [], "
465                                                         "\"attributes\": []}"
466                                         "], "
467                                         "\"services\": []},"
468                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
469                                         "\"update_interval\": \"0s\", \"backends\": [], "
470                                         "\"attributes\": [], "
471                                         "\"metrics\": [], "
472                                         "\"services\": ["
473                                                 "{\"name\": \"s1\", "
474                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
475                                                         "\"update_interval\": \"0s\", \"backends\": [], "
476                                                         "\"attributes\": []},"
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                                                                 "{\"name\": \"k2\", \"value\": 4711, "
485                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
486                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
487                                                         "]}"
488                                         "]}"
489                         "]}" },
490                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_SERVICES,
491                         "{\"hosts\":["
492                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
493                                         "\"update_interval\": \"0s\", \"backends\": [], "
494                                         "\"attributes\": ["
495                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
496                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
497                                                         "\"update_interval\": \"0s\", \"backends\": []},"
498                                                 "{\"name\": \"k2\", \"value\": \"v2\", "
499                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
500                                                         "\"update_interval\": \"0s\", \"backends\": []},"
501                                                 "{\"name\": \"k3\", \"value\": \"v3\", "
502                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
503                                                         "\"update_interval\": \"0s\", \"backends\": []}"
504                                         "], "
505                                         "\"metrics\": ["
506                                                 "{\"name\": \"m1\", "
507                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
508                                                         "\"update_interval\": \"0s\", \"backends\": [], "
509                                                         "\"attributes\": ["
510                                                                 "{\"name\": \"k3\", \"value\": 42, "
511                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
512                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
513                                                         "]},"
514                                                 "{\"name\": \"m2\", "
515                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
516                                                         "\"update_interval\": \"0s\", \"backends\": [], "
517                                                         "\"attributes\": []}"
518                                         "]},"
519                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
520                                         "\"update_interval\": \"0s\", \"backends\": [], "
521                                         "\"attributes\": [], "
522                                         "\"metrics\": []}"
523                         "]}" },
524                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_METRICS,
525                         "{\"hosts\":["
526                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
527                                         "\"update_interval\": \"0s\", \"backends\": [], "
528                                         "\"attributes\": ["
529                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
530                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
531                                                         "\"update_interval\": \"0s\", \"backends\": []},"
532                                                 "{\"name\": \"k2\", \"value\": \"v2\", "
533                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
534                                                         "\"update_interval\": \"0s\", \"backends\": []},"
535                                                 "{\"name\": \"k3\", \"value\": \"v3\", "
536                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
537                                                         "\"update_interval\": \"0s\", \"backends\": []}"
538                                         "], "
539                                         "\"services\": []},"
540                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
541                                         "\"update_interval\": \"0s\", \"backends\": [], "
542                                         "\"attributes\": [], "
543                                         "\"services\": ["
544                                                 "{\"name\": \"s1\", "
545                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
546                                                         "\"update_interval\": \"0s\", \"backends\": [], "
547                                                         "\"attributes\": []},"
548                                                 "{\"name\": \"s2\", "
549                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
550                                                         "\"update_interval\": \"0s\", \"backends\": [], "
551                                                         "\"attributes\": ["
552                                                                 "{\"name\": \"k1\", \"value\": 123, "
553                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
554                                                                         "\"update_interval\": \"0s\", \"backends\": []},"
555                                                                 "{\"name\": \"k2\", \"value\": 4711, "
556                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
557                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
558                                                         "]}"
559                                         "]}"
560                         "]}" },
561                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ATTRIBUTES,
562                         "{\"hosts\":["
563                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
564                                         "\"update_interval\": \"0s\", \"backends\": [], "
565                                         "\"metrics\": ["
566                                                 "{\"name\": \"m1\", "
567                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
568                                                         "\"update_interval\": \"0s\", \"backends\": []},"
569                                                 "{\"name\": \"m2\", "
570                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
571                                                         "\"update_interval\": \"0s\", \"backends\": []}"
572                                         "], "
573                                         "\"services\": []},"
574                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
575                                         "\"update_interval\": \"0s\", \"backends\": [], "
576                                         "\"metrics\": [], "
577                                         "\"services\": ["
578                                                 "{\"name\": \"s1\", "
579                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
580                                                         "\"update_interval\": \"0s\", \"backends\": []},"
581                                                 "{\"name\": \"s2\", "
582                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
583                                                         "\"update_interval\": \"0s\", \"backends\": []}"
584                                         "]}"
585                         "]}" },
586                 { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ALL,
587                         "{\"hosts\":["
588                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
589                                         "\"update_interval\": \"0s\", \"backends\": []},"
590                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
591                                         "\"update_interval\": \"0s\", \"backends\": []}"
592                         "]}" },
593                 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
594                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
595                         "{\"hosts\":["
596                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
597                                         "\"update_interval\": \"0s\", \"backends\": [], "
598                                         "\"attributes\": [], "
599                                         "\"metrics\": [], "
600                                         "\"services\": ["
601                                                 "{\"name\": \"s2\", "
602                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
603                                                         "\"update_interval\": \"0s\", \"backends\": [], "
604                                                         "\"attributes\": ["
605                                                                 "{\"name\": \"k1\", \"value\": 123, "
606                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
607                                                                         "\"update_interval\": \"0s\", \"backends\": []},"
608                                                         "]}"
609                                         "]}"
610                         "]}" },
611                 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
612                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
613                         "{\"hosts\":["
614                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
615                                         "\"update_interval\": \"0s\", \"backends\": [], "
616                                         "\"attributes\": ["
617                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
618                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
619                                                         "\"update_interval\": \"0s\", \"backends\": []},"
620                                         "], "
621                                         "\"metrics\": ["
622                                                 "{\"name\": \"m2\", "
623                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
624                                                         "\"update_interval\": \"0s\", \"backends\": [], "
625                                                         "\"attributes\": []}"
626                                         "], "
627                                         "\"services\": []}"
628                         "]}" },
629                 { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
630                                 { SDB_TYPE_DATETIME, { .datetime = 3 } } }, 0,
631                         "{\"hosts\":["
632                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
633                                         "\"update_interval\": \"0s\", \"backends\": [], "
634                                         "\"attributes\": [], "
635                                         "\"metrics\": [], "
636                                         "\"services\": []}"
637                         "]}" },
638         };
640         buf = sdb_strbuf_create(0);
641         fail_unless(buf != NULL, "INTERNAL ERROR: failed to create string buffer");
642         populate();
644         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
645                 sdb_store_matcher_t *filter = NULL;
646                 char filter_str[1024] = "<none>";
647                 int status;
649                 sdb_strbuf_clear(buf);
651                 if (golden_data[i].filter.m) {
652                         sdb_store_expr_t *expr;
653                         sdb_store_cond_t *c = NULL;
655                         expr = sdb_store_expr_constvalue(&golden_data[i].filter.value);
656                         fail_unless(expr != NULL,
657                                         "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
658                         c = sdb_store_obj_cond(golden_data[i].filter.field, expr);
659                         sdb_object_deref(SDB_OBJ(expr));
660                         fail_unless(c != NULL,
661                                         "INTERNAL ERROR: sdb_store_obj_cond() = NULL");
662                         filter = golden_data[i].filter.m(c);
663                         sdb_object_deref(SDB_OBJ(c));
664                         fail_unless(filter != NULL,
665                                         "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
667                         if (sdb_store_matcher_tostring(filter,
668                                                 filter_str, sizeof(filter_str)))
669                                 snprintf(filter_str, sizeof(filter_str), "ERR");
670                 }
672                 status = sdb_store_tojson(buf, filter, golden_data[i].flags);
673                 fail_unless(status == 0,
674                                 "sdb_store_tojson(<buf>, %s, %x) = %d; expected: 0",
675                                 filter_str, golden_data[i].flags, status);
677                 verify_json_output(buf, golden_data[i].expected,
678                                 filter_str, golden_data[i].flags);
679                 sdb_object_deref(SDB_OBJ(filter));
680         }
681         sdb_strbuf_destroy(buf);
683 END_TEST
685 START_TEST(test_get_field)
687         sdb_store_obj_t *host;
688         sdb_data_t value = SDB_DATA_INIT;
689         int check;
691         sdb_store_host("host", 10);
692         sdb_store_host("host", 20);
694         host = sdb_store_get_host("host");
695         fail_unless(host != NULL,
696                         "INTERNAL ERROR: store doesn't have host after adding it");
698         check = sdb_store_get_field(NULL, 0, NULL);
699         fail_unless(check < 0,
700                         "sdb_store_get_field(NULL, 0, NULL) = %d; expected: <0");
701         check = sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, NULL);
702         fail_unless(check < 0,
703                         "sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, NULL) = %d; "
704                         "expected: <0");
705         check = sdb_store_get_field(host, SDB_FIELD_LAST_UPDATE, NULL);
706         fail_unless(check < 0,
707                         "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, NULL) = %d; "
708                         "expected: <0");
709         check = sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, &value);
710         fail_unless(check < 0,
711                         "sdb_store_get_field(NULL, SDB_FIELD_LAST_UPDATE, <value>) = %d; "
712                         "expected: <0");
714         check = sdb_store_get_field(host, SDB_FIELD_LAST_UPDATE, &value);
715         fail_unless(check == 0,
716                         "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, <value>) = "
717                         "%d; expected: 0");
718         fail_unless((value.type == SDB_TYPE_DATETIME)
719                         && (value.data.datetime == 20),
720                         "sdb_store_get_field(<host>, SDB_FIELD_LAST_UPDATE, <value>) "
721                         "returned value {%d, %lu}; expected {%d, 20}",
722                         value.type, value.data.datetime, SDB_TYPE_DATETIME);
724         check = sdb_store_get_field(host, SDB_FIELD_AGE, &value);
725         fail_unless(check == 0,
726                         "sdb_store_get_field(<host>, SDB_FIELD_AGE, <value>) = "
727                         "%d; expected: 0");
728         /* let's assume we're at least in year 1980 ;-) */
729         fail_unless((value.type == SDB_TYPE_DATETIME)
730                         && (value.data.datetime > 10L * SDB_INTERVAL_YEAR),
731                         "sdb_store_get_field(<host>, SDB_FIELD_AGE, <value>) "
732                         "returned value {%d, %lu}; expected {%d, >%lu}",
733                         value.type, value.data.datetime,
734                         SDB_TYPE_DATETIME, 10L * SDB_INTERVAL_YEAR);
736         check = sdb_store_get_field(host, SDB_FIELD_INTERVAL, &value);
737         fail_unless(check == 0,
738                         "sdb_store_get_field(<host>, SDB_FIELD_INTERVAL, <value>) = "
739                         "%d; expected: 0");
740         fail_unless((value.type == SDB_TYPE_DATETIME)
741                         && (value.data.datetime == 10),
742                         "sdb_store_get_field(<host>, SDB_FIELD_INTERVAL, <value>) "
743                         "returned value {%d, %lu}; expected {%d, 10}",
744                         value.type, value.data.datetime, SDB_TYPE_DATETIME);
746 END_TEST
748 START_TEST(test_interval)
750         sdb_store_obj_t *host;
752         /* 10 us interval */
753         sdb_store_host("host", 10);
754         sdb_store_host("host", 20);
755         sdb_store_host("host", 30);
756         sdb_store_host("host", 40);
758         host = sdb_store_get_host("host");
759         fail_unless(host != NULL,
760                         "INTERNAL ERROR: store doesn't have host after adding it");
762         fail_unless(host->interval == 10,
763                         "sdb_store_host() did not calculate interval correctly: "
764                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10);
766         /* multiple updates for the same timestamp don't modify the interval */
767         sdb_store_host("host", 40);
768         sdb_store_host("host", 40);
769         sdb_store_host("host", 40);
770         sdb_store_host("host", 40);
772         fail_unless(host->interval == 10,
773                         "sdb_store_host() changed interval when doing multiple updates "
774                         "using the same timestamp; got: %"PRIsdbTIME"; "
775                         "expected: %"PRIsdbTIME, host->interval, 10);
777         /* multiple updates using an timestamp don't modify the interval */
778         sdb_store_host("host", 20);
779         sdb_store_host("host", 20);
780         sdb_store_host("host", 20);
781         sdb_store_host("host", 20);
783         fail_unless(host->interval == 10,
784                         "sdb_store_host() changed interval when doing multiple updates "
785                         "using an old timestamp; got: %"PRIsdbTIME"; expected: %"PRIsdbTIME,
786                         host->interval, 10);
788         /* new interval: 20 us */
789         sdb_store_host("host", 60);
790         fail_unless(host->interval == 11,
791                         "sdb_store_host() did not calculate interval correctly: "
792                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
794         /* new interval: 40 us */
795         sdb_store_host("host", 100);
796         fail_unless(host->interval == 13,
797                         "sdb_store_host() did not calculate interval correctly: "
798                         "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11);
800         sdb_object_deref(SDB_OBJ(host));
802 END_TEST
804 static int
805 iter_incr(sdb_store_obj_t *obj, void *user_data)
807         intptr_t *i = user_data;
809         fail_unless(obj != NULL,
810                         "sdb_store_iterate callback received NULL obj; expected: "
811                         "<store base obj>");
812         fail_unless(i != NULL,
813                         "sdb_store_iterate callback received NULL user_data; "
814                         "expected: <pointer to data>");
816         ++(*i);
817         return 0;
818 } /* iter_incr */
820 static int
821 iter_error(sdb_store_obj_t *obj, void *user_data)
823         intptr_t *i = user_data;
825         fail_unless(obj != NULL,
826                         "sdb_store_iterate callback received NULL obj; expected: "
827                         "<store base obj>");
828         fail_unless(i != NULL,
829                         "sdb_store_iterate callback received NULL user_data; "
830                         "expected: <pointer to data>");
832         ++(*i);
833         return -1;
834 } /* iter_error */
836 START_TEST(test_iterate)
838         intptr_t i = 0;
839         int check;
841         /* empty store */
842         check = sdb_store_iterate(iter_incr, &i);
843         fail_unless(check == -1,
844                         "sdb_store_iterate(), empty store = %d; expected: -1", check);
845         fail_unless(i == 0,
846                         "sdb_store_iterate called callback %d times; expected: 0", (int)i);
848         populate();
850         check = sdb_store_iterate(iter_incr, &i);
851         fail_unless(check == 0,
852                         "sdb_store_iterate() = %d; expected: 0", check);
853         fail_unless(i == 2,
854                         "sdb_store_iterate called callback %d times; expected: 1", (int)i);
856         i = 0;
857         check = sdb_store_iterate(iter_error, &i);
858         fail_unless(check == -1,
859                         "sdb_store_iterate(), error callback = %d; expected: -1", check);
860         fail_unless(i == 1,
861                         "sdb_store_iterate called callback %d times "
862                         "(callback returned error); expected: 1", (int)i);
864 END_TEST
866 Suite *
867 core_store_suite(void)
869         Suite *s = suite_create("core::store");
870         TCase *tc;
872         tc = tcase_create("core");
873         tcase_add_test(tc, test_store_tojson);
874         tcase_add_test(tc, test_store_host);
875         tcase_add_test(tc, test_store_get_host);
876         tcase_add_test(tc, test_store_attr);
877         tcase_add_test(tc, test_store_metric);
878         tcase_add_test(tc, test_store_metric_attr);
879         tcase_add_test(tc, test_store_service);
880         tcase_add_test(tc, test_store_service_attr);
881         tcase_add_test(tc, test_get_field);
882         tcase_add_test(tc, test_interval);
883         tcase_add_test(tc, test_iterate);
884         tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);
885         suite_add_tcase(s, tc);
887         return s;
888 } /* core_store_suite */
890 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */