a0447b639e8b5ea73de65ab8b15f4d9289c3da1a
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)
103 {
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)
110 {
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)
116 {
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)
366 {
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);
407 }
408 END_TEST
410 TEST_MAIN("core::store_json")
411 {
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);
416 }
417 TEST_MAIN_END
419 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */