04dfc8b9ee0b9b6e07b245de973c3a762aa04d92
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/store-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);
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);
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);
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);
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);
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);
134 ck_assert(status == 0);
135 }
136 } /* populate */
138 static void
139 turndown(void)
140 {
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)
557 {
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);
636 }
637 END_TEST
639 TEST_MAIN("core::store_expr")
640 {
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);
645 }
646 TEST_MAIN_END
648 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */