Code

c544633e3e4e1b189ebcd180687957fcfeaf2f17
[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 (*f)(sdb_store_obj_t *, sdb_store_matcher_t *, void *);
134                 const char *expected;
135         } golden_data[] = {
136                 { { NULL, 0, SDB_DATA_INIT }, scan_tojson_full,
137                         "["
138                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
139                                         "\"update_interval\": \"0s\", \"backends\": [], "
140                                         "\"attributes\": ["
141                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
142                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
143                                                         "\"update_interval\": \"0s\", \"backends\": []},"
144                                                 "{\"name\": \"k2\", \"value\": \"v2\", "
145                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
146                                                         "\"update_interval\": \"0s\", \"backends\": []},"
147                                                 "{\"name\": \"k3\", \"value\": \"v3\", "
148                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
149                                                         "\"update_interval\": \"0s\", \"backends\": []}"
150                                         "], "
151                                         "\"metrics\": ["
152                                                 "{\"name\": \"m1\", "
153                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
154                                                         "\"update_interval\": \"0s\", \"backends\": [], "
155                                                         "\"attributes\": ["
156                                                                 "{\"name\": \"k3\", \"value\": 42, "
157                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
158                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
159                                                         "]},"
160                                                 "{\"name\": \"m2\", "
161                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
162                                                         "\"update_interval\": \"0s\", \"backends\": []}"
163                                         "]},"
164                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
165                                         "\"update_interval\": \"0s\", \"backends\": [], "
166                                         "\"metrics\": ["
167                                                 "{\"name\": \"m1\", "
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 }, scan_tojson,
189                         "["
190                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
191                                         "\"update_interval\": \"0s\", \"backends\": []},"
192                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
193                                         "\"update_interval\": \"0s\", \"backends\": []}"
194                         "]" },
195                 { { sdb_store_eq_matcher, SDB_FIELD_NAME,
196                                 { SDB_TYPE_STRING, { .string = "h1" } } }, scan_tojson_full,
197                         "["
198                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
199                                         "\"update_interval\": \"0s\", \"backends\": []}"
200                         "]" },
201                 { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
202                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, scan_tojson_full,
203                         "["
204                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
205                                         "\"update_interval\": \"0s\", \"backends\": [], "
206                                         "\"services\": ["
207                                                 "{\"name\": \"s2\", "
208                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
209                                                         "\"update_interval\": \"0s\", \"backends\": [], "
210                                                         "\"attributes\": ["
211                                                                 "{\"name\": \"k1\", \"value\": 123, "
212                                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
213                                                                         "\"update_interval\": \"0s\", \"backends\": []}"
214                                                         "]}"
215                                         "]}"
216                         "]" },
217                 { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
218                                 { SDB_TYPE_DATETIME, { .datetime = 1 } } }, scan_tojson_full,
219                         "["
220                                 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
221                                         "\"update_interval\": \"0s\", \"backends\": [], "
222                                         "\"attributes\": ["
223                                                 "{\"name\": \"k1\", \"value\": \"v1\", "
224                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
225                                                         "\"update_interval\": \"0s\", \"backends\": []}"
226                                         "], "
227                                         "\"metrics\": ["
228                                                 "{\"name\": \"m2\", "
229                                                         "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
230                                                         "\"update_interval\": \"0s\", \"backends\": []}"
231                                         "]}"
232                         "]" },
233                 { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
234                                 { SDB_TYPE_DATETIME, { .datetime = 3 } } }, scan_tojson_full,
235                         "["
236                                 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
237                                         "\"update_interval\": \"0s\", \"backends\": []}"
238                         "]" },
239                 { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
240                                 { SDB_TYPE_DATETIME, { .datetime = 0 } } }, scan_tojson_full,
241                         "[]" },
242         };
244         buf = sdb_strbuf_create(0);
245         fail_unless(buf != NULL, "INTERNAL ERROR: failed to create string buffer");
246         populate();
248         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
249                 sdb_store_matcher_t *filter = NULL;
250                 sdb_store_json_formatter_t *f;
251                 int status;
253                 sdb_strbuf_clear(buf);
255                 if (golden_data[i].filter.m) {
256                         sdb_store_expr_t *field;
257                         sdb_store_expr_t *value;
259                         field = sdb_store_expr_fieldvalue(golden_data[i].filter.field);
260                         fail_unless(field != NULL,
261                                         "INTERNAL ERROR: sdb_store_expr_fieldvalue() = NULL");
262                         value = sdb_store_expr_constvalue(&golden_data[i].filter.value);
263                         fail_unless(value != NULL,
264                                         "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
266                         filter = golden_data[i].filter.m(field, value);
267                         fail_unless(filter != NULL,
268                                         "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
270                         sdb_object_deref(SDB_OBJ(field));
271                         sdb_object_deref(SDB_OBJ(value));
272                 }
274                 sdb_strbuf_clear(buf);
275                 f = sdb_store_json_formatter(buf, SDB_WANT_ARRAY);
276                 assert(f);
278                 status = sdb_store_scan(SDB_HOST, /* m = */ NULL, filter,
279                                 golden_data[i].f, f);
280                 fail_unless(status == 0,
281                                 "sdb_store_scan(HOST, ..., tojson) = %d; expected: 0",
282                                 status);
283                 sdb_store_json_finish(f);
285                 verify_json_output(buf, golden_data[i].expected);
286                 free(f);
287                 sdb_object_deref(SDB_OBJ(filter));
288         }
289         sdb_strbuf_destroy(buf);
291 END_TEST
293 Suite *
294 core_store_json_suite(void)
296         Suite *s = suite_create("core::store_json");
297         TCase *tc;
299         tc = tcase_create("core");
300         tcase_add_test(tc, test_store_tojson);
301         tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);
302         suite_add_tcase(s, tc);
304         return s;
305 } /* core_store_json_suite */
307 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */