861313f5363d9094897b83f967f5782f9ae772f2
1 /*
2 * SysDB - t/unit/frontend/query_test.c
3 * Copyright (C) 2015 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 "frontend/connection.h"
33 #include "frontend/connection-private.h"
34 #include "testutils.h"
36 #include <check.h>
38 /*
39 * private helpers
40 */
42 static void
43 populate(void)
44 {
45 sdb_data_t datum;
47 sdb_store_host("h1", 1);
48 sdb_store_host("h2", 3);
50 datum.type = SDB_TYPE_STRING;
51 datum.data.string = "v1";
52 sdb_store_attribute("h1", "k1", &datum, 1);
53 datum.data.string = "v2";
54 sdb_store_attribute("h1", "k2", &datum, 2);
55 datum.data.string = "v3";
56 sdb_store_attribute("h1", "k3", &datum, 2);
58 sdb_store_metric("h1", "m1", /* store */ NULL, 2);
59 sdb_store_metric("h1", "m2", /* store */ NULL, 1);
60 sdb_store_metric("h2", "m1", /* store */ NULL, 1);
62 datum.type = SDB_TYPE_INTEGER;
63 datum.data.integer = 42;
64 sdb_store_metric_attr("h1", "m1", "k3", &datum, 2);
66 sdb_store_service("h2", "s1", 1);
67 sdb_store_service("h2", "s2", 2);
69 datum.data.integer = 123;
70 sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
71 datum.data.integer = 4711;
72 sdb_store_service_attr("h2", "s2", "k2", &datum, 1);
73 } /* populate */
75 #define HOST_H1 \
76 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
77 "\"update_interval\": \"0s\", \"backends\": [], " \
78 "\"attributes\": [" \
79 "{\"name\": \"k1\", \"value\": \"v1\", " \
80 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
81 "\"update_interval\": \"0s\", \"backends\": []}," \
82 "{\"name\": \"k2\", \"value\": \"v2\", " \
83 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
84 "\"update_interval\": \"0s\", \"backends\": []}," \
85 "{\"name\": \"k3\", \"value\": \"v3\", " \
86 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
87 "\"update_interval\": \"0s\", \"backends\": []}], " \
88 "\"metrics\": [" \
89 "{\"name\": \"m1\", \"timeseries\": false, " \
90 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
91 "\"update_interval\": \"0s\", \"backends\": [], " \
92 "\"attributes\": [" \
93 "{\"name\": \"hostname\", \"value\": \"h1\", " \
94 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
95 "\"update_interval\": \"0s\", \"backends\": []}," \
96 "{\"name\": \"k3\", \"value\": 42, " \
97 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
98 "\"update_interval\": \"0s\", \"backends\": []}]}," \
99 "{\"name\": \"m2\", \"timeseries\": false, " \
100 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
101 "\"update_interval\": \"0s\", \"backends\": [], " \
102 "\"attributes\": [" \
103 "{\"name\": \"hostname\", \"value\": \"h1\", " \
104 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
105 "\"update_interval\": \"0s\", \"backends\": []}]}]}"
106 #define HOST_H1_ARRAY "["HOST_H1"]"
107 #define HOST_H1_LISTING \
108 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
109 "\"update_interval\": \"0s\", \"backends\": []}"
110 #define HOST_H2_LISTING \
111 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
112 "\"update_interval\": \"0s\", \"backends\": []}"
114 #define SERVICE_H2_S1 \
115 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
116 "\"update_interval\": \"0s\", \"backends\": [], " \
117 "\"services\": [" \
118 "{\"name\": \"s1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
119 "\"update_interval\": \"0s\", \"backends\": [], " \
120 "\"attributes\": [" \
121 "{\"name\": \"hostname\", \"value\": \"h2\", " \
122 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
123 "\"update_interval\": \"0s\", \"backends\": []}]}]}"
124 #define SERVICE_H2_S1_ARRAY "["SERVICE_H2_S1"]"
125 #define SERVICE_H2_S12_LISTING \
126 "[{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
127 "\"update_interval\": \"0s\", \"backends\": [], " \
128 "\"services\": [" \
129 "{\"name\": \"s1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
130 "\"update_interval\": \"0s\", \"backends\": []}," \
131 "{\"name\": \"s2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
132 "\"update_interval\": \"0s\", \"backends\": []}]}]"
134 #define METRIC_H1_M1 \
135 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
136 "\"update_interval\": \"0s\", \"backends\": [], " \
137 "\"metrics\": [" \
138 "{\"name\": \"m1\", \"timeseries\": false, " \
139 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
140 "\"update_interval\": \"0s\", \"backends\": [], " \
141 "\"attributes\": [" \
142 "{\"name\": \"hostname\", \"value\": \"h1\", " \
143 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
144 "\"update_interval\": \"0s\", \"backends\": []}," \
145 "{\"name\": \"k3\", \"value\": 42, " \
146 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
147 "\"update_interval\": \"0s\", \"backends\": []}]}]}"
148 #define METRIC_H12_M1_ARRAY \
149 "["METRIC_H1_M1"," \
150 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
151 "\"update_interval\": \"0s\", \"backends\": [], " \
152 "\"metrics\": [" \
153 "{\"name\": \"m1\", \"timeseries\": false, " \
154 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
155 "\"update_interval\": \"0s\", \"backends\": [], " \
156 "\"attributes\": [" \
157 "{\"name\": \"hostname\", \"value\": \"h2\", " \
158 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
159 "\"update_interval\": \"0s\", \"backends\": []}]}]}]"
160 #define METRIC_H12_M12_LISTING \
161 "[{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
162 "\"update_interval\": \"0s\", \"backends\": [], " \
163 "\"metrics\": [" \
164 "{\"name\": \"m1\", \"timeseries\": false, " \
165 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
166 "\"update_interval\": \"0s\", \"backends\": []}," \
167 "{\"name\": \"m2\", \"timeseries\": false, " \
168 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
169 "\"update_interval\": \"0s\", \"backends\": []}]}," \
170 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
171 "\"update_interval\": \"0s\", \"backends\": [], " \
172 "\"metrics\": [" \
173 "{\"name\": \"m1\", \"timeseries\": false, " \
174 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
175 "\"update_interval\": \"0s\", \"backends\": []}]}]"
177 typedef struct {
178 sdb_conn_t conn;
179 sdb_strbuf_t *write_buf;
180 } mock_conn_t;
181 #define MOCK_CONN(obj) ((mock_conn_t *)(obj))
182 #define CONN(obj) ((sdb_conn_t *)(obj))
184 static void
185 mock_conn_destroy(sdb_conn_t *conn)
186 {
187 sdb_strbuf_destroy(conn->buf);
188 sdb_strbuf_destroy(conn->errbuf);
189 sdb_strbuf_destroy(MOCK_CONN(conn)->write_buf);
190 free(conn);
191 } /* mock_conn_destroy */
193 static ssize_t
194 mock_conn_read(sdb_conn_t *conn, size_t len)
195 {
196 if (! conn)
197 return -1;
198 /* unused so far */
199 return len;
200 } /* conn_read */
202 static ssize_t
203 mock_conn_write(sdb_conn_t *conn, const void *buf, size_t len)
204 {
205 if (! conn)
206 return -1;
207 return sdb_strbuf_memappend(MOCK_CONN(conn)->write_buf, buf, len);
208 } /* conn_write */
210 static sdb_conn_t *
211 mock_conn_create(void)
212 {
213 mock_conn_t *conn;
215 conn = calloc(1, sizeof(*conn));
216 if (! conn) {
217 fail("INTERNAL ERROR: failed to allocate connection object");
218 return NULL;
219 }
221 SDB_OBJ(conn)->name = "mock_connection";
222 SDB_OBJ(conn)->ref_cnt = 1;
224 conn->conn.buf = sdb_strbuf_create(0);
225 conn->conn.errbuf = sdb_strbuf_create(0);
226 conn->write_buf = sdb_strbuf_create(64);
227 if ((! conn->conn.buf) || (! conn->conn.errbuf) || (! conn->write_buf)) {
228 mock_conn_destroy(CONN(conn));
229 fail("INTERNAL ERROR: failed to allocate connection object");
230 return NULL;
231 }
233 conn->conn.read = mock_conn_read;
234 conn->conn.write = mock_conn_write;
236 conn->conn.username = "mock_user";
237 conn->conn.cmd = SDB_CONNECTION_IDLE;
238 conn->conn.cmd_len = 0;
239 return CONN(conn);
240 } /* mock_conn_create */
242 /* TODO: move this into a test helper module */
243 static void
244 fail_if_strneq(const char *got, const char *expected, size_t n, const char *fmt, ...)
245 {
246 sdb_strbuf_t *buf;
247 va_list ap;
249 size_t len1 = strlen(got);
250 size_t len2 = strlen(expected);
252 size_t i;
253 int pos = -1;
255 if (n) {
256 len1 = SDB_MIN(len1, n);
257 len2 = SDB_MIN(len2, n);
258 }
260 if (len1 != len2)
261 pos = (int)SDB_MIN(len1, len2);
263 for (i = 0; i < SDB_MIN(len1, len2); ++i) {
264 if (got[i] != expected[i]) {
265 pos = (int)i;
266 break;
267 }
268 }
270 if (pos == -1)
271 return;
273 buf = sdb_strbuf_create(64);
274 va_start(ap, fmt);
275 sdb_strbuf_vsprintf(buf, fmt, ap);
277 fail("%s\n got: %s\n %*s\n expected: %s",
278 sdb_strbuf_string(buf), got, pos + 1, "^", expected);
279 } /* fail_if_strneq */
281 /*
282 * tests
283 */
285 #define VALUE "\0\0\0\4""v1"
286 #define VALUE_LEN 7
288 static struct {
289 uint32_t cmd;
290 const char *query;
291 int query_len;
292 int expected;
293 uint32_t code;
294 size_t len;
295 uint32_t type;
296 const char *data;
297 } query_data[] = {
298 /* hosts */
299 {
300 SDB_CONNECTION_QUERY, "LIST hosts", -1,
301 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST,
302 "["HOST_H1_LISTING","HOST_H2_LISTING"]",
303 },
304 {
305 SDB_CONNECTION_LIST, "\0\0\0\1", 4,
306 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST,
307 "["HOST_H1_LISTING","HOST_H2_LISTING"]",
308 },
309 {
310 SDB_CONNECTION_LIST, "", 0, /* LIST defaults to hosts */
311 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST,
312 "["HOST_H1_LISTING","HOST_H2_LISTING"]",
313 },
314 {
315 SDB_CONNECTION_QUERY, "LIST hosts; LIST hosts", -1, /* ignore second (and later) commands */
316 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST,
317 "["HOST_H1_LISTING","HOST_H2_LISTING"]",
318 },
319 {
320 SDB_CONNECTION_QUERY, "LIST hosts FILTER name = 'h1'", -1,
321 0, SDB_CONNECTION_DATA, 105, SDB_CONNECTION_LIST, "["HOST_H1_LISTING"]",
322 },
323 {
324 SDB_CONNECTION_QUERY, "LIST hosts FILTER name = 's1'", -1,
325 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]",
326 },
327 /* SDB_CONNECTION_LIST doesn't support filters yet */
328 {
329 SDB_CONNECTION_QUERY, "FETCH host 'h1'", -1,
330 0, SDB_CONNECTION_DATA, 1110, SDB_CONNECTION_FETCH, HOST_H1,
331 },
332 {
333 SDB_CONNECTION_FETCH, "\0\0\0\1""h1", 7,
334 0, SDB_CONNECTION_DATA, 1110, SDB_CONNECTION_FETCH, HOST_H1,
335 },
336 {
337 SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'h1'", -1,
338 0, SDB_CONNECTION_DATA, 1112, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY,
339 },
340 {
341 SDB_CONNECTION_LOOKUP, "\0\0\0\1""name = 'h1'", 16,
342 0, SDB_CONNECTION_DATA, 1112, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY,
343 },
344 {
345 SDB_CONNECTION_QUERY, "FETCH host 'h1' FILTER age >= 0s", -1, /* always matches */
346 0, SDB_CONNECTION_DATA, 1110, SDB_CONNECTION_FETCH, HOST_H1,
347 },
348 /* SDB_CONNECTION_FETCH doesn't support filters yet */
349 {
350 SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'h1' FILTER age >= 0s", -1, /* always matches */
351 0, SDB_CONNECTION_DATA, 1112, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY,
352 },
353 {
354 SDB_CONNECTION_QUERY, "FETCH host 'h1' FILTER age < 0s", -1, /* never matches */
355 -1, UINT32_MAX, 0, 0, NULL, /* FETCH fails if the object doesn't exist */
356 },
357 /* SDB_CONNECTION_FETCH doesn't support filters yet */
358 {
359 SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'h1' FILTER age < 0s", -1, /* never matches */
360 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
361 },
362 /* SDB_CONNECTION_LOOKUP doesn't support filters yet */
363 {
364 SDB_CONNECTION_QUERY, "FETCH host 'x1'", -1, /* does not exist */
365 -1, UINT32_MAX, 0, 0, NULL,
366 },
367 {
368 SDB_CONNECTION_FETCH, "\0\0\0\1x1", 7,
369 -1, UINT32_MAX, 0, 0, NULL,
370 },
371 {
372 SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'x1'", -1, /* does not exist */
373 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
374 },
375 {
376 SDB_CONNECTION_LOOKUP, "\0\0\0\1""name = 'x1'", 16, /* does not exist */
377 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
378 },
379 {
380 SDB_CONNECTION_QUERY, "FETCH host 'h1'.'s1'", -1, /* invalid args */
381 -1, UINT32_MAX, 0, 0, NULL,
382 },
383 {
384 SDB_CONNECTION_QUERY, "LOOKUP hosts BY name = 'x1'", -1, /* does not exist */
385 -1, UINT32_MAX, 0, 0, NULL,
386 },
387 /* services */
388 {
389 SDB_CONNECTION_QUERY, "LIST services", -1,
390 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING,
391 },
392 {
393 SDB_CONNECTION_LIST, "\0\0\0\2", 4,
394 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING,
395 },
396 {
397 SDB_CONNECTION_QUERY, "LIST services FILTER host.name = 'h2'", -1,
398 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING,
399 },
400 {
401 SDB_CONNECTION_QUERY, "LIST services FILTER host.name = 'h1'", -1,
402 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]",
403 },
404 /* SDB_CONNECTION_LIST doesn't support filters yet */
405 {
406 SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1'", -1,
407 0, SDB_CONNECTION_DATA, 356, SDB_CONNECTION_FETCH, SERVICE_H2_S1,
408 },
409 /* SDB_CONNECTION_FETCH doesn't support services yet */
410 {
411 SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1'", -1,
412 0, SDB_CONNECTION_DATA, 358, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY,
413 },
414 {
415 SDB_CONNECTION_LOOKUP, "\0\0\0\2""name = 's1'", 16,
416 0, SDB_CONNECTION_DATA, 358, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY,
417 },
418 {
419 SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1' FILTER age >= 0s", -1, /* always matches */
420 0, SDB_CONNECTION_DATA, 356, SDB_CONNECTION_FETCH, SERVICE_H2_S1,
421 },
422 /* SDB_CONNECTION_FETCH doesn't support services yet */
423 {
424 SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1' FILTER age >= 0s", -1, /* always matches */
425 0, SDB_CONNECTION_DATA, 358, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY,
426 },
427 {
428 SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1' FILTER age < 0s", -1, /* never matches */
429 -1, UINT32_MAX, 0, 0, NULL,
430 },
431 /* SDB_CONNECTION_FETCH doesn't support services yet */
432 {
433 SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1' FILTER age < 0s", -1, /* never matches */
434 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
435 },
436 /* SDB_CONNECTION_LOOKUP doesn't support filters yet */
437 {
438 SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1' FILTER name = 'h2'", -1, /* only matches host */
439 -1, UINT32_MAX, 0, 0, NULL,
440 },
441 /* SDB_CONNECTION_FETCH doesn't support services yet */
442 {
443 SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1' FILTER name = 'h2'", -1, /* only matches host */
444 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
445 },
446 {
447 SDB_CONNECTION_QUERY, "FETCH service 'h2'.'x1'", -1, /* does not exist */
448 -1, UINT32_MAX, 0, 0, NULL,
449 },
450 /* SDB_CONNECTION_FETCH doesn't support services yet */
451 {
452 SDB_CONNECTION_QUERY, "FETCH service 'x2'.'s1'", -1, /* does not exist */
453 -1, UINT32_MAX, 0, 0, NULL,
454 },
455 /* SDB_CONNECTION_FETCH doesn't support services yet */
456 {
457 SDB_CONNECTION_QUERY, "FETCH service 'h2'", -1, /* invalid args */
458 -1, UINT32_MAX, 0, 0, NULL,
459 },
460 /* SDB_CONNECTION_FETCH doesn't support services yet */
461 /* metrics */
462 {
463 SDB_CONNECTION_QUERY, "LIST metrics", -1,
464 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING,
465 },
466 {
467 SDB_CONNECTION_LIST, "\0\0\0\3", 4,
468 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING,
469 },
470 {
471 SDB_CONNECTION_QUERY, "LIST metrics FILTER age > 0s", -1,
472 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING,
473 },
474 {
475 SDB_CONNECTION_QUERY, "LIST metrics FILTER age < 0s", -1,
476 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]",
477 },
478 /* SDB_CONNECTION_LIST doesn't support filters yet */
479 {
480 SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1'", -1,
481 0, SDB_CONNECTION_DATA, 489, SDB_CONNECTION_FETCH, METRIC_H1_M1,
482 },
483 /* SDB_CONNECTION_FETCH doesn't support metrics yet */
484 {
485 SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1'", -1,
486 0, SDB_CONNECTION_DATA, 864, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY,
487 },
488 {
489 SDB_CONNECTION_LOOKUP, "\0\0\0\3""name = 'm1'", 16,
490 0, SDB_CONNECTION_DATA, 864, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY,
491 },
492 {
493 SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1' FILTER age >= 0s", -1, /* always matches */
494 0, SDB_CONNECTION_DATA, 489, SDB_CONNECTION_FETCH, METRIC_H1_M1,
495 },
496 /* SDB_CONNECTION_FETCH doesn't support metrics yet */
497 {
498 SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1' FILTER age >= 0s", -1, /* always matches */
499 0, SDB_CONNECTION_DATA, 864, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY,
500 },
501 {
502 SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1' FILTER age < 0s", -1, /* never matches */
503 -1, UINT32_MAX, 0, 0, NULL,
504 },
505 /* SDB_CONNECTION_FETCH doesn't support metrics yet */
506 {
507 SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1' FILTER age < 0s", -1, /* never matches */
508 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
509 },
510 /* SDB_CONEECTION_LOOKUP doesn't support filters yet */
511 {
512 SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1' FILTER name = 'h1'", -1, /* only matches host */
513 -1, UINT32_MAX, 0, 0, NULL,
514 },
515 /* SDB_CONNECTION_FETCH doesn't support metrics yet */
516 {
517 SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1' FILTER name = 'h1'", -1, /* only matches host */
518 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
519 },
520 {
521 SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'x1'", -1, /* does not exist */
522 -1, UINT32_MAX, 0, 0, NULL,
523 },
524 /* SDB_CONNECTION_FETCH doesn't support metrics yet */
525 {
526 SDB_CONNECTION_QUERY, "FETCH metric 'x1'.'m1'", -1, /* does not exist */
527 -1, UINT32_MAX, 0, 0, NULL,
528 },
529 /* SDB_CONNECTION_FETCH doesn't support metrics yet */
530 {
531 SDB_CONNECTION_QUERY, "FETCH metric 'x1'", -1, /* invalid args */
532 -1, UINT32_MAX, 0, 0, NULL,
533 },
534 /* SDB_CONNECTION_FETCH doesn't support metrics yet */
535 /* timeseries */
536 {
537 SDB_CONNECTION_QUERY, "TIMESERIES 'h1'.'m1'", -1,
538 -1, UINT32_MAX, 0, 0, NULL, /* no data-store available */
539 },
540 {
541 SDB_CONNECTION_QUERY, "TIMESERIES 'h1'.'x1'", -1,
542 -1, UINT32_MAX, 0, 0, NULL, /* does not exist */
543 },
544 {
545 SDB_CONNECTION_QUERY, "TIMESERIES 'x1'.'m1'", -1,
546 -1, UINT32_MAX, 0, 0, NULL, /* does not exist */
547 },
548 /* store commands */
549 {
550 SDB_CONNECTION_QUERY, "STORE host 'hA' LAST UPDATE 01:00", -1,
551 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA",
552 },
553 {
554 SDB_CONNECTION_STORE, "\0\0\0\1""\0\0\0\0\xd6\x93\xa4\0""hA", 15,
555 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA",
556 },
557 {
558 SDB_CONNECTION_QUERY, "STORE host 'hA'", -1,
559 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA",
560 },
561 {
562 SDB_CONNECTION_QUERY, "STORE host attribute 'h1'.'aA' 'vA'", -1,
563 0, SDB_CONNECTION_OK, 40, 0, "Successfully stored host attribute h1.aA",
564 },
565 {
566 SDB_CONNECTION_STORE, "\0\0\0\x11""\0\0\0\0\xd6\x93\xa4\0""h1\0aA\0"VALUE, 18+VALUE_LEN,
567 0, SDB_CONNECTION_OK, 40, 0, "Successfully stored host attribute h1.aA",
568 },
569 {
570 SDB_CONNECTION_QUERY, "STORE host attribute 'x1'.'aA' 'vA'", -1,
571 -1, UINT32_MAX, 0, 0, NULL,
572 },
573 {
574 SDB_CONNECTION_STORE, "\0\0\0\x11""\0\0\0\0\xd6\x93\xa4\0""x1\0aA\0"VALUE, 18+VALUE_LEN,
575 -1, UINT32_MAX, 0, 0, NULL,
576 },
577 {
578 SDB_CONNECTION_QUERY, "STORE service 'h1'.'sA'", -1,
579 0, SDB_CONNECTION_OK, 33, 0, "Successfully stored service h1.sA",
580 },
581 {
582 SDB_CONNECTION_STORE, "\0\0\0\2""\0\0\0\0\xd6\x93\xa4\0""h1\0sA", 18,
583 0, SDB_CONNECTION_OK, 33, 0, "Successfully stored service h1.sA",
584 },
585 {
586 SDB_CONNECTION_QUERY, "STORE service 'x1'.'sA'", -1,
587 -1, UINT32_MAX, 0, 0, NULL,
588 },
589 {
590 SDB_CONNECTION_STORE, "\0\0\0\x12""\0\0\0\0\xd6\x93\xa4\0""x1\0sA", 18,
591 -1, UINT32_MAX, 0, 0, NULL,
592 },
593 {
594 SDB_CONNECTION_QUERY, "STORE service attribute 'h2'.'s1'.'aA' 'vA'", -1,
595 0, SDB_CONNECTION_OK, 46, 0, "Successfully stored service attribute h2.s1.aA",
596 },
597 {
598 SDB_CONNECTION_STORE, "\0\0\0\x12""\0\0\0\0\xd6\x93\xa4\0""h2\0s1\0aA\0"VALUE,27+VALUE_LEN,
599 0, SDB_CONNECTION_OK, 46, 0, "Successfully stored service attribute h2.s1.aA",
600 },
601 {
602 SDB_CONNECTION_QUERY, "STORE service attribute 'h2'.'x1'.'aA' 'vA'", -1,
603 -1, UINT32_MAX, 0, 0, NULL,
604 },
605 {
606 SDB_CONNECTION_STORE, "\0\0\0\x12""\0\0\0\0\xd6\x93\xa4\0""h2\0x1\0aA\0"VALUE,27+VALUE_LEN,
607 -1, UINT32_MAX, 0, 0, NULL,
608 },
609 {
610 SDB_CONNECTION_QUERY, "STORE metric 'h1'.'mA'", -1,
611 0, SDB_CONNECTION_OK, 32, 0, "Successfully stored metric h1.mA",
612 },
613 {
614 SDB_CONNECTION_STORE, "\0\0\0\3""\0\0\0\0\xd6\x93\xa4\0""h1\0mA", 18,
615 0, SDB_CONNECTION_OK, 32, 0, "Successfully stored metric h1.mA",
616 },
617 {
618 SDB_CONNECTION_QUERY, "STORE metric 'x1'.'mA'", -1,
619 -1, UINT32_MAX, 0, 0, NULL,
620 },
621 {
622 SDB_CONNECTION_STORE, "\0\0\0\3""\0\0\0\0\xd6\x93\xa4\0""x1\0mA", 18,
623 -1, UINT32_MAX, 0, 0, NULL,
624 },
625 {
626 SDB_CONNECTION_QUERY, "STORE metric attribute 'h1'.'m1'.'aA' 'vA'", -1,
627 0, SDB_CONNECTION_OK, 45, 0, "Successfully stored metric attribute h1.m1.aA",
628 },
629 {
630 SDB_CONNECTION_STORE, "\0\0\0\x13""\0\0\0\0\xd6\x93\xa4\0""h1\0m1\0aA\0"VALUE, 27+VALUE_LEN,
631 0, SDB_CONNECTION_OK, 45, 0, "Successfully stored metric attribute h1.m1.aA",
632 },
633 {
634 SDB_CONNECTION_QUERY, "STORE metric attribute 'h1'.'x1'.'aA' 'vA'", -1,
635 -1, UINT32_MAX, 0, 0, NULL,
636 },
637 {
638 SDB_CONNECTION_STORE, "\0\0\0\x13""\0\0\0\0\xd6\x93\xa4\0""h1\0x1\0aA\0"VALUE, 27+VALUE_LEN,
639 -1, UINT32_MAX, 0, 0, NULL,
640 },
641 };
643 START_TEST(test_query)
644 {
645 sdb_conn_t *conn = mock_conn_create();
647 uint32_t code = UINT32_MAX, msg_len = UINT32_MAX;
648 const char *data;
649 ssize_t tmp;
650 size_t len;
651 int check;
653 conn->cmd = query_data[_i].cmd;
654 if (query_data[_i].query_len < 0)
655 conn->cmd_len = (uint32_t)strlen(query_data[_i].query);
656 else
657 conn->cmd_len = (uint32_t)query_data[_i].query_len;
658 sdb_strbuf_memcpy(conn->buf, query_data[_i].query, conn->cmd_len);
660 switch (conn->cmd) {
661 case SDB_CONNECTION_QUERY:
662 check = sdb_fe_query(conn);
663 break;
664 case SDB_CONNECTION_FETCH:
665 check = sdb_fe_fetch(conn);
666 break;
667 case SDB_CONNECTION_LIST:
668 check = sdb_fe_list(conn);
669 break;
670 case SDB_CONNECTION_LOOKUP:
671 check = sdb_fe_lookup(conn);
672 break;
673 /* SDB_CONNECTION_TIMESERIES not supported yet */
674 case SDB_CONNECTION_STORE:
675 check = sdb_fe_store(conn);
676 break;
677 default:
678 fail("Invalid command %#x", conn->cmd);
679 }
681 fail_unless(check == query_data[_i].expected,
682 "sdb_fe_query(%s) = %d; expected: %d (err: %s)",
683 query_data[_i].query, check, query_data[_i].expected,
684 sdb_strbuf_string(conn->errbuf));
686 data = sdb_strbuf_string(MOCK_CONN(conn)->write_buf);
687 len = sdb_strbuf_len(MOCK_CONN(conn)->write_buf);
689 if (query_data[_i].code == UINT32_MAX) {
690 fail_unless(len == 0,
691 "sdb_fe_query(%s) returned data on error: '%s'",
692 query_data[_i].query, data);
693 mock_conn_destroy(conn);
694 return;
695 }
697 tmp = sdb_proto_unmarshal_header(data, len, &code, &msg_len);
698 ck_assert_msg(tmp == (ssize_t)(2 * sizeof(uint32_t)));
699 data += tmp;
700 len -= tmp;
702 fail_unless((code == query_data[_i].code)
703 && ((size_t)msg_len == query_data[_i].len),
704 "sdb_fe_query(%s) returned %u, %u; expected: %u, %zu",
705 query_data[_i].query, code, msg_len,
706 query_data[_i].code, query_data[_i].len);
708 if (code == SDB_CONNECTION_DATA) {
709 tmp = sdb_proto_unmarshal_int32(data, len, &code);
710 fail_unless(code == query_data[_i].type,
711 "sdb_fe_query(%s) returned %s object; expected: %s",
712 query_data[_i].query, SDB_CONN_MSGTYPE_TO_STRING((int)code),
713 SDB_CONN_MSGTYPE_TO_STRING((int)query_data[_i].type));
714 data += tmp;
715 len -= tmp;
716 }
718 fail_if_strneq(data, query_data[_i].data, (size_t)msg_len,
719 "sdb_fe_query(%s) returned unexpected data",
720 query_data[_i].query, data, query_data[_i].data);
722 mock_conn_destroy(conn);
723 }
724 END_TEST
726 TEST_MAIN("frontend::query")
727 {
728 TCase *tc = tcase_create("core");
729 tcase_add_checked_fixture(tc, populate, sdb_store_clear);
730 TC_ADD_LOOP_TEST(tc, query);
731 ADD_TCASE(tc);
732 }
733 TEST_MAIN_END
735 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */