Code

plugin, store: Add service/metric "hostname" attributes centrally.
[sysdb.git] / t / unit / core / store_json_test.c
1 /*
2  * SysDB - t/unit/core/store_json_test.c
3  * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #if HAVE_CONFIG_H
29 #       include "config.h"
30 #endif
32 #include "core/store.h"
33 #include "testutils.h"
35 #include <check.h>
36 #include <stdlib.h>
38 /* Make SDB_INTERVAL_SECOND a constant initializer. */
39 #undef SDB_INTERVAL_SECOND
40 #define SDB_INTERVAL_SECOND 1000000000L
42 static sdb_store_t *store;
44 static void
45 populate(void)
46 {
47         sdb_data_t datum;
49         store = sdb_store_create();
50         ck_assert(store != NULL);
52         sdb_store_host(store, "h1", 1 * SDB_INTERVAL_SECOND);
53         sdb_store_host(store, "h2", 3 * SDB_INTERVAL_SECOND);
55         datum.type = SDB_TYPE_STRING;
56         datum.data.string = "v1";
57         sdb_store_attribute(store, "h1", "k1", &datum, 1 * SDB_INTERVAL_SECOND);
58         datum.data.string = "v2";
59         sdb_store_attribute(store, "h1", "k2", &datum, 2 * SDB_INTERVAL_SECOND);
60         datum.data.string = "v3";
61         sdb_store_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND);
63         /* make sure that older updates don't overwrite existing values */
64         datum.data.string = "fail";
65         sdb_store_attribute(store, "h1", "k2", &datum, 1 * SDB_INTERVAL_SECOND);
66         sdb_store_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND);
68         sdb_store_metric(store, "h1", "m1", /* store */ NULL, 2 * SDB_INTERVAL_SECOND);
69         sdb_store_metric(store, "h1", "m2", /* store */ NULL, 1 * SDB_INTERVAL_SECOND);
70         sdb_store_metric(store, "h2", "m1", /* store */ NULL, 1 * SDB_INTERVAL_SECOND);
72         sdb_store_service(store, "h2", "s1", 1 * SDB_INTERVAL_SECOND);
73         sdb_store_service(store, "h2", "s2", 2 * SDB_INTERVAL_SECOND);
75         datum.type = SDB_TYPE_INTEGER;
76         datum.data.integer = 42;
77         sdb_store_metric_attr(store, "h1", "m1", "k3",
78                         &datum, 2 * SDB_INTERVAL_SECOND);
80         datum.data.integer = 123;
81         sdb_store_service_attr(store, "h2", "s2", "k1",
82                         &datum, 2 * SDB_INTERVAL_SECOND);
83         datum.data.integer = 4711;
84         sdb_store_service_attr(store, "h2", "s2", "k2",
85                         &datum, 1 * SDB_INTERVAL_SECOND);
87         /* don't overwrite k1 */
88         datum.data.integer = 666;
89         sdb_store_service_attr(store, "h2", "s2", "k1",
90                         &datum, 2 * SDB_INTERVAL_SECOND);
91 } /* populate */
93 static void
94 turndown(void)
95 {
96         sdb_object_deref(SDB_OBJ(store));
97         store = NULL;
98 } /* turndown */
100 static int
101 scan_tojson(sdb_store_obj_t *obj,
102                 sdb_store_matcher_t __attribute__((unused)) *filter,
103                 void *user_data)
105         sdb_store_json_formatter_t *f = user_data;
106         return sdb_store_json_emit(f, obj);
107 } /* scan_tojson */
109 static int
110 scan_tojson_full(sdb_store_obj_t *obj, sdb_store_matcher_t *filter,
111                 void *user_data)
113         sdb_store_json_formatter_t *f = user_data;
114         return sdb_store_json_emit_full(f, obj, filter);
115 } /* scan_tojson_full */
117 static void
118 verify_json_output(sdb_strbuf_t *buf, const char *expected)
120         const char *got = sdb_strbuf_string(buf);
121         size_t len1 = strlen(got);
122         size_t len2 = strlen(expected);
124         size_t i;
125         int pos = -1;
127         if (len1 != len2)
128                 pos = (int)SDB_MIN(len1, len2);
130         for (i = 0; i < SDB_MIN(len1, len2); ++i) {
131                 if (got[i] != expected[i]) {
132                         pos = (int)i;
133                         break;
134                 }
135         }
137         fail_unless(pos == -1,
138                         "Serializing hosts to JSON returned unexpected result\n"
139                         "         got: %s\n              %*s\n    expected: %s",
140                         got, pos + 1, "^", expected);
141 } /* verify_json_output */
143 struct {
144         struct {
145                 sdb_store_matcher_t *(*m)(sdb_store_expr_t *, sdb_store_expr_t *);
146                 int field;
147                 sdb_data_t value;
148         } filter;
149         int type;
150         int (*f)(sdb_store_obj_t *, sdb_store_matcher_t *, void *);
151         const char *expected;
152 } store_tojson_data[] = {
153         { { NULL, 0, SDB_DATA_INIT },
154                 SDB_HOST, scan_tojson_full,
155                 "["
156                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
157                                 "\"update_interval\": \"0s\", \"backends\": [], "
158                                 "\"attributes\": ["
159                                         "{\"name\": \"k1\", \"value\": \"v1\", "
160                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
161                                                 "\"update_interval\": \"0s\", \"backends\": []},"
162                                         "{\"name\": \"k2\", \"value\": \"v2\", "
163                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
164                                                 "\"update_interval\": \"0s\", \"backends\": []},"
165                                         "{\"name\": \"k3\", \"value\": \"v3\", "
166                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
167                                                 "\"update_interval\": \"0s\", \"backends\": []}"
168                                 "], "
169                                 "\"metrics\": ["
170                                         "{\"name\": \"m1\", "
171                                                 "\"timeseries\": false, "
172                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
173                                                 "\"update_interval\": \"0s\", \"backends\": [], "
174                                                 "\"attributes\": ["
175                                                         "{\"name\": \"k3\", \"value\": 42, "
176                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
177                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
178                                                 "]},"
179                                         "{\"name\": \"m2\", "
180                                                 "\"timeseries\": false, "
181                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
182                                                 "\"update_interval\": \"0s\", \"backends\": []}"
183                                 "]},"
184                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
185                                 "\"update_interval\": \"0s\", \"backends\": [], "
186                                 "\"metrics\": ["
187                                         "{\"name\": \"m1\", "
188                                                 "\"timeseries\": false, "
189                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
190                                                 "\"update_interval\": \"0s\", \"backends\": []}"
191                                 "], "
192                                 "\"services\": ["
193                                         "{\"name\": \"s1\", "
194                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
195                                                 "\"update_interval\": \"0s\", \"backends\": []},"
196                                         "{\"name\": \"s2\", "
197                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
198                                                 "\"update_interval\": \"0s\", \"backends\": [], "
199                                                 "\"attributes\": ["
200                                                         "{\"name\": \"k1\", \"value\": 123, "
201                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
202                                                                 "\"update_interval\": \"0s\", \"backends\": []},"
203                                                         "{\"name\": \"k2\", \"value\": 4711, "
204                                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
205                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
206                                                 "]}"
207                                 "]}"
208                 "]" },
209         { { NULL, 0, SDB_DATA_INIT },
210                 SDB_HOST, scan_tojson,
211                 "["
212                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
213                                 "\"update_interval\": \"0s\", \"backends\": []},"
214                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
215                                 "\"update_interval\": \"0s\", \"backends\": []}"
216                 "]" },
217         { { sdb_store_eq_matcher, SDB_FIELD_NAME,
218                         { SDB_TYPE_STRING, { .string = "h1" } } },
219                 SDB_HOST, scan_tojson_full,
220                 "["
221                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
222                                 "\"update_interval\": \"0s\", \"backends\": []}"
223                 "]" },
224         { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
225                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
226                 SDB_HOST, scan_tojson_full,
227                 "["
228                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
229                                 "\"update_interval\": \"0s\", \"backends\": [], "
230                                 "\"services\": ["
231                                         "{\"name\": \"s2\", "
232                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
233                                                 "\"update_interval\": \"0s\", \"backends\": [], "
234                                                 "\"attributes\": ["
235                                                         "{\"name\": \"k1\", \"value\": 123, "
236                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
237                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
238                                                 "]}"
239                                 "]}"
240                 "]" },
241         { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
242                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
243                 SDB_HOST, scan_tojson_full,
244                 "["
245                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
246                                 "\"update_interval\": \"0s\", \"backends\": [], "
247                                 "\"attributes\": ["
248                                         "{\"name\": \"k1\", \"value\": \"v1\", "
249                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
250                                                 "\"update_interval\": \"0s\", \"backends\": []}"
251                                 "], "
252                                 "\"metrics\": ["
253                                         "{\"name\": \"m2\", "
254                                                 "\"timeseries\": false, "
255                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
256                                                 "\"update_interval\": \"0s\", \"backends\": []}"
257                                 "]}"
258                 "]" },
259         { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
260                         { SDB_TYPE_DATETIME, { .datetime = 3 * SDB_INTERVAL_SECOND } } },
261                 SDB_HOST, scan_tojson_full,
262                 "["
263                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
264                                 "\"update_interval\": \"0s\", \"backends\": []}"
265                 "]" },
266         { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
267                         { SDB_TYPE_DATETIME, { .datetime = 0 } } },
268                 SDB_HOST, scan_tojson_full,
269                 "[]" },
271         { { NULL, 0, SDB_DATA_INIT },
272                 SDB_SERVICE, scan_tojson_full,
273                 "["
274                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
275                                 "\"update_interval\": \"0s\", \"backends\": [], "
276                                 "\"services\": ["
277                                         "{\"name\": \"s1\", "
278                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
279                                                 "\"update_interval\": \"0s\", \"backends\": []},"
280                                         "{\"name\": \"s2\", "
281                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
282                                                 "\"update_interval\": \"0s\", \"backends\": [], "
283                                                 "\"attributes\": ["
284                                                         "{\"name\": \"k1\", \"value\": 123, "
285                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
286                                                                 "\"update_interval\": \"0s\", \"backends\": []},"
287                                                         "{\"name\": \"k2\", \"value\": 4711, "
288                                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
289                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
290                                                 "]}"
291                                 "]}"
292                 "]" },
293         { { NULL, 0, SDB_DATA_INIT },
294                 SDB_SERVICE, scan_tojson,
295                 "["
296                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
297                                 "\"update_interval\": \"0s\", \"backends\": [], "
298                                 "\"services\": ["
299                                         "{\"name\": \"s1\", "
300                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
301                                                 "\"update_interval\": \"0s\", \"backends\": []},"
302                                         "{\"name\": \"s2\", "
303                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
304                                                 "\"update_interval\": \"0s\", \"backends\": []}"
305                                 "]}"
306                 "]" },
307         { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
308                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
309                 SDB_SERVICE, scan_tojson_full,
310                 "["
311                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
312                                 "\"update_interval\": \"0s\", \"backends\": [], "
313                                 "\"services\": ["
314                                         "{\"name\": \"s2\", "
315                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
316                                                 "\"update_interval\": \"0s\", \"backends\": [], "
317                                                 "\"attributes\": ["
318                                                         "{\"name\": \"k1\", \"value\": 123, "
319                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
320                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
321                                                 "]}"
322                                 "]}"
323                 "]" },
324         { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
325                         { SDB_TYPE_DATETIME, { .datetime = 0 } } },
326                 SDB_SERVICE, scan_tojson_full,
327                 "[]" },
328         { { NULL, 0, SDB_DATA_INIT },
329                 SDB_METRIC, scan_tojson_full,
330                 "["
331                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
332                                 "\"update_interval\": \"0s\", \"backends\": [], "
333                                 "\"metrics\": ["
334                                         "{\"name\": \"m1\", "
335                                                 "\"timeseries\": false, "
336                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
337                                                 "\"update_interval\": \"0s\", \"backends\": [], "
338                                                 "\"attributes\": ["
339                                                         "{\"name\": \"k3\", \"value\": 42, "
340                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
341                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
342                                                 "]},"
343                                         "{\"name\": \"m2\", "
344                                                 "\"timeseries\": false, "
345                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
346                                                 "\"update_interval\": \"0s\", \"backends\": []}"
347                                 "]},"
348                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
349                                 "\"update_interval\": \"0s\", \"backends\": [], "
350                                 "\"metrics\": ["
351                                         "{\"name\": \"m1\", "
352                                                 "\"timeseries\": false, "
353                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
354                                                 "\"update_interval\": \"0s\", \"backends\": []}"
355                                 "]}"
356                 "]" },
357         { { NULL, 0, SDB_DATA_INIT },
358                 SDB_METRIC, scan_tojson,
359                 "["
360                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
361                                 "\"update_interval\": \"0s\", \"backends\": [], "
362                                 "\"metrics\": ["
363                                         "{\"name\": \"m1\", "
364                                                 "\"timeseries\": false, "
365                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
366                                                 "\"update_interval\": \"0s\", \"backends\": []},"
367                                         "{\"name\": \"m2\", "
368                                                 "\"timeseries\": false, "
369                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
370                                                 "\"update_interval\": \"0s\", \"backends\": []}"
371                                 "]},"
372                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
373                                 "\"update_interval\": \"0s\", \"backends\": [], "
374                                 "\"metrics\": ["
375                                         "{\"name\": \"m1\", "
376                                                 "\"timeseries\": false, "
377                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
378                                                 "\"update_interval\": \"0s\", \"backends\": []}"
379                                 "]}"
380                 "]" },
381         { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
382                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
383                 SDB_METRIC, scan_tojson_full,
384                 "["
385                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
386                                 "\"update_interval\": \"0s\", \"backends\": [], "
387                                 "\"metrics\": ["
388                                         "{\"name\": \"m2\", "
389                                                 "\"timeseries\": false, "
390                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
391                                                 "\"update_interval\": \"0s\", \"backends\": []}"
392                                 "]}"
393                 "]" },
394         { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
395                         { SDB_TYPE_DATETIME, { .datetime = 0 } } },
396                 SDB_METRIC, scan_tojson_full,
397                 "[]" },
398 };
400 START_TEST(test_store_tojson)
402         sdb_strbuf_t *buf = sdb_strbuf_create(0);
403         sdb_store_matcher_t *filter = NULL;
404         sdb_store_json_formatter_t *f;
405         int status;
407         if (store_tojson_data[_i].filter.m) {
408                 sdb_store_expr_t *field;
409                 sdb_store_expr_t *value;
411                 field = sdb_store_expr_fieldvalue(store_tojson_data[_i].filter.field);
412                 fail_unless(field != NULL,
413                                 "INTERNAL ERROR: sdb_store_expr_fieldvalue() = NULL");
414                 value = sdb_store_expr_constvalue(&store_tojson_data[_i].filter.value);
415                 fail_unless(value != NULL,
416                                 "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
418                 filter = store_tojson_data[_i].filter.m(field, value);
419                 fail_unless(filter != NULL,
420                                 "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
422                 sdb_object_deref(SDB_OBJ(field));
423                 sdb_object_deref(SDB_OBJ(value));
424         }
426         sdb_strbuf_clear(buf);
427         f = sdb_store_json_formatter(buf,
428                         store_tojson_data[_i].type, SDB_WANT_ARRAY);
429         ck_assert(f != NULL);
431         status = sdb_store_scan(store, store_tojson_data[_i].type,
432                         /* m = */ NULL, filter, store_tojson_data[_i].f, f);
433         fail_unless(status == 0,
434                         "sdb_store_scan(HOST, ..., tojson) = %d; expected: 0",
435                         status);
436         sdb_store_json_finish(f);
438         verify_json_output(buf, store_tojson_data[_i].expected);
440         sdb_object_deref(SDB_OBJ(filter));
441         sdb_object_deref(SDB_OBJ(f));
442         sdb_strbuf_destroy(buf);
444 END_TEST
446 TEST_MAIN("core::store_json")
448         TCase *tc = tcase_create("core");
449         tcase_add_unchecked_fixture(tc, populate, turndown);
450         TC_ADD_LOOP_TEST(tc, store_tojson);
451         ADD_TCASE(tc);
453 TEST_MAIN_END
455 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */