Code

d11452ae72dc072e0c5fac7330fd4b29b18e4969
[sysdb.git] / t / unit / core / store_expr_test.c
1 /*
2  * SysDB - t/unit/core/store_expr_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 "core/plugin.h"
33 #include "core/store.h"
34 #include "core/store-private.h"
35 #include "parser/parser.h"
36 #include "testutils.h"
38 #include <check.h>
40 static sdb_store_t *store;
42 static void
43 populate(void)
44 {
45         const char *hosts[] = { "a", "b", "c" };
47         struct {
48                 const char *host;
49                 const char *metric;
50         } metrics[] = {
51                 { "a", "m1" },
52                 { "b", "m1" },
53                 { "b", "m2" },
54         };
56         struct {
57                 const char *host;
58                 const char *service;
59         } services[] = {
60                 { "a", "s1" },
61                 { "a", "s2" },
62                 { "b", "s1" },
63                 { "b", "s3" },
64         };
66         struct {
67                 const char *host;
68                 const char *name;
69                 sdb_data_t  value;
70         } attrs[] = {
71                 { "a", "k1", { SDB_TYPE_STRING, { .string = "v1" } } },
72                 { "a", "k2", { SDB_TYPE_INTEGER, { .integer = 123 } } },
73                 { "b", "k1", { SDB_TYPE_STRING, { .string = "v2" } } },
74         };
76         struct {
77                 const char *host;
78                 const char *service;
79                 const char *name;
80                 sdb_data_t  value;
81         } svc_attrs[] = {
82                 { "a", "s1", "k1", { SDB_TYPE_STRING, { .string = "v1" } } },
83                 { "a", "s2", "k2", { SDB_TYPE_INTEGER, { .integer = 123 } } },
84         };
86         struct {
87                 const char *host;
88                 const char *metric;
89                 const char *name;
90                 sdb_data_t  value;
91         } metric_attrs[] = {
92                 { "b", "m2", "k1", { SDB_TYPE_STRING, { .string = "v1" } } },
93                 { "b", "m2", "k2", { SDB_TYPE_INTEGER, { .integer = 123 } } },
94         };
96         size_t i;
98         store = sdb_store_create();
99         ck_assert(store != NULL);
101         for (i = 0; i < SDB_STATIC_ARRAY_LEN(hosts); ++i) {
102                 int status = sdb_store_host(store, hosts[i], 1);
103                 ck_assert(status == 0);
104         }
106         for (i = 0; i < SDB_STATIC_ARRAY_LEN(metrics); ++i) {
107                 int status = sdb_store_metric(store, metrics[i].host,
108                                 metrics[i].metric, /* store */ NULL, 1);
109                 ck_assert(status == 0);
110         }
112         for (i = 0; i < SDB_STATIC_ARRAY_LEN(services); ++i) {
113                 int status = sdb_store_service(store, services[i].host,
114                                 services[i].service, 1);
115                 ck_assert(status == 0);
116         }
118         for (i = 0; i < SDB_STATIC_ARRAY_LEN(attrs); ++i) {
119                 int status = sdb_store_attribute(store, attrs[i].host,
120                                 attrs[i].name, &attrs[i].value, 1);
121                 ck_assert(status == 0);
122         }
124         for (i = 0; i < SDB_STATIC_ARRAY_LEN(svc_attrs); ++i) {
125                 int status = sdb_store_service_attr(store, svc_attrs[i].host,
126                                 svc_attrs[i].service, svc_attrs[i].name,
127                                 &svc_attrs[i].value, 1);
128                 ck_assert(status == 0);
129         }
131         for (i = 0; i < SDB_STATIC_ARRAY_LEN(metric_attrs); ++i) {
132                 int status = sdb_store_metric_attr(store, metric_attrs[i].host,
133                                 metric_attrs[i].metric, metric_attrs[i].name,
134                                 &metric_attrs[i].value, 1);
135                 ck_assert(status == 0);
136         }
137 } /* populate */
139 static void
140 turndown(void)
142         sdb_object_deref(SDB_OBJ(store));
143         store = NULL;
144 } /* turndown */
146 #define NAME { SDB_TYPE_INTEGER, { .integer = SDB_FIELD_NAME } }
147 #define LAST_UPDATE { SDB_TYPE_INTEGER, { .integer = SDB_FIELD_LAST_UPDATE } }
148 #define AGE { SDB_TYPE_INTEGER, { .integer = SDB_FIELD_AGE } }
149 #define INTERVAL { SDB_TYPE_INTEGER, { .integer = SDB_FIELD_INTERVAL } }
150 #define BACKENDS { SDB_TYPE_INTEGER, { .integer = SDB_FIELD_BACKEND } }
151 #define HOSTS { SDB_TYPE_INTEGER, { .integer = SDB_HOST } }
152 #define SERVICES { SDB_TYPE_INTEGER, { .integer = SDB_SERVICE } }
153 #define METRICS { SDB_TYPE_INTEGER, { .integer = SDB_METRIC } }
154 #define ATTRS { SDB_TYPE_INTEGER, { .integer = SDB_ATTRIBUTE } }
155 static sdb_store_expr_t namer = {
156         SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, NAME,
157 };
158 static int64_t int_values[] = { 1, 2, 3, 4, 5 };
159 static double dec_values[] = { 47.0, 11.0, 32.0, 64.0 };
160 static char *str_values[] = { "foo", "bar", "qux" };
161 static sdb_time_t dt_values[] = { 4711L, 1234567890L };
162 static struct {
163         size_t length;
164         unsigned char *datum;
165 } bin_values[] = { { 4, (unsigned char *)"\3\2\0\1" } };
166 struct {
167         sdb_store_expr_t expr;
168         bool iterable;
170         char *host;
171         int child_type;
172         char *child;  /* optional */
173         char *filter; /* optional */
175         sdb_data_t expected[5];
176         size_t expected_len;
177 } expr_iter_data[] = {
178         /* iterate host children */
179         {
180                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, SERVICES }, true,
181                 "a", -1, NULL, NULL,
182                 {
183                         { SDB_TYPE_STRING, { .string = "s1" } },
184                         { SDB_TYPE_STRING, { .string = "s2" } },
185                         { 0 },
186                         { 0 },
187                         { 0 },
188                 }, 2,
189         },
190         {
191                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, SERVICES }, true,
192                 "b", -1, NULL, NULL,
193                 {
194                         { SDB_TYPE_STRING, { .string = "s1" } },
195                         { SDB_TYPE_STRING, { .string = "s3" } },
196                         { 0 },
197                         { 0 },
198                         { 0 },
199                 }, 2,
200         },
201         {
202                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, SERVICES }, true,
203                 "a", -1, NULL, "name = 'a' OR name = 's1'",
204                 {
205                         { SDB_TYPE_STRING, { .string = "s1" } },
206                         { 0 },
207                         { 0 },
208                         { 0 },
209                         { 0 },
210                 }, 1,
211         },
212         {
213                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, SERVICES }, true,
214                 "a", -1, NULL, "name = 'a' OR name = 's2'",
215                 {
216                         { SDB_TYPE_STRING, { .string = "s2" } },
217                         { 0 },
218                         { 0 },
219                         { 0 },
220                         { 0 },
221                 }, 1,
222         },
223         {
224                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, SERVICES }, true,
225                 "a", -1, NULL, "name = 'a'",
226                 {
227                         { 0 },
228                         { 0 },
229                         { 0 },
230                         { 0 },
231                         { 0 },
232                 }, 0,
233         },
234         {
235                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, METRICS }, true,
236                 "a", -1, NULL, NULL,
237                 {
238                         { SDB_TYPE_STRING, { .string = "m1" } },
239                         { 0 },
240                         { 0 },
241                         { 0 },
242                         { 0 },
243                 }, 1,
244         },
245         {
246                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, METRICS }, true,
247                 "a", -1, NULL, "name = 'a' OR name = 'm1'",
248                 {
249                         { SDB_TYPE_STRING, { .string = "m1" } },
250                         { 0 },
251                         { 0 },
252                         { 0 },
253                         { 0 },
254                 }, 1,
255         },
256         {
257                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, METRICS }, true,
258                 "a", -1, NULL, "name = 'a' OR name = 'm2'",
259                 {
260                         { 0 },
261                         { 0 },
262                         { 0 },
263                         { 0 },
264                         { 0 },
265                 }, 0,
266         },
267         {
268                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, METRICS }, true,
269                 "a", -1, NULL, "name = 'a'",
270                 {
271                         { 0 },
272                         { 0 },
273                         { 0 },
274                         { 0 },
275                         { 0 },
276                 }, 0,
277         },
278         {
279                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
280                 "a", -1, NULL, NULL,
281                 {
282                         { SDB_TYPE_STRING, { .string = "k1" } },
283                         { SDB_TYPE_STRING, { .string = "k2" } },
284                         { 0 },
285                         { 0 },
286                         { 0 },
287                 }, 2,
288         },
289         {
290                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, HOSTS }, false,
291                 "a", -1, NULL, NULL,
292                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
293         },
294         /* host fields */
295         {
296                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, BACKENDS }, true,
297                 "a", -1, NULL, NULL,
298                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
299         },
300         {
301                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, NAME }, false,
302                 "a", -1, NULL, NULL,
303                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
304         },
305         {
306                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, LAST_UPDATE }, false,
307                 "a", -1, NULL, NULL,
308                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
309         },
310         {
311                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, AGE }, false,
312                 "a", -1, NULL, NULL,
313                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
314         },
315         {
316                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, INTERVAL }, false,
317                 "a", -1, NULL, NULL,
318                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
319         },
320         /* service children */
321         {
322                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
323                 "a", SDB_SERVICE, "s1", NULL,
324                 {
325                         { SDB_TYPE_STRING, { .string = "hostname" } },
326                         { SDB_TYPE_STRING, { .string = "k1" } },
327                         { 0 },
328                         { 0 },
329                         { 0 },
330                 }, 2,
331         },
332         {
333                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
334                 "a", SDB_SERVICE, "s1", "age >= 0s",
335                 {
336                         { SDB_TYPE_STRING, { .string = "hostname" } },
337                         { SDB_TYPE_STRING, { .string = "k1" } },
338                         { 0 },
339                         { 0 },
340                         { 0 },
341                 }, 2,
342         },
343         {
344                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
345                 "a", SDB_SERVICE, "s1", "age < 0s",
346                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
347         },
348         {
349                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, HOSTS }, false,
350                 "a", SDB_SERVICE, "s1", NULL,
351                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
352         },
353         {
354                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, SERVICES }, false,
355                 "a", SDB_SERVICE, "s1", NULL,
356                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
357         },
358         {
359                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, METRICS }, false,
360                 "a", SDB_SERVICE, "s1", NULL,
361                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
362         },
363         /* service fields */
364         {
365                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, BACKENDS }, true,
366                 "a", SDB_SERVICE, "s1", NULL,
367                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
368         },
369         {
370                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, NAME }, false,
371                 "a", SDB_SERVICE, "s1", NULL,
372                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
373         },
374         {
375                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, LAST_UPDATE }, false,
376                 "a", SDB_SERVICE, "s1", NULL,
377                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
378         },
379         {
380                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, AGE }, false,
381                 "a", SDB_SERVICE, "s1", NULL,
382                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
383         },
384         {
385                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, INTERVAL }, false,
386                 "a", SDB_SERVICE, "s1", NULL,
387                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
388         },
389         /* metric children */
390         {
391                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
392                 "b", SDB_METRIC, "m2", NULL,
393                 {
394                         { SDB_TYPE_STRING, { .string = "hostname" } },
395                         { SDB_TYPE_STRING, { .string = "k1" } },
396                         { SDB_TYPE_STRING, { .string = "k2" } },
397                         { 0 },
398                         { 0 },
399                 }, 3,
400         },
401         {
402                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
403                 "b", SDB_METRIC, "m2", "age >= 0s",
404                 {
405                         { SDB_TYPE_STRING, { .string = "hostname" } },
406                         { SDB_TYPE_STRING, { .string = "k1" } },
407                         { SDB_TYPE_STRING, { .string = "k2" } },
408                         { 0 },
409                         { 0 },
410                 }, 3,
411         },
412         {
413                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
414                 "b", SDB_METRIC, "m2", "name = 'b' OR name = 'm2' OR name = 'k2'",
415                 {
416                         { SDB_TYPE_STRING, { .string = "k2" } },
417                         { 0 },
418                         { 0 },
419                         { 0 },
420                         { 0 },
421                 }, 1,
422         },
423         {
424                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, ATTRS }, true,
425                 "b", SDB_METRIC, "m2", "age < 0s",
426                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
427         },
428         {
429                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, HOSTS }, false,
430                 "b", SDB_METRIC, "m2", NULL,
431                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
432         },
433         {
434                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, SERVICES }, false,
435                 "b", SDB_METRIC, "m2", NULL,
436                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
437         },
438         {
439                 { SDB_OBJECT_INIT, TYPED_EXPR, -1, &namer, NULL, METRICS }, false,
440                 "b", SDB_METRIC, "m2", NULL,
441                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } }, 0,
442         },
443         /* metric fields */
444         {
445                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, BACKENDS }, true,
446                 "b", SDB_METRIC, "m2", NULL,
447                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
448         },
449         {
450                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, NAME }, false,
451                 "b", SDB_METRIC, "m2", NULL,
452                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
453         },
454         {
455                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, LAST_UPDATE }, false,
456                 "b", SDB_METRIC, "m2", NULL,
457                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
458         },
459         {
460                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, AGE }, false,
461                 "b", SDB_METRIC, "m2", NULL,
462                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
463         },
464         {
465                 { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, INTERVAL }, false,
466                 "b", SDB_METRIC, "m2", NULL,
467                 { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, }, 0,
468         },
469         /* arrays */
470         {
471                 {
472                         SDB_OBJECT_INIT, 0, -1, NULL, NULL,
473                         {
474                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
475                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
476                         },
477                 }, true,
478                 NULL, -1, NULL, NULL,
479                 {
480                         { SDB_TYPE_INTEGER, { .integer = 1 } },
481                         { SDB_TYPE_INTEGER, { .integer = 2 } },
482                         { SDB_TYPE_INTEGER, { .integer = 3 } },
483                         { SDB_TYPE_INTEGER, { .integer = 4 } },
484                         { SDB_TYPE_INTEGER, { .integer = 5 } },
485                 }, 5,
486         },
487         {
488                 {
489                         SDB_OBJECT_INIT, 0, -1, NULL, NULL,
490                         {
491                                 SDB_TYPE_DECIMAL | SDB_TYPE_ARRAY,
492                                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } },
493                         },
494                 }, true,
495                 NULL, -1, NULL, NULL,
496                 {
497                         { SDB_TYPE_DECIMAL, { .decimal = 47.0 } },
498                         { SDB_TYPE_DECIMAL, { .decimal = 11.0 } },
499                         { SDB_TYPE_DECIMAL, { .decimal = 32.0 } },
500                         { SDB_TYPE_DECIMAL, { .decimal = 64.0 } },
501                         { 0 },
502                 }, 4,
503         },
504         {
505                 {
506                         SDB_OBJECT_INIT, 0, -1, NULL, NULL,
507                         {
508                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
509                                 { .array = { SDB_STATIC_ARRAY_LEN(str_values), str_values } },
510                         },
511                 }, true,
512                 NULL, -1, NULL, NULL,
513                 {
514                         { SDB_TYPE_STRING, { .string = "foo" } },
515                         { SDB_TYPE_STRING, { .string = "bar" } },
516                         { SDB_TYPE_STRING, { .string = "qux" } },
517                         { 0 },
518                         { 0 },
519                 }, 3,
520         },
521         {
522                 {
523                         SDB_OBJECT_INIT, 0, -1, NULL, NULL,
524                         {
525                                 SDB_TYPE_DATETIME | SDB_TYPE_ARRAY,
526                                 { .array = { SDB_STATIC_ARRAY_LEN(dt_values), dt_values } },
527                         },
528                 }, true,
529                 NULL, -1, NULL, NULL,
530                 {
531                         { SDB_TYPE_DATETIME, { .datetime = 4711L } },
532                         { SDB_TYPE_DATETIME, { .datetime = 1234567890L } },
533                         { 0 },
534                         { 0 },
535                         { 0 },
536                 }, 2,
537         },
538         {
539                 {
540                         SDB_OBJECT_INIT, 0, -1, NULL, NULL,
541                         {
542                                 SDB_TYPE_BINARY  | SDB_TYPE_ARRAY,
543                                 { .array = { SDB_STATIC_ARRAY_LEN(bin_values), bin_values } },
544                         },
545                 }, true,
546                 NULL, -1, NULL, NULL,
547                 {
548                         { SDB_TYPE_BINARY, { .binary = { 4, (unsigned char *)"\3\2\0\1" } } },
549                         { 0 },
550                         { 0 },
551                         { 0 },
552                         { 0 },
553                 }, 1,
554         },
555 };
557 START_TEST(test_expr_iter)
559         sdb_store_obj_t *obj = NULL;
560         sdb_store_matcher_t *filter = NULL;
561         int context = SDB_HOST;
563         sdb_store_expr_iter_t *iter;
564         size_t i;
566         if (expr_iter_data[_i].host) {
567                 obj = sdb_store_get_host(store, expr_iter_data[_i].host);
568                 ck_assert(obj != NULL);
570                 if (expr_iter_data[_i].child) {
571                         sdb_store_obj_t *child = sdb_store_get_child(obj,
572                                         expr_iter_data[_i].child_type, expr_iter_data[_i].child);
573                         ck_assert(child != NULL);
574                         sdb_object_deref(SDB_OBJ(obj));
575                         obj = child;
576                         context = expr_iter_data[_i].child_type;
577                 }
578                 ck_assert(obj->type == context);
579         }
581         if (expr_iter_data[_i].filter) {
582                 sdb_ast_node_t *ast;
583                 ast = sdb_parser_parse_conditional(context, expr_iter_data[_i].filter, -1, NULL);
584                 filter = sdb_store_query_prepare_matcher(ast);
585                 sdb_object_deref(SDB_OBJ(ast));
586                 ck_assert(filter != NULL);
587         }
589         iter = sdb_store_expr_iter(&expr_iter_data[_i].expr, obj, filter);
590         fail_unless((iter != NULL) == expr_iter_data[_i].iterable,
591                         "sdb_store_expr_iter(%s expression, %s, %s) = %s; expected: %s",
592                         EXPR_TO_STRING(&expr_iter_data[_i].expr),
593                         obj ? SDB_STORE_TYPE_TO_NAME(obj->type) : "<array>",
594                         expr_iter_data[_i].filter, iter ? "<iter>" : "NULL",
595                         expr_iter_data[_i].iterable ? "<iter>" : "NULL");
597         /* the iterator will keep a reference */
598         sdb_object_deref(SDB_OBJ(obj)); obj = NULL;
599         sdb_object_deref(SDB_OBJ(filter)); filter = NULL;
601         i = 0;
602         while (sdb_store_expr_iter_has_next(iter)) {
603                 char v_str[64], expected_str[64];
604                 sdb_data_t v;
606                 fail_unless(i < expr_iter_data[_i].expected_len,
607                                 "iter<%s expression, %s, %s> returned >= %zu elements; "
608                                 "expected: %zu", EXPR_TO_STRING(&expr_iter_data[_i].expr),
609                                 SDB_STORE_TYPE_TO_NAME(context), expr_iter_data[_i].filter,
610                                 i + 1, expr_iter_data[_i].expected_len);
612                 v = sdb_store_expr_iter_get_next(iter);
613                 sdb_data_format(&v, v_str, sizeof(v_str), SDB_DOUBLE_QUOTED);
614                 sdb_data_format(&expr_iter_data[_i].expected[i],
615                                 expected_str, sizeof(expected_str), SDB_DOUBLE_QUOTED);
616                 fail_unless(sdb_data_cmp(&v, &expr_iter_data[_i].expected[i]) == 0,
617                                 "iter<%s expression, %s, %s>, elem %zu = %s; expected: %s",
618                                 EXPR_TO_STRING(&expr_iter_data[_i].expr),
619                                 SDB_STORE_TYPE_TO_NAME(context), expr_iter_data[_i].filter,
620                                 i, v_str, expected_str);
622                 sdb_data_free_datum(&v);
623                 ++i;
624         }
626         fail_unless(i == expr_iter_data[_i].expected_len,
627                         "iter<%s expression, %s, %s> returned %zu elements; "
628                         "expected: %zu", EXPR_TO_STRING(&expr_iter_data[_i].expr),
629                         SDB_STORE_TYPE_TO_NAME(context), expr_iter_data[_i].filter,
630                         i, expr_iter_data[_i].expected_len);
631         fail_unless(sdb_store_expr_iter_get_next(iter).type == SDB_TYPE_NULL,
632                         "iter<%s expression, %s, %s> returned further elements "
633                         "passed the end", EXPR_TO_STRING(&expr_iter_data[_i].expr),
634                         SDB_STORE_TYPE_TO_NAME(context), expr_iter_data[_i].filter);
636         sdb_store_expr_iter_destroy(iter);
638 END_TEST
640 TEST_MAIN("core::store_expr")
642         TCase *tc = tcase_create("core");
643         tcase_add_checked_fixture(tc, populate, turndown);
644         TC_ADD_LOOP_TEST(tc, expr_iter);
645         ADD_TCASE(tc);
647 TEST_MAIN_END
649 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */