Code

store: Include in metric JSON whether access to time-series is available.
[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 #include "core/store.h"
29 #include "libsysdb_test.h"
31 #include <assert.h>
33 #include <check.h>
34 #include <stdlib.h>
36 static void
37 populate(void)
38 {
39         sdb_data_t datum;
41         sdb_store_host("h1", 1);
42         sdb_store_host("h2", 3);
44         datum.type = SDB_TYPE_STRING;
45         datum.data.string = "v1";
46         sdb_store_attribute("h1", "k1", &datum, 1);
47         datum.data.string = "v2";
48         sdb_store_attribute("h1", "k2", &datum, 2);
49         datum.data.string = "v3";
50         sdb_store_attribute("h1", "k3", &datum, 2);
52         /* make sure that older updates don't overwrite existing values */
53         datum.data.string = "fail";
54         sdb_store_attribute("h1", "k2", &datum, 1);
55         sdb_store_attribute("h1", "k3", &datum, 2);
57         sdb_store_metric("h1", "m1", /* store */ NULL, 2);
58         sdb_store_metric("h1", "m2", /* store */ NULL, 1);
59         sdb_store_metric("h2", "m1", /* store */ NULL, 1);
61         sdb_store_service("h2", "s1", 1);
62         sdb_store_service("h2", "s2", 2);
64         datum.type = SDB_TYPE_INTEGER;
65         datum.data.integer = 42;
66         sdb_store_metric_attr("h1", "m1", "k3", &datum, 2);
68         datum.data.integer = 123;
69         sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
70         datum.data.integer = 4711;
71         sdb_store_service_attr("h2", "s2", "k2", &datum, 1);
73         /* don't overwrite k1 */
74         datum.data.integer = 666;
75         sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
76 } /* populate */
78 static int
79 scan_tojson(sdb_store_obj_t *obj,
80                 sdb_store_matcher_t __attribute__((unused)) *filter,
81                 void *user_data)
82 {
83         sdb_store_json_formatter_t *f = user_data;
84         return sdb_store_json_emit(f, obj);
85 } /* scan_tojson */
87 static int
88 scan_tojson_full(sdb_store_obj_t *obj, sdb_store_matcher_t *filter,
89                 void *user_data)
90 {
91         sdb_store_json_formatter_t *f = user_data;
92         return sdb_store_json_emit_full(f, obj, filter);
93 } /* scan_tojson_full */
95 static void
96 verify_json_output(sdb_strbuf_t *buf, const char *expected)
97 {
98         const char *got = sdb_strbuf_string(buf);
99         size_t len1 = strlen(got);
100         size_t len2 = strlen(expected);
102         size_t i;
103         int pos = -1;
105         if (len1 != len2)
106                 pos = (int)SDB_MIN(len1, len2);
108         for (i = 0; i < SDB_MIN(len1, len2); ++i) {
109                 if (got[i] != expected[i]) {
110                         pos = (int)i;
111                         break;
112                 }
113         }
115         fail_unless(pos == -1,
116                         "Serializing hosts to JSON returned unexpected result\n"
117                         "         got: %s\n              %*s\n    expected: %s",
118                         got, pos + 1, "^", expected);
119 } /* verify_json_output */
121 START_TEST(test_store_tojson)
123         sdb_strbuf_t *buf;
124         size_t i;
126         struct {
127                 struct {
128                         sdb_store_matcher_t *(*m)(sdb_store_expr_t *,
129                                         sdb_store_expr_t *);
130                         int field;
131                         sdb_data_t value;
132                 } filter;
133                 int type;
134                 int (*f)(sdb_store_obj_t *, sdb_store_matcher_t *, void *);
135                 const char *expected;
136         } golden_data[] = {
137                 { { NULL, 0, SDB_DATA_INIT },
138                         SDB_HOST, scan_tojson_full,
139                         "["
140                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
141                                         "\"update_interval\": \"0s\", \"backends\": [], "
142                                         "\"attributes\": ["
143                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
144                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
145                                                         "\"update_interval\": \"0s\", \"backends\": []},"
146                                                 "{\"name\": \"k2\", \"value\": \"v2\", "
147                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
148                                                         "\"update_interval\": \"0s\", \"backends\": []},"
149                                                 "{\"name\": \"k3\", \"value\": \"v3\", "
150                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
151                                                         "\"update_interval\": \"0s\", \"backends\": []}"
152                                         "], "
153                                         "\"metrics\": ["
154                                                 "{\"name\": \"m1\", "
155                                                         "\"timeseries\": false, "
156                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
157                                                         "\"update_interval\": \"0s\", \"backends\": [], "
158                                                         "\"attributes\": ["
159                                                                 "{\"name\": \"k3\", \"value\": 42, "
160                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
161                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
162                                                         "]},"
163                                                 "{\"name\": \"m2\", "
164                                                         "\"timeseries\": false, "
165                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
166                                                         "\"update_interval\": \"0s\", \"backends\": []}"
167                                         "]},"
168                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
169                                         "\"update_interval\": \"0s\", \"backends\": [], "
170                                         "\"metrics\": ["
171                                                 "{\"name\": \"m1\", "
172                                                         "\"timeseries\": false, "
173                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
174                                                         "\"update_interval\": \"0s\", \"backends\": []}"
175                                         "], "
176                                         "\"services\": ["
177                                                 "{\"name\": \"s1\", "
178                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
179                                                         "\"update_interval\": \"0s\", \"backends\": []},"
180                                                 "{\"name\": \"s2\", "
181                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
182                                                         "\"update_interval\": \"0s\", \"backends\": [], "
183                                                         "\"attributes\": ["
184                                                                 "{\"name\": \"k1\", \"value\": 123, "
185                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
186                                                                         "\"update_interval\": \"0s\", \"backends\": []},"
187                                                                 "{\"name\": \"k2\", \"value\": 4711, "
188                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
189                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
190                                                         "]}"
191                                         "]}"
192                         "]" },
193                 { { NULL, 0, SDB_DATA_INIT },
194                         SDB_HOST, scan_tojson,
195                         "["
196                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
197                                         "\"update_interval\": \"0s\", \"backends\": []},"
198                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
199                                         "\"update_interval\": \"0s\", \"backends\": []}"
200                         "]" },
201                 { { sdb_store_eq_matcher, SDB_FIELD_NAME,
202                                 { SDB_TYPE_STRING, { .string = "h1" } } },
203                         SDB_HOST, scan_tojson_full,
204                         "["
205                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
206                                         "\"update_interval\": \"0s\", \"backends\": []}"
207                         "]" },
208                 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
209                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
210                         SDB_HOST, scan_tojson_full,
211                         "["
212                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
213                                         "\"update_interval\": \"0s\", \"backends\": [], "
214                                         "\"services\": ["
215                                                 "{\"name\": \"s2\", "
216                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
217                                                         "\"update_interval\": \"0s\", \"backends\": [], "
218                                                         "\"attributes\": ["
219                                                                 "{\"name\": \"k1\", \"value\": 123, "
220                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
221                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
222                                                         "]}"
223                                         "]}"
224                         "]" },
225                 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
226                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
227                         SDB_HOST, scan_tojson_full,
228                         "["
229                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
230                                         "\"update_interval\": \"0s\", \"backends\": [], "
231                                         "\"attributes\": ["
232                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
233                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
234                                                         "\"update_interval\": \"0s\", \"backends\": []}"
235                                         "], "
236                                         "\"metrics\": ["
237                                                 "{\"name\": \"m2\", "
238                                                         "\"timeseries\": false, "
239                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
240                                                         "\"update_interval\": \"0s\", \"backends\": []}"
241                                         "]}"
242                         "]" },
243                 { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
244                                 { SDB_TYPE_DATETIME, { .datetime = 3 } } },
245                         SDB_HOST, scan_tojson_full,
246                         "["
247                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
248                                         "\"update_interval\": \"0s\", \"backends\": []}"
249                         "]" },
250                 { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
251                                 { SDB_TYPE_DATETIME, { .datetime = 0 } } },
252                         SDB_HOST, scan_tojson_full,
253                         "[]" },
255                 { { NULL, 0, SDB_DATA_INIT },
256                         SDB_SERVICE, scan_tojson_full,
257                         "["
258                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
259                                         "\"update_interval\": \"0s\", \"backends\": [], "
260                                         "\"services\": ["
261                                                 "{\"name\": \"s1\", "
262                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
263                                                         "\"update_interval\": \"0s\", \"backends\": []},"
264                                                 "{\"name\": \"s2\", "
265                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
266                                                         "\"update_interval\": \"0s\", \"backends\": [], "
267                                                         "\"attributes\": ["
268                                                                 "{\"name\": \"k1\", \"value\": 123, "
269                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
270                                                                         "\"update_interval\": \"0s\", \"backends\": []},"
271                                                                 "{\"name\": \"k2\", \"value\": 4711, "
272                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
273                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
274                                                         "]}"
275                                         "]}"
276                         "]" },
277                 { { NULL, 0, SDB_DATA_INIT },
278                         SDB_SERVICE, scan_tojson,
279                         "["
280                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
281                                         "\"update_interval\": \"0s\", \"backends\": [], "
282                                         "\"services\": ["
283                                                 "{\"name\": \"s1\", "
284                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
285                                                         "\"update_interval\": \"0s\", \"backends\": []},"
286                                                 "{\"name\": \"s2\", "
287                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
288                                                         "\"update_interval\": \"0s\", \"backends\": []}"
289                                         "]}"
290                         "]" },
291                 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
292                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
293                         SDB_SERVICE, scan_tojson_full,
294                         "["
295                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
296                                         "\"update_interval\": \"0s\", \"backends\": [], "
297                                         "\"services\": ["
298                                                 "{\"name\": \"s2\", "
299                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
300                                                         "\"update_interval\": \"0s\", \"backends\": [], "
301                                                         "\"attributes\": ["
302                                                                 "{\"name\": \"k1\", \"value\": 123, "
303                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
304                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
305                                                         "]}"
306                                         "]}"
307                         "]" },
308                 { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
309                                 { SDB_TYPE_DATETIME, { .datetime = 0 } } },
310                         SDB_SERVICE, scan_tojson_full,
311                         "[]" },
312                 { { NULL, 0, SDB_DATA_INIT },
313                         SDB_METRIC, scan_tojson_full,
314                         "["
315                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
316                                         "\"update_interval\": \"0s\", \"backends\": [], "
317                                         "\"metrics\": ["
318                                                 "{\"name\": \"m1\", "
319                                                         "\"timeseries\": false, "
320                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
321                                                         "\"update_interval\": \"0s\", \"backends\": [], "
322                                                         "\"attributes\": ["
323                                                                 "{\"name\": \"k3\", \"value\": 42, "
324                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
325                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
326                                                         "]},"
327                                                 "{\"name\": \"m2\", "
328                                                         "\"timeseries\": false, "
329                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
330                                                         "\"update_interval\": \"0s\", \"backends\": []}"
331                                         "]},"
332                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
333                                         "\"update_interval\": \"0s\", \"backends\": [], "
334                                         "\"metrics\": ["
335                                                 "{\"name\": \"m1\", "
336                                                         "\"timeseries\": false, "
337                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
338                                                         "\"update_interval\": \"0s\", \"backends\": []}"
339                                         "]}"
340                         "]" },
341                 { { NULL, 0, SDB_DATA_INIT },
342                         SDB_METRIC, scan_tojson,
343                         "["
344                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
345                                         "\"update_interval\": \"0s\", \"backends\": [], "
346                                         "\"metrics\": ["
347                                                 "{\"name\": \"m1\", "
348                                                         "\"timeseries\": false, "
349                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
350                                                         "\"update_interval\": \"0s\", \"backends\": []},"
351                                                 "{\"name\": \"m2\", "
352                                                         "\"timeseries\": false, "
353                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
354                                                         "\"update_interval\": \"0s\", \"backends\": []}"
355                                         "]},"
356                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
357                                         "\"update_interval\": \"0s\", \"backends\": [], "
358                                         "\"metrics\": ["
359                                                 "{\"name\": \"m1\", "
360                                                         "\"timeseries\": false, "
361                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
362                                                         "\"update_interval\": \"0s\", \"backends\": []}"
363                                         "]}"
364                         "]" },
365                 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
366                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
367                         SDB_METRIC, scan_tojson_full,
368                         "["
369                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
370                                         "\"update_interval\": \"0s\", \"backends\": [], "
371                                         "\"metrics\": ["
372                                                 "{\"name\": \"m2\", "
373                                                         "\"timeseries\": false, "
374                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
375                                                         "\"update_interval\": \"0s\", \"backends\": []}"
376                                         "]}"
377                         "]" },
378                 { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
379                                 { SDB_TYPE_DATETIME, { .datetime = 0 } } },
380                         SDB_METRIC, scan_tojson_full,
381                         "[]" },
382         };
384         buf = sdb_strbuf_create(0);
385         fail_unless(buf != NULL, "INTERNAL ERROR: failed to create string buffer");
386         populate();
388         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
389                 sdb_store_matcher_t *filter = NULL;
390                 sdb_store_json_formatter_t *f;
391                 int status;
393                 sdb_strbuf_clear(buf);
395                 if (golden_data[i].filter.m) {
396                         sdb_store_expr_t *field;
397                         sdb_store_expr_t *value;
399                         field = sdb_store_expr_fieldvalue(golden_data[i].filter.field);
400                         fail_unless(field != NULL,
401                                         "INTERNAL ERROR: sdb_store_expr_fieldvalue() = NULL");
402                         value = sdb_store_expr_constvalue(&golden_data[i].filter.value);
403                         fail_unless(value != NULL,
404                                         "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
406                         filter = golden_data[i].filter.m(field, value);
407                         fail_unless(filter != NULL,
408                                         "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
410                         sdb_object_deref(SDB_OBJ(field));
411                         sdb_object_deref(SDB_OBJ(value));
412                 }
414                 sdb_strbuf_clear(buf);
415                 f = sdb_store_json_formatter(buf,
416                                 golden_data[i].type, SDB_WANT_ARRAY);
417                 assert(f);
419                 status = sdb_store_scan(golden_data[i].type, /* m = */ NULL, filter,
420                                 golden_data[i].f, f);
421                 fail_unless(status == 0,
422                                 "sdb_store_scan(HOST, ..., tojson) = %d; expected: 0",
423                                 status);
424                 sdb_store_json_finish(f);
426                 verify_json_output(buf, golden_data[i].expected);
427                 free(f);
428                 sdb_object_deref(SDB_OBJ(filter));
429         }
430         sdb_strbuf_destroy(buf);
432 END_TEST
434 Suite *
435 core_store_json_suite(void)
437         Suite *s = suite_create("core::store_json");
438         TCase *tc;
440         tc = tcase_create("core");
441         tcase_add_test(tc, test_store_tojson);
442         tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);
443         suite_add_tcase(s, tc);
445         return s;
446 } /* core_store_json_suite */
448 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */