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/parser.h"
34 #include "frontend/connection-private.h"
35 #include "testutils.h"
37 #include <check.h>
39 /*
40 * private helpers
41 */
43 static void
44 populate(void)
45 {
46 sdb_data_t datum;
48 sdb_store_host("h1", 1);
49 sdb_store_host("h2", 3);
51 datum.type = SDB_TYPE_STRING;
52 datum.data.string = "v1";
53 sdb_store_attribute("h1", "k1", &datum, 1);
54 datum.data.string = "v2";
55 sdb_store_attribute("h1", "k2", &datum, 2);
56 datum.data.string = "v3";
57 sdb_store_attribute("h1", "k3", &datum, 2);
59 sdb_store_metric("h1", "m1", /* store */ NULL, 2);
60 sdb_store_metric("h1", "m2", /* store */ NULL, 1);
61 sdb_store_metric("h2", "m1", /* store */ NULL, 1);
63 datum.type = SDB_TYPE_INTEGER;
64 datum.data.integer = 42;
65 sdb_store_metric_attr("h1", "m1", "k3", &datum, 2);
67 sdb_store_service("h2", "s1", 1);
68 sdb_store_service("h2", "s2", 2);
70 datum.data.integer = 123;
71 sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
72 datum.data.integer = 4711;
73 sdb_store_service_attr("h2", "s2", "k2", &datum, 1);
74 } /* populate */
76 #define HOST_H1 \
77 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
78 "\"update_interval\": \"0s\", \"backends\": [], " \
79 "\"attributes\": [" \
80 "{\"name\": \"k1\", \"value\": \"v1\", " \
81 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
82 "\"update_interval\": \"0s\", \"backends\": []}," \
83 "{\"name\": \"k2\", \"value\": \"v2\", " \
84 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
85 "\"update_interval\": \"0s\", \"backends\": []}," \
86 "{\"name\": \"k3\", \"value\": \"v3\", " \
87 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
88 "\"update_interval\": \"0s\", \"backends\": []}], " \
89 "\"metrics\": [" \
90 "{\"name\": \"m1\", \"timeseries\": false, " \
91 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
92 "\"update_interval\": \"0s\", \"backends\": [], " \
93 "\"attributes\": [" \
94 "{\"name\": \"k3\", \"value\": 42, " \
95 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
96 "\"update_interval\": \"0s\", \"backends\": []}]}," \
97 "{\"name\": \"m2\", \"timeseries\": false, " \
98 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
99 "\"update_interval\": \"0s\", \"backends\": []}]}"
100 #define HOST_H1_ARRAY "["HOST_H1"]"
101 #define HOST_H1_LISTING \
102 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
103 "\"update_interval\": \"0s\", \"backends\": []}"
104 #define HOST_H2_LISTING \
105 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
106 "\"update_interval\": \"0s\", \"backends\": []}"
108 #define SERVICE_H2_S1 \
109 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
110 "\"update_interval\": \"0s\", \"backends\": [], " \
111 "\"services\": [" \
112 "{\"name\": \"s1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
113 "\"update_interval\": \"0s\", \"backends\": []}]}"
114 #define SERVICE_H2_S1_ARRAY "["SERVICE_H2_S1"]"
115 #define SERVICE_H2_S12_LISTING \
116 "[{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
117 "\"update_interval\": \"0s\", \"backends\": [], " \
118 "\"services\": [" \
119 "{\"name\": \"s1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
120 "\"update_interval\": \"0s\", \"backends\": []}," \
121 "{\"name\": \"s2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
122 "\"update_interval\": \"0s\", \"backends\": []}]}]"
124 #define METRIC_H1_M1 \
125 "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
126 "\"update_interval\": \"0s\", \"backends\": [], " \
127 "\"metrics\": [" \
128 "{\"name\": \"m1\", \"timeseries\": false, " \
129 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
130 "\"update_interval\": \"0s\", \"backends\": [], " \
131 "\"attributes\": [" \
132 "{\"name\": \"k3\", \"value\": 42, " \
133 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
134 "\"update_interval\": \"0s\", \"backends\": []}]}]}"
135 #define METRIC_H12_M1_ARRAY \
136 "["METRIC_H1_M1"," \
137 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
138 "\"update_interval\": \"0s\", \"backends\": [], " \
139 "\"metrics\": [" \
140 "{\"name\": \"m1\", \"timeseries\": false, " \
141 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
142 "\"update_interval\": \"0s\", \"backends\": []}]}]"
143 #define METRIC_H12_M12_LISTING \
144 "[{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
145 "\"update_interval\": \"0s\", \"backends\": [], " \
146 "\"metrics\": [" \
147 "{\"name\": \"m1\", \"timeseries\": false, " \
148 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
149 "\"update_interval\": \"0s\", \"backends\": []}," \
150 "{\"name\": \"m2\", \"timeseries\": false, " \
151 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
152 "\"update_interval\": \"0s\", \"backends\": []}]}," \
153 "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " \
154 "\"update_interval\": \"0s\", \"backends\": [], " \
155 "\"metrics\": [" \
156 "{\"name\": \"m1\", \"timeseries\": false, " \
157 "\"last_update\": \"1970-01-01 00:00:00 +0000\", " \
158 "\"update_interval\": \"0s\", \"backends\": []}]}]"
160 typedef struct {
161 sdb_conn_t conn;
162 sdb_strbuf_t *write_buf;
163 } mock_conn_t;
164 #define MOCK_CONN(obj) ((mock_conn_t *)(obj))
165 #define CONN(obj) ((sdb_conn_t *)(obj))
167 static void
168 mock_conn_destroy(sdb_conn_t *conn)
169 {
170 sdb_strbuf_destroy(conn->buf);
171 sdb_strbuf_destroy(conn->errbuf);
172 sdb_strbuf_destroy(MOCK_CONN(conn)->write_buf);
173 free(conn);
174 } /* mock_conn_destroy */
176 static ssize_t
177 mock_conn_read(sdb_conn_t *conn, size_t len)
178 {
179 if (! conn)
180 return -1;
181 /* unused so far */
182 return len;
183 } /* conn_read */
185 static ssize_t
186 mock_conn_write(sdb_conn_t *conn, const void *buf, size_t len)
187 {
188 if (! conn)
189 return -1;
190 return sdb_strbuf_memappend(MOCK_CONN(conn)->write_buf, buf, len);
191 } /* conn_write */
193 static sdb_conn_t *
194 mock_conn_create(void)
195 {
196 mock_conn_t *conn;
198 conn = calloc(1, sizeof(*conn));
199 if (! conn) {
200 fail("INTERNAL ERROR: failed to allocate connection object");
201 return NULL;
202 }
204 SDB_OBJ(conn)->name = "mock_connection";
205 SDB_OBJ(conn)->ref_cnt = 1;
207 conn->conn.buf = sdb_strbuf_create(0);
208 conn->conn.errbuf = sdb_strbuf_create(0);
209 conn->write_buf = sdb_strbuf_create(64);
210 if ((! conn->conn.buf) || (! conn->conn.errbuf) || (! conn->write_buf)) {
211 mock_conn_destroy(CONN(conn));
212 fail("INTERNAL ERROR: failed to allocate connection object");
213 return NULL;
214 }
216 conn->conn.read = mock_conn_read;
217 conn->conn.write = mock_conn_write;
219 conn->conn.username = "mock_user";
220 conn->conn.cmd = SDB_CONNECTION_IDLE;
221 conn->conn.cmd_len = 0;
222 return CONN(conn);
223 } /* mock_conn_create */
225 /* TODO: move this into a test helper module */
226 static void
227 fail_if_strneq(const char *got, const char *expected, size_t n, const char *fmt, ...)
228 {
229 sdb_strbuf_t *buf;
230 va_list ap;
232 size_t len1 = strlen(got);
233 size_t len2 = strlen(expected);
235 size_t i;
236 int pos = -1;
238 if (n) {
239 len1 = SDB_MIN(len1, n);
240 len2 = SDB_MIN(len2, n);
241 }
243 if (len1 != len2)
244 pos = (int)SDB_MIN(len1, len2);
246 for (i = 0; i < SDB_MIN(len1, len2); ++i) {
247 if (got[i] != expected[i]) {
248 pos = (int)i;
249 break;
250 }
251 }
253 if (pos == -1)
254 return;
256 buf = sdb_strbuf_create(64);
257 va_start(ap, fmt);
258 sdb_strbuf_vsprintf(buf, fmt, ap);
260 fail("%s\n got: %s\n %*s\n expected: %s",
261 sdb_strbuf_string(buf), got, pos + 1, "^", expected);
262 } /* fail_if_strneq */
264 /*
265 * tests
266 */
268 static struct {
269 const char *query;
270 int expected;
271 uint32_t code;
272 size_t len;
273 uint32_t type;
274 const char *data;
275 } query_data[] = {
276 /* hosts */
277 {
278 "LIST hosts",
279 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST,
280 "["HOST_H1_LISTING","HOST_H2_LISTING"]",
281 },
282 {
283 "LIST hosts; LIST hosts", /* ignore second (and later) commands */
284 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST,
285 "["HOST_H1_LISTING","HOST_H2_LISTING"]",
286 },
287 {
288 "LIST hosts FILTER name = 'h1'",
289 0, SDB_CONNECTION_DATA, 105, SDB_CONNECTION_LIST, "["HOST_H1_LISTING"]",
290 },
291 {
292 "LIST hosts FILTER name = 's1'",
293 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]",
294 },
295 {
296 "FETCH host 'h1'",
297 0, SDB_CONNECTION_DATA, 851, SDB_CONNECTION_FETCH, HOST_H1,
298 },
299 {
300 "LOOKUP hosts MATCHING name = 'h1'",
301 0, SDB_CONNECTION_DATA, 853, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY,
302 },
303 {
304 "FETCH host 'h1' FILTER age >= 0s", /* always matches */
305 0, SDB_CONNECTION_DATA, 851, SDB_CONNECTION_FETCH, HOST_H1,
306 },
307 {
308 "LOOKUP hosts MATCHING name = 'h1' FILTER age >= 0s", /* always matches */
309 0, SDB_CONNECTION_DATA, 853, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY,
310 },
311 {
312 "FETCH host 'h1' FILTER age < 0s", /* never matches */
313 -1, UINT32_MAX, 0, 0, NULL, /* FETCH fails if the object doesn't exist */
314 },
315 {
316 "LOOKUP hosts MATCHING name = 'h1' FILTER age < 0s", /* never matches */
317 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
318 },
319 {
320 "FETCH host 'x1'", /* does not exist */
321 -1, UINT32_MAX, 0, 0, NULL,
322 },
323 {
324 "LOOKUP hosts MATCHING name = 'x1'", /* does not exist */
325 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
326 },
327 {
328 "FETCH host 'h1'.'s1'", /* invalid args */
329 -1, UINT32_MAX, 0, 0, NULL,
330 },
331 {
332 "LOOKUP hosts BY name = 'x1'", /* does not exist */
333 -1, UINT32_MAX, 0, 0, NULL,
334 },
335 /* services */
336 {
337 "LIST services",
338 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING,
339 },
340 {
341 "LIST services FILTER host.name = 'h2'",
342 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING,
343 },
344 {
345 "LIST services FILTER host.name = 'h1'",
346 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]",
347 },
348 {
349 "FETCH service 'h2'.'s1'",
350 0, SDB_CONNECTION_DATA, 218, SDB_CONNECTION_FETCH, SERVICE_H2_S1,
351 },
352 {
353 "LOOKUP services MATCHING name = 's1'",
354 0, SDB_CONNECTION_DATA, 220, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY,
355 },
356 {
357 "FETCH service 'h2'.'s1' FILTER age >= 0s", /* always matches */
358 0, SDB_CONNECTION_DATA, 218, SDB_CONNECTION_FETCH, SERVICE_H2_S1,
359 },
360 {
361 "LOOKUP services MATCHING name = 's1' FILTER age >= 0s", /* always matches */
362 0, SDB_CONNECTION_DATA, 220, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY,
363 },
364 {
365 "FETCH service 'h2'.'s1' FILTER age < 0s", /* never matches */
366 -1, UINT32_MAX, 0, 0, NULL,
367 },
368 {
369 "LOOKUP services MATCHING name = 's1' FILTER age < 0s", /* never matches */
370 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
371 },
372 {
373 "FETCH service 'h2'.'s1' FILTER name = 'h2'", /* only matches host */
374 -1, UINT32_MAX, 0, 0, NULL,
375 },
376 {
377 "LOOKUP services MATCHING name = 's1' FILTER name = 'h2'", /* only matches host */
378 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
379 },
380 {
381 "FETCH service 'h2'.'x1'", /* does not exist */
382 -1, UINT32_MAX, 0, 0, NULL,
383 },
384 {
385 "FETCH service 'x2'.'s1'", /* does not exist */
386 -1, UINT32_MAX, 0, 0, NULL,
387 },
388 {
389 "FETCH service 'h2'", /* invalid args */
390 -1, UINT32_MAX, 0, 0, NULL,
391 },
392 /* metrics */
393 {
394 "LIST metrics",
395 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING,
396 },
397 {
398 "LIST metrics FILTER age > 0s",
399 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING,
400 },
401 {
402 "LIST metrics FILTER age < 0s",
403 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]",
404 },
405 {
406 "FETCH metric 'h1'.'m1'",
407 0, SDB_CONNECTION_DATA, 368, SDB_CONNECTION_FETCH, METRIC_H1_M1,
408 },
409 {
410 "LOOKUP metrics MATCHING name = 'm1'",
411 0, SDB_CONNECTION_DATA, 605, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY,
412 },
413 {
414 "FETCH metric 'h1'.'m1' FILTER age >= 0s", /* always matches */
415 0, SDB_CONNECTION_DATA, 368, SDB_CONNECTION_FETCH, METRIC_H1_M1,
416 },
417 {
418 "LOOKUP metrics MATCHING name = 'm1' FILTER age >= 0s", /* always matches */
419 0, SDB_CONNECTION_DATA, 605, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY,
420 },
421 {
422 "FETCH metric 'h1'.'m1' FILTER age < 0s", /* never matches */
423 -1, UINT32_MAX, 0, 0, NULL,
424 },
425 {
426 "LOOKUP metrics MATCHING name = 'm1' FILTER age < 0s", /* never matches */
427 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
428 },
429 {
430 "FETCH metric 'h1'.'m1' FILTER name = 'h1'", /* only matches host */
431 -1, UINT32_MAX, 0, 0, NULL,
432 },
433 {
434 "LOOKUP metrics MATCHING name = 'm1' FILTER name = 'h1'", /* only matches host */
435 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]",
436 },
437 {
438 "FETCH metric 'h1'.'x1'", /* does not exist */
439 -1, UINT32_MAX, 0, 0, NULL,
440 },
441 {
442 "FETCH metric 'x1'.'m1'", /* does not exist */
443 -1, UINT32_MAX, 0, 0, NULL,
444 },
445 {
446 "FETCH metric 'x1'", /* invalid args */
447 -1, UINT32_MAX, 0, 0, NULL,
448 },
449 /* timeseries */
450 {
451 "TIMESERIES 'h1'.'m1'",
452 -1, UINT32_MAX, 0, 0, NULL, /* no data-store available */
453 },
454 {
455 "TIMESERIES 'h1'.'x1'",
456 -1, UINT32_MAX, 0, 0, NULL, /* does not exist */
457 },
458 {
459 "TIMESERIES 'x1'.'m1'",
460 -1, UINT32_MAX, 0, 0, NULL, /* does not exist */
461 },
462 /* store commands */
463 {
464 "STORE host 'hA' LAST UPDATE 01:00",
465 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA",
466 },
467 {
468 "STORE host 'hA'",
469 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA",
470 },
471 {
472 "STORE host attribute 'h1'.'aA' 'vA'",
473 0, SDB_CONNECTION_OK, 40, 0, "Successfully stored host attribute h1.aA",
474 },
475 {
476 "STORE host attribute 'x1'.'aA' 'vA'",
477 -1, UINT32_MAX, 0, 0, NULL,
478 },
479 {
480 "STORE service 'h1'.'sA'",
481 0, SDB_CONNECTION_OK, 33, 0, "Successfully stored service h1.sA",
482 },
483 {
484 "STORE service 'x1'.'sA'",
485 -1, UINT32_MAX, 0, 0, NULL,
486 },
487 {
488 "STORE service attribute 'h2'.'s1'.'aA' 'vA'",
489 0, SDB_CONNECTION_OK, 43, 0, "Successfully stored service attribute s1.aA",
490 },
491 {
492 "STORE service attribute 'h2'.'x1'.'aA' 'vA'",
493 -1, UINT32_MAX, 0, 0, NULL,
494 },
495 {
496 "STORE metric 'h1'.'mA'",
497 0, SDB_CONNECTION_OK, 32, 0, "Successfully stored metric h1.mA",
498 },
499 {
500 "STORE metric 'x1'.'mA'",
501 -1, UINT32_MAX, 0, 0, NULL,
502 },
503 {
504 "STORE metric attribute 'h1'.'m1'.'aA' 'vA'",
505 0, SDB_CONNECTION_OK, 42, 0, "Successfully stored metric attribute m1.aA",
506 },
507 {
508 "STORE metric attribute 'h1'.'x1'.'aA' 'vA'",
509 -1, UINT32_MAX, 0, 0, NULL,
510 },
511 };
513 START_TEST(test_query)
514 {
515 sdb_conn_t *conn = mock_conn_create();
517 uint32_t code = UINT32_MAX, msg_len = UINT32_MAX;
518 const char *data;
519 ssize_t tmp;
520 size_t len;
521 int check;
523 conn->cmd = SDB_CONNECTION_QUERY;
524 conn->cmd_len = (uint32_t)strlen(query_data[_i].query);
525 sdb_strbuf_memcpy(conn->buf, query_data[_i].query, conn->cmd_len);
527 check = sdb_fe_query(conn);
528 fail_unless(check == query_data[_i].expected,
529 "sdb_fe_query(%s) = %d; expected: %d",
530 query_data[_i].query, check, query_data[_i].expected);
532 data = sdb_strbuf_string(MOCK_CONN(conn)->write_buf);
533 len = sdb_strbuf_len(MOCK_CONN(conn)->write_buf);
535 if (query_data[_i].code == UINT32_MAX) {
536 fail_unless(len == 0,
537 "sdb_fe_query(%s) returned data on error: '%s'",
538 query_data[_i].query, data);
539 mock_conn_destroy(conn);
540 return;
541 }
543 tmp = sdb_proto_unmarshal_header(data, len, &code, &msg_len);
544 ck_assert_msg(tmp == (ssize_t)(2 * sizeof(uint32_t)));
545 data += tmp;
546 len -= tmp;
548 fail_unless((code == query_data[_i].code)
549 && ((size_t)msg_len == query_data[_i].len),
550 "sdb_fe_query(%s) returned %u, %u; expected: %u, %zu",
551 query_data[_i].query, code, msg_len,
552 query_data[_i].code, query_data[_i].len);
554 if (code == SDB_CONNECTION_DATA) {
555 tmp = sdb_proto_unmarshal_int32(data, len, &code);
556 fail_unless(code == query_data[_i].type,
557 "sdb_fe_query(%s) returned %s object; expected: %s",
558 query_data[_i].query, SDB_CONN_MSGTYPE_TO_STRING((int)code),
559 SDB_CONN_MSGTYPE_TO_STRING((int)query_data[_i].type));
560 data += tmp;
561 len -= tmp;
562 }
564 fail_if_strneq(data, query_data[_i].data, (size_t)msg_len,
565 "sdb_fe_query(%s) returned unexpected data",
566 query_data[_i].query, data, query_data[_i].data);
568 mock_conn_destroy(conn);
569 }
570 END_TEST
572 TEST_MAIN("frontend::query")
573 {
574 TCase *tc = tcase_create("core");
575 tcase_add_checked_fixture(tc, populate, sdb_store_clear);
576 TC_ADD_LOOP_TEST(tc, query);
577 ADD_TCASE(tc);
578 }
579 TEST_MAIN_END
581 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */