Code

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