9dc157068183b49c2e2c4e1e74276bcccee9c064
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 struct {
122 struct {
123 sdb_store_matcher_t *(*m)(sdb_store_expr_t *,
124 sdb_store_expr_t *);
125 int field;
126 sdb_data_t value;
127 } filter;
128 int type;
129 int (*f)(sdb_store_obj_t *, sdb_store_matcher_t *, void *);
130 const char *expected;
131 } store_tojson_data[] = {
132 { { NULL, 0, SDB_DATA_INIT },
133 SDB_HOST, scan_tojson_full,
134 "["
135 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
136 "\"update_interval\": \"0s\", \"backends\": [], "
137 "\"attributes\": ["
138 "{\"name\": \"k1\", \"value\": \"v1\", "
139 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
140 "\"update_interval\": \"0s\", \"backends\": []},"
141 "{\"name\": \"k2\", \"value\": \"v2\", "
142 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
143 "\"update_interval\": \"0s\", \"backends\": []},"
144 "{\"name\": \"k3\", \"value\": \"v3\", "
145 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
146 "\"update_interval\": \"0s\", \"backends\": []}"
147 "], "
148 "\"metrics\": ["
149 "{\"name\": \"m1\", "
150 "\"timeseries\": false, "
151 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
152 "\"update_interval\": \"0s\", \"backends\": [], "
153 "\"attributes\": ["
154 "{\"name\": \"k3\", \"value\": 42, "
155 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
156 "\"update_interval\": \"0s\", \"backends\": []}"
157 "]},"
158 "{\"name\": \"m2\", "
159 "\"timeseries\": false, "
160 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
161 "\"update_interval\": \"0s\", \"backends\": []}"
162 "]},"
163 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
164 "\"update_interval\": \"0s\", \"backends\": [], "
165 "\"metrics\": ["
166 "{\"name\": \"m1\", "
167 "\"timeseries\": false, "
168 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
169 "\"update_interval\": \"0s\", \"backends\": []}"
170 "], "
171 "\"services\": ["
172 "{\"name\": \"s1\", "
173 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
174 "\"update_interval\": \"0s\", \"backends\": []},"
175 "{\"name\": \"s2\", "
176 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
177 "\"update_interval\": \"0s\", \"backends\": [], "
178 "\"attributes\": ["
179 "{\"name\": \"k1\", \"value\": 123, "
180 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
181 "\"update_interval\": \"0s\", \"backends\": []},"
182 "{\"name\": \"k2\", \"value\": 4711, "
183 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
184 "\"update_interval\": \"0s\", \"backends\": []}"
185 "]}"
186 "]}"
187 "]" },
188 { { NULL, 0, SDB_DATA_INIT },
189 SDB_HOST, scan_tojson,
190 "["
191 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
192 "\"update_interval\": \"0s\", \"backends\": []},"
193 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
194 "\"update_interval\": \"0s\", \"backends\": []}"
195 "]" },
196 { { sdb_store_eq_matcher, SDB_FIELD_NAME,
197 { SDB_TYPE_STRING, { .string = "h1" } } },
198 SDB_HOST, scan_tojson_full,
199 "["
200 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
201 "\"update_interval\": \"0s\", \"backends\": []}"
202 "]" },
203 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
204 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
205 SDB_HOST, scan_tojson_full,
206 "["
207 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
208 "\"update_interval\": \"0s\", \"backends\": [], "
209 "\"services\": ["
210 "{\"name\": \"s2\", "
211 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
212 "\"update_interval\": \"0s\", \"backends\": [], "
213 "\"attributes\": ["
214 "{\"name\": \"k1\", \"value\": 123, "
215 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
216 "\"update_interval\": \"0s\", \"backends\": []}"
217 "]}"
218 "]}"
219 "]" },
220 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
221 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
222 SDB_HOST, scan_tojson_full,
223 "["
224 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
225 "\"update_interval\": \"0s\", \"backends\": [], "
226 "\"attributes\": ["
227 "{\"name\": \"k1\", \"value\": \"v1\", "
228 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
229 "\"update_interval\": \"0s\", \"backends\": []}"
230 "], "
231 "\"metrics\": ["
232 "{\"name\": \"m2\", "
233 "\"timeseries\": false, "
234 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
235 "\"update_interval\": \"0s\", \"backends\": []}"
236 "]}"
237 "]" },
238 { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
239 { SDB_TYPE_DATETIME, { .datetime = 3 } } },
240 SDB_HOST, scan_tojson_full,
241 "["
242 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
243 "\"update_interval\": \"0s\", \"backends\": []}"
244 "]" },
245 { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
246 { SDB_TYPE_DATETIME, { .datetime = 0 } } },
247 SDB_HOST, scan_tojson_full,
248 "[]" },
250 { { NULL, 0, SDB_DATA_INIT },
251 SDB_SERVICE, scan_tojson_full,
252 "["
253 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
254 "\"update_interval\": \"0s\", \"backends\": [], "
255 "\"services\": ["
256 "{\"name\": \"s1\", "
257 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
258 "\"update_interval\": \"0s\", \"backends\": []},"
259 "{\"name\": \"s2\", "
260 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
261 "\"update_interval\": \"0s\", \"backends\": [], "
262 "\"attributes\": ["
263 "{\"name\": \"k1\", \"value\": 123, "
264 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
265 "\"update_interval\": \"0s\", \"backends\": []},"
266 "{\"name\": \"k2\", \"value\": 4711, "
267 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
268 "\"update_interval\": \"0s\", \"backends\": []}"
269 "]}"
270 "]}"
271 "]" },
272 { { NULL, 0, SDB_DATA_INIT },
273 SDB_SERVICE, scan_tojson,
274 "["
275 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
276 "\"update_interval\": \"0s\", \"backends\": [], "
277 "\"services\": ["
278 "{\"name\": \"s1\", "
279 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
280 "\"update_interval\": \"0s\", \"backends\": []},"
281 "{\"name\": \"s2\", "
282 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
283 "\"update_interval\": \"0s\", \"backends\": []}"
284 "]}"
285 "]" },
286 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
287 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
288 SDB_SERVICE, scan_tojson_full,
289 "["
290 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
291 "\"update_interval\": \"0s\", \"backends\": [], "
292 "\"services\": ["
293 "{\"name\": \"s2\", "
294 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
295 "\"update_interval\": \"0s\", \"backends\": [], "
296 "\"attributes\": ["
297 "{\"name\": \"k1\", \"value\": 123, "
298 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
299 "\"update_interval\": \"0s\", \"backends\": []}"
300 "]}"
301 "]}"
302 "]" },
303 { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
304 { SDB_TYPE_DATETIME, { .datetime = 0 } } },
305 SDB_SERVICE, scan_tojson_full,
306 "[]" },
307 { { NULL, 0, SDB_DATA_INIT },
308 SDB_METRIC, scan_tojson_full,
309 "["
310 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
311 "\"update_interval\": \"0s\", \"backends\": [], "
312 "\"metrics\": ["
313 "{\"name\": \"m1\", "
314 "\"timeseries\": false, "
315 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
316 "\"update_interval\": \"0s\", \"backends\": [], "
317 "\"attributes\": ["
318 "{\"name\": \"k3\", \"value\": 42, "
319 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
320 "\"update_interval\": \"0s\", \"backends\": []}"
321 "]},"
322 "{\"name\": \"m2\", "
323 "\"timeseries\": false, "
324 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
325 "\"update_interval\": \"0s\", \"backends\": []}"
326 "]},"
327 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
328 "\"update_interval\": \"0s\", \"backends\": [], "
329 "\"metrics\": ["
330 "{\"name\": \"m1\", "
331 "\"timeseries\": false, "
332 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
333 "\"update_interval\": \"0s\", \"backends\": []}"
334 "]}"
335 "]" },
336 { { NULL, 0, SDB_DATA_INIT },
337 SDB_METRIC, scan_tojson,
338 "["
339 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
340 "\"update_interval\": \"0s\", \"backends\": [], "
341 "\"metrics\": ["
342 "{\"name\": \"m1\", "
343 "\"timeseries\": false, "
344 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
345 "\"update_interval\": \"0s\", \"backends\": []},"
346 "{\"name\": \"m2\", "
347 "\"timeseries\": false, "
348 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
349 "\"update_interval\": \"0s\", \"backends\": []}"
350 "]},"
351 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
352 "\"update_interval\": \"0s\", \"backends\": [], "
353 "\"metrics\": ["
354 "{\"name\": \"m1\", "
355 "\"timeseries\": false, "
356 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
357 "\"update_interval\": \"0s\", \"backends\": []}"
358 "]}"
359 "]" },
360 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
361 { SDB_TYPE_DATETIME, { .datetime = 1 } } },
362 SDB_METRIC, scan_tojson_full,
363 "["
364 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
365 "\"update_interval\": \"0s\", \"backends\": [], "
366 "\"metrics\": ["
367 "{\"name\": \"m2\", "
368 "\"timeseries\": false, "
369 "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
370 "\"update_interval\": \"0s\", \"backends\": []}"
371 "]}"
372 "]" },
373 { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
374 { SDB_TYPE_DATETIME, { .datetime = 0 } } },
375 SDB_METRIC, scan_tojson_full,
376 "[]" },
377 };
379 START_TEST(test_store_tojson)
380 {
381 sdb_strbuf_t *buf = sdb_strbuf_create(0);
382 sdb_store_matcher_t *filter = NULL;
383 sdb_store_json_formatter_t *f;
384 int status;
386 if (store_tojson_data[_i].filter.m) {
387 sdb_store_expr_t *field;
388 sdb_store_expr_t *value;
390 field = sdb_store_expr_fieldvalue(store_tojson_data[_i].filter.field);
391 fail_unless(field != NULL,
392 "INTERNAL ERROR: sdb_store_expr_fieldvalue() = NULL");
393 value = sdb_store_expr_constvalue(&store_tojson_data[_i].filter.value);
394 fail_unless(value != NULL,
395 "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
397 filter = store_tojson_data[_i].filter.m(field, value);
398 fail_unless(filter != NULL,
399 "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
401 sdb_object_deref(SDB_OBJ(field));
402 sdb_object_deref(SDB_OBJ(value));
403 }
405 sdb_strbuf_clear(buf);
406 f = sdb_store_json_formatter(buf,
407 store_tojson_data[_i].type, SDB_WANT_ARRAY);
408 assert(f);
410 status = sdb_store_scan(store_tojson_data[_i].type,
411 /* m = */ NULL, filter, store_tojson_data[_i].f, f);
412 fail_unless(status == 0,
413 "sdb_store_scan(HOST, ..., tojson) = %d; expected: 0",
414 status);
415 sdb_store_json_finish(f);
417 verify_json_output(buf, store_tojson_data[_i].expected);
419 free(f);
420 sdb_object_deref(SDB_OBJ(filter));
421 sdb_strbuf_destroy(buf);
422 }
423 END_TEST
425 Suite *
426 core_store_json_suite(void)
427 {
428 Suite *s = suite_create("core::store_json");
429 TCase *tc;
431 tc = tcase_create("core");
432 TC_ADD_LOOP_TEST(tc, store_tojson);
433 tcase_add_unchecked_fixture(tc, populate, sdb_store_clear);
434 suite_add_tcase(s, tc);
436 return s;
437 } /* core_store_json_suite */
439 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */