Code

frontend/query_test: Test various QUERY functions.
[sysdb.git] / t / unit / frontend / query_test.c
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)
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)
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)
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)
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, ...)
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)
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);
570 END_TEST
572 TEST_MAIN("frontend::query")
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);
579 TEST_MAIN_END
581 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */