Code

Handle last_update/interval in the core rather than in memstore.
[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/memstore.h"
33 #include "core/store.h"
34 #include "testutils.h"
36 #include <check.h>
37 #include <stdlib.h>
39 /* Make SDB_INTERVAL_SECOND a constant initializer. */
40 #undef SDB_INTERVAL_SECOND
41 #define SDB_INTERVAL_SECOND 1000000000L
43 static sdb_memstore_t *store;
45 static void
46 populate(void)
47 {
48         sdb_data_t datum;
50         store = sdb_memstore_create();
51         ck_assert(store != NULL);
53         sdb_memstore_host(store, "h1", 1 * SDB_INTERVAL_SECOND, 0);
54         sdb_memstore_host(store, "h2", 3 * SDB_INTERVAL_SECOND, 0);
56         datum.type = SDB_TYPE_STRING;
57         datum.data.string = "v1";
58         sdb_memstore_attribute(store, "h1", "k1", &datum, 1 * SDB_INTERVAL_SECOND, 0);
59         datum.data.string = "v2";
60         sdb_memstore_attribute(store, "h1", "k2", &datum, 2 * SDB_INTERVAL_SECOND, 0);
61         datum.data.string = "v3";
62         sdb_memstore_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND, 0);
64 /* TODO: move these tests into generic store tests */
65 #if 0
66         /* make sure that older updates don't overwrite existing values */
67         datum.data.string = "fail";
68         sdb_memstore_attribute(store, "h1", "k2", &datum, 1 * SDB_INTERVAL_SECOND, 0);
69         sdb_memstore_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND, 0);
70 #endif
72         sdb_memstore_metric(store, "h1", "m1", /* store */ NULL, 2 * SDB_INTERVAL_SECOND, 0);
73         sdb_memstore_metric(store, "h1", "m2", /* store */ NULL, 1 * SDB_INTERVAL_SECOND, 0);
74         sdb_memstore_metric(store, "h2", "m1", /* store */ NULL, 1 * SDB_INTERVAL_SECOND, 0);
76         sdb_memstore_service(store, "h2", "s1", 1 * SDB_INTERVAL_SECOND, 0);
77         sdb_memstore_service(store, "h2", "s2", 2 * SDB_INTERVAL_SECOND, 0);
79         datum.type = SDB_TYPE_INTEGER;
80         datum.data.integer = 42;
81         sdb_memstore_metric_attr(store, "h1", "m1", "k3",
82                         &datum, 2 * SDB_INTERVAL_SECOND, 0);
84         datum.data.integer = 123;
85         sdb_memstore_service_attr(store, "h2", "s2", "k1",
86                         &datum, 2 * SDB_INTERVAL_SECOND, 0);
87         datum.data.integer = 4711;
88         sdb_memstore_service_attr(store, "h2", "s2", "k2",
89                         &datum, 1 * SDB_INTERVAL_SECOND, 0);
90 } /* populate */
92 static void
93 turndown(void)
94 {
95         sdb_object_deref(SDB_OBJ(store));
96         store = NULL;
97 } /* turndown */
99 static int
100 scan_tojson(sdb_memstore_obj_t *obj,
101                 sdb_memstore_matcher_t __attribute__((unused)) *filter,
102                 void *user_data)
104         return sdb_memstore_emit(obj, &sdb_store_json_writer, user_data);
105 } /* scan_tojson */
107 static int
108 scan_tojson_full(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter,
109                 void *user_data)
111         return sdb_memstore_emit_full(obj, filter, &sdb_store_json_writer, user_data);
112 } /* scan_tojson_full */
114 static void
115 verify_json_output(sdb_strbuf_t *buf, const char *expected)
117         const char *got = sdb_strbuf_string(buf);
118         size_t len1 = strlen(got);
119         size_t len2 = strlen(expected);
121         size_t i;
122         int pos = -1;
124         if (len1 != len2)
125                 pos = (int)SDB_MIN(len1, len2);
127         for (i = 0; i < SDB_MIN(len1, len2); ++i) {
128                 if (got[i] != expected[i]) {
129                         pos = (int)i;
130                         break;
131                 }
132         }
134         fail_unless(pos == -1,
135                         "Serializing hosts to JSON returned unexpected result\n"
136                         "         got: %s\n              %*s\n    expected: %s",
137                         got, pos + 1, "^", expected);
138 } /* verify_json_output */
140 struct {
141         struct {
142                 sdb_memstore_matcher_t *(*m)(sdb_memstore_expr_t *, sdb_memstore_expr_t *);
143                 int field;
144                 sdb_data_t value;
145         } filter;
146         int type;
147         int (*f)(sdb_memstore_obj_t *, sdb_memstore_matcher_t *, void *);
148         const char *expected;
149 } store_tojson_data[] = {
150         { { NULL, 0, SDB_DATA_INIT },
151                 SDB_HOST, scan_tojson_full,
152                 "["
153                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
154                                 "\"update_interval\": \"0s\", \"backends\": [], "
155                                 "\"attributes\": ["
156                                         "{\"name\": \"k1\", \"value\": \"v1\", "
157                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
158                                                 "\"update_interval\": \"0s\", \"backends\": []},"
159                                         "{\"name\": \"k2\", \"value\": \"v2\", "
160                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
161                                                 "\"update_interval\": \"0s\", \"backends\": []},"
162                                         "{\"name\": \"k3\", \"value\": \"v3\", "
163                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
164                                                 "\"update_interval\": \"0s\", \"backends\": []}"
165                                 "], "
166                                 "\"metrics\": ["
167                                         "{\"name\": \"m1\", "
168                                                 "\"timeseries\": false, "
169                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
170                                                 "\"update_interval\": \"0s\", \"backends\": [], "
171                                                 "\"attributes\": ["
172                                                         "{\"name\": \"k3\", \"value\": 42, "
173                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
174                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
175                                                 "]},"
176                                         "{\"name\": \"m2\", "
177                                                 "\"timeseries\": false, "
178                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
179                                                 "\"update_interval\": \"0s\", \"backends\": []}"
180                                 "]},"
181                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
182                                 "\"update_interval\": \"0s\", \"backends\": [], "
183                                 "\"metrics\": ["
184                                         "{\"name\": \"m1\", "
185                                                 "\"timeseries\": false, "
186                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
187                                                 "\"update_interval\": \"0s\", \"backends\": []}"
188                                 "], "
189                                 "\"services\": ["
190                                         "{\"name\": \"s1\", "
191                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
192                                                 "\"update_interval\": \"0s\", \"backends\": []},"
193                                         "{\"name\": \"s2\", "
194                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
195                                                 "\"update_interval\": \"0s\", \"backends\": [], "
196                                                 "\"attributes\": ["
197                                                         "{\"name\": \"k1\", \"value\": 123, "
198                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
199                                                                 "\"update_interval\": \"0s\", \"backends\": []},"
200                                                         "{\"name\": \"k2\", \"value\": 4711, "
201                                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
202                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
203                                                 "]}"
204                                 "]}"
205                 "]" },
206         { { NULL, 0, SDB_DATA_INIT },
207                 SDB_HOST, scan_tojson,
208                 "["
209                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
210                                 "\"update_interval\": \"0s\", \"backends\": []},"
211                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
212                                 "\"update_interval\": \"0s\", \"backends\": []}"
213                 "]" },
214         { { sdb_memstore_eq_matcher, SDB_FIELD_NAME,
215                         { SDB_TYPE_STRING, { .string = "h1" } } },
216                 SDB_HOST, scan_tojson_full,
217                 "["
218                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
219                                 "\"update_interval\": \"0s\", \"backends\": []}"
220                 "]" },
221         { { sdb_memstore_gt_matcher, SDB_FIELD_LAST_UPDATE,
222                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
223                 SDB_HOST, scan_tojson_full,
224                 "["
225                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
226                                 "\"update_interval\": \"0s\", \"backends\": [], "
227                                 "\"services\": ["
228                                         "{\"name\": \"s2\", "
229                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
230                                                 "\"update_interval\": \"0s\", \"backends\": [], "
231                                                 "\"attributes\": ["
232                                                         "{\"name\": \"k1\", \"value\": 123, "
233                                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
234                                                                 "\"update_interval\": \"0s\", \"backends\": []}"
235                                                 "]}"
236                                 "]}"
237                 "]" },
238         { { sdb_memstore_le_matcher, SDB_FIELD_LAST_UPDATE,
239                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
240                 SDB_HOST, scan_tojson_full,
241                 "["
242                         "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
243                                 "\"update_interval\": \"0s\", \"backends\": [], "
244                                 "\"attributes\": ["
245                                         "{\"name\": \"k1\", \"value\": \"v1\", "
246                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
247                                                 "\"update_interval\": \"0s\", \"backends\": []}"
248                                 "], "
249                                 "\"metrics\": ["
250                                         "{\"name\": \"m2\", "
251                                                 "\"timeseries\": false, "
252                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
253                                                 "\"update_interval\": \"0s\", \"backends\": []}"
254                                 "]}"
255                 "]" },
256         { { sdb_memstore_ge_matcher, SDB_FIELD_LAST_UPDATE,
257                         { SDB_TYPE_DATETIME, { .datetime = 3 * SDB_INTERVAL_SECOND } } },
258                 SDB_HOST, scan_tojson_full,
259                 "["
260                         "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
261                                 "\"update_interval\": \"0s\", \"backends\": []}"
262                 "]" },
263         { { sdb_memstore_lt_matcher, SDB_FIELD_LAST_UPDATE,
264                         { SDB_TYPE_DATETIME, { .datetime = 0 } } },
265                 SDB_HOST, scan_tojson_full,
266                 "[]" },
268         { { NULL, 0, SDB_DATA_INIT },
269                 SDB_SERVICE, scan_tojson_full,
270                 "["
271                         "{\"name\": \"s1\", "
272                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
273                                 "\"update_interval\": \"0s\", \"backends\": []},"
274                         "{\"name\": \"s2\", "
275                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
276                                 "\"update_interval\": \"0s\", \"backends\": [], "
277                                 "\"attributes\": ["
278                                         "{\"name\": \"k1\", \"value\": 123, "
279                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
280                                                 "\"update_interval\": \"0s\", \"backends\": []},"
281                                         "{\"name\": \"k2\", \"value\": 4711, "
282                                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
283                                                 "\"update_interval\": \"0s\", \"backends\": []}"
284                                 "]}"
285                 "]" },
286         { { NULL, 0, SDB_DATA_INIT },
287                 SDB_SERVICE, scan_tojson,
288                 "["
289                         "{\"name\": \"s1\", "
290                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
291                                 "\"update_interval\": \"0s\", \"backends\": []},"
292                         "{\"name\": \"s2\", "
293                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
294                                 "\"update_interval\": \"0s\", \"backends\": []}"
295                 "]" },
296         { { sdb_memstore_gt_matcher, SDB_FIELD_LAST_UPDATE,
297                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
298                 SDB_SERVICE, scan_tojson_full,
299                 "["
300                         "{\"name\": \"s2\", "
301                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
302                                 "\"update_interval\": \"0s\", \"backends\": [], "
303                                 "\"attributes\": ["
304                                         "{\"name\": \"k1\", \"value\": 123, "
305                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
306                                                 "\"update_interval\": \"0s\", \"backends\": []}"
307                                 "]}"
308                 "]" },
309         { { sdb_memstore_lt_matcher, SDB_FIELD_LAST_UPDATE,
310                         { SDB_TYPE_DATETIME, { .datetime = 0 } } },
311                 SDB_SERVICE, scan_tojson_full,
312                 "[]" },
313         { { NULL, 0, SDB_DATA_INIT },
314                 SDB_METRIC, scan_tojson_full,
315                 "["
316                         "{\"name\": \"m1\", "
317                                 "\"timeseries\": false, "
318                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
319                                 "\"update_interval\": \"0s\", \"backends\": [], "
320                                 "\"attributes\": ["
321                                         "{\"name\": \"k3\", \"value\": 42, "
322                                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
323                                                 "\"update_interval\": \"0s\", \"backends\": []}"
324                                 "]},"
325                         "{\"name\": \"m2\", "
326                                 "\"timeseries\": false, "
327                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
328                                 "\"update_interval\": \"0s\", \"backends\": []},"
329                         "{\"name\": \"m1\", "
330                                 "\"timeseries\": false, "
331                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
332                                 "\"update_interval\": \"0s\", \"backends\": []}"
333                 "]" },
334         { { NULL, 0, SDB_DATA_INIT },
335                 SDB_METRIC, scan_tojson,
336                 "["
337                         "{\"name\": \"m1\", "
338                                 "\"timeseries\": false, "
339                                 "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
340                                 "\"update_interval\": \"0s\", \"backends\": []},"
341                         "{\"name\": \"m2\", "
342                                 "\"timeseries\": false, "
343                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
344                                 "\"update_interval\": \"0s\", \"backends\": []},"
345                         "{\"name\": \"m1\", "
346                                 "\"timeseries\": false, "
347                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
348                                 "\"update_interval\": \"0s\", \"backends\": []}"
349                 "]" },
350         { { sdb_memstore_le_matcher, SDB_FIELD_LAST_UPDATE,
351                         { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
352                 SDB_METRIC, scan_tojson_full,
353                 "["
354                         "{\"name\": \"m2\", "
355                                 "\"timeseries\": false, "
356                                 "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
357                                 "\"update_interval\": \"0s\", \"backends\": []}"
358                 "]" },
359         { { sdb_memstore_lt_matcher, SDB_FIELD_LAST_UPDATE,
360                         { SDB_TYPE_DATETIME, { .datetime = 0 } } },
361                 SDB_METRIC, scan_tojson_full,
362                 "[]" },
363 };
365 START_TEST(test_store_tojson)
367         sdb_strbuf_t *buf = sdb_strbuf_create(0);
368         sdb_memstore_matcher_t *filter = NULL;
369         sdb_store_json_formatter_t *f;
370         int status;
372         if (store_tojson_data[_i].filter.m) {
373                 sdb_memstore_expr_t *field;
374                 sdb_memstore_expr_t *value;
376                 field = sdb_memstore_expr_fieldvalue(store_tojson_data[_i].filter.field);
377                 fail_unless(field != NULL,
378                                 "INTERNAL ERROR: sdb_memstore_expr_fieldvalue() = NULL");
379                 value = sdb_memstore_expr_constvalue(&store_tojson_data[_i].filter.value);
380                 fail_unless(value != NULL,
381                                 "INTERNAL ERROR: sdb_memstore_expr_constvalue() = NULL");
383                 filter = store_tojson_data[_i].filter.m(field, value);
384                 fail_unless(filter != NULL,
385                                 "INTERNAL ERROR: sdb_memstore_*_matcher() = NULL");
387                 sdb_object_deref(SDB_OBJ(field));
388                 sdb_object_deref(SDB_OBJ(value));
389         }
391         sdb_strbuf_clear(buf);
392         f = sdb_store_json_formatter(buf, store_tojson_data[_i].type, SDB_WANT_ARRAY);
393         ck_assert(f != NULL);
395         status = sdb_memstore_scan(store, store_tojson_data[_i].type,
396                         /* m = */ NULL, filter, store_tojson_data[_i].f, f);
397         fail_unless(status == 0,
398                         "sdb_memstore_scan(HOST, ..., tojson) = %d; expected: 0",
399                         status);
400         sdb_store_json_finish(f);
402         verify_json_output(buf, store_tojson_data[_i].expected);
404         sdb_object_deref(SDB_OBJ(filter));
405         sdb_object_deref(SDB_OBJ(f));
406         sdb_strbuf_destroy(buf);
408 END_TEST
410 TEST_MAIN("core::store_json")
412         TCase *tc = tcase_create("core");
413         tcase_add_unchecked_fixture(tc, populate, turndown);
414         TC_ADD_LOOP_TEST(tc, store_tojson);
415         ADD_TCASE(tc);
417 TEST_MAIN_END
419 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */