Code

data: Add basic support for a boolean type.
[sysdb.git] / t / unit / core / data_test.c
1 /*
2  * SysDB - t/unit/core/data_test.c
3  * Copyright (C) 2014 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/data.h"
33 #include "testutils.h"
35 #include <assert.h>
36 #include <check.h>
38 static regex_t empty_re;
40 START_TEST(test_data)
41 {
42         sdb_data_t d1, d2;
43         int check;
45         bool bool_values[] = { true, false, false, true };
46         int64_t int_values[] = { 47, 11, 23 };
47         char *string_values[] = { "foo", "bar", "qux" "baz" };
48         size_t i;
50         d2.type = SDB_TYPE_BOOLEAN;
51         d2.data.boolean = true;
52         memset(&d1, 0, sizeof(d1));
53         check = sdb_data_copy(&d1, &d2);
54         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
55         fail_unless(d1.type == d2.type,
56                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
57                         d1.type, d2.type);
58         fail_unless(d1.data.boolean == d2.data.boolean,
59                         "sdb_data_copy() didn't copy boolean data: got: %d; expected: %d",
60                         d1.data.boolean, d2.data.boolean);
62         d2.type = SDB_TYPE_INTEGER;
63         d2.data.integer = 4711;
64         memset(&d1, 0, sizeof(d1));
65         check = sdb_data_copy(&d1, &d2);
66         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
67         fail_unless(d1.type == d2.type,
68                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
69                         d1.type, d2.type);
70         fail_unless(d1.data.integer == d2.data.integer,
71                         "sdb_data_copy() didn't copy integer data: got: %d; expected: %d",
72                         d1.data.integer, d2.data.integer);
74         d2.type = SDB_TYPE_DECIMAL;
75         d2.data.decimal = 47.11;
76         check = sdb_data_copy(&d1, &d2);
77         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
78         fail_unless(d1.type == d2.type,
79                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
80                         d1.type, d2.type);
81         fail_unless(d1.data.decimal == d2.data.decimal,
82                         "sdb_data_copy() didn't copy decimal data: got: %f; expected: %f",
83                         d1.data.decimal, d2.data.decimal);
85         d2.type = SDB_TYPE_STRING;
86         d2.data.string = "some string";
87         check = sdb_data_copy(&d1, &d2);
88         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
89         fail_unless(d1.type == d2.type,
90                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
91                         d1.type, d2.type);
92         fail_unless(!strcmp(d1.data.string, d2.data.string),
93                         "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
94                         d1.data.string, d2.data.string);
96         sdb_data_free_datum(&d1);
97         fail_unless(d1.data.string == NULL,
98                         "sdb_data_free_datum() didn't free string data");
100         d1.type = 0;
101         d2.type = SDB_TYPE_STRING;
102         d2.data.string = NULL;
103         check = sdb_data_copy(&d1, &d2);
104         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
105         fail_unless(d1.type == d2.type,
106                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
107                         d1.type, d2.type);
108         fail_unless(d1.data.string == d2.data.string,
109                         "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
110                         d1.data.string, d2.data.string);
112         sdb_data_free_datum(&d1);
113         fail_unless(d1.data.string == NULL,
114                         "sdb_data_free_datum() didn't free string data");
116         d2.type = SDB_TYPE_DATETIME;
117         d2.data.datetime = 4711;
118         check = sdb_data_copy(&d1, &d2);
119         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
120         fail_unless(d1.type == d2.type,
121                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
122                         d1.type, d2.type);
123         fail_unless(d1.data.datetime == d2.data.datetime,
124                         "sdb_data_copy() didn't copy datetime data: got: %d; expected: %d",
125                         d1.data.datetime, d2.data.datetime);
127         d2.type = SDB_TYPE_BINARY;
128         d2.data.binary.datum = (unsigned char *)"some string";
129         d2.data.binary.length = strlen((const char *)d2.data.binary.datum);
130         check = sdb_data_copy(&d1, &d2);
131         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
132         fail_unless(d1.type == d2.type,
133                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
134                         d1.type, d2.type);
135         fail_unless(d1.data.binary.length == d2.data.binary.length,
136                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
137                         d1.data.binary.length, d2.data.binary.length);
138         fail_unless(!memcmp(d1.data.binary.datum, d2.data.binary.datum,
139                                 d2.data.binary.length),
140                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
141                         d1.data.binary.datum, d2.data.binary.datum);
143         sdb_data_free_datum(&d1);
144         fail_unless(d1.data.binary.length == 0,
145                         "sdb_data_free_datum() didn't reset binary datum length");
146         fail_unless(d1.data.binary.datum == NULL,
147                         "sdb_data_free_datum() didn't free binary datum");
149         d1.type = 0;
150         d2.type = SDB_TYPE_BINARY;
151         d2.data.binary.datum = NULL;
152         d2.data.binary.length = 0;
153         check = sdb_data_copy(&d1, &d2);
154         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
155         fail_unless(d1.type == d2.type,
156                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
157                         d1.type, d2.type);
158         fail_unless(d1.data.binary.length == d2.data.binary.length,
159                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
160                         d1.data.binary.length, d2.data.binary.length);
161         fail_unless(d1.data.binary.datum == d2.data.binary.datum,
162                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
163                         d1.data.binary.datum, d2.data.binary.datum);
165         sdb_data_free_datum(&d1);
166         fail_unless(d1.data.binary.length == 0,
167                         "sdb_data_free_datum() didn't reset binary datum length");
168         fail_unless(d1.data.binary.datum == NULL,
169                         "sdb_data_free_datum() didn't free binary datum");
171         check = sdb_data_parse(".", SDB_TYPE_REGEX, &d2);
172         fail_unless(check == 0,
173                         "INTERNAL ERROR: Failed to parse regex '.'");
174         assert(d2.type == SDB_TYPE_REGEX);
175         check = sdb_data_copy(&d1, &d2);
176         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
177         fail_unless(d1.type == d2.type,
178                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
179                         d1.type, d2.type);
180         fail_unless(d1.data.re.raw != d2.data.re.raw,
181                         "sdb_data_copy() copy string pointer");
182         fail_unless(!strcmp(d1.data.re.raw, d2.data.re.raw),
183                         "sdb_data_copy() didn't copy raw regex: got: %s; expected: %s",
184                         d1.data.re.raw, d2.data.re.raw);
185         sdb_data_free_datum(&d2);
187         sdb_data_free_datum(&d1);
188         fail_unless(d1.data.re.raw == NULL,
189                         "sdb_data_free_datum() didn't reset raw regex");
191         d2.type = SDB_TYPE_REGEX;
192         d2.data.re.raw = NULL;
193         check = sdb_data_copy(&d1, &d2);
194         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
195         fail_unless(d1.type == d2.type,
196                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
197                         d1.type, d2.type);
199         d2.type = SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN;
200         d2.data.array.length = SDB_STATIC_ARRAY_LEN(bool_values);
201         d2.data.array.values = bool_values;
202         check = sdb_data_copy(&d1, &d2);
203         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
204         fail_unless(d1.type == d2.type,
205                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
206                         d1.type, d2.type);
207         fail_unless(d1.data.array.values != d2.data.array.values,
208                         "sdb_data_copy() didn't copy values: got: %p; expected: %p",
209                         d1.data.array.values, d2.data.array.values);
210         for (i = 0; i < SDB_STATIC_ARRAY_LEN(bool_values); ++i) {
211                 bool *b1 = d1.data.array.values;
212                 bool *b2 = d2.data.array.values;
213                 fail_unless(b1[i] == b2[i],
214                                 "sdb_data_copy() modified boolean value %d: "
215                                 "got: %d; expected: %d", i, b1[i], b2[i]);
216         }
217         sdb_data_free_datum(&d1);
219         d2.type = SDB_TYPE_ARRAY | SDB_TYPE_INTEGER;
220         d2.data.array.length = SDB_STATIC_ARRAY_LEN(int_values);
221         d2.data.array.values = int_values;
222         check = sdb_data_copy(&d1, &d2);
223         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
224         fail_unless(d1.type == d2.type,
225                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
226                         d1.type, d2.type);
227         fail_unless(d1.data.array.values != d2.data.array.values,
228                         "sdb_data_copy() didn't copy values: got: %p; expected: %p",
229                         d1.data.array.values, d2.data.array.values);
230         for (i = 0; i < SDB_STATIC_ARRAY_LEN(int_values); ++i) {
231                 int *i1 = d1.data.array.values;
232                 int *i2 = d2.data.array.values;
233                 fail_unless(i1[i] == i2[i],
234                                 "sdb_data_copy() modified integer value %d: "
235                                 "got: %d; expected: %d", i, i1[i], i2[i]);
236         }
237         sdb_data_free_datum(&d1);
239         d2.type = SDB_TYPE_ARRAY | SDB_TYPE_STRING;
240         d2.data.array.length = SDB_STATIC_ARRAY_LEN(string_values);
241         d2.data.array.values = string_values;
242         check = sdb_data_copy(&d1, &d2);
243         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
244         fail_unless(d1.type == d2.type,
245                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
246                         d1.type, d2.type);
247         fail_unless(d1.data.array.values != d2.data.array.values,
248                         "sdb_data_copy() didn't copy values: got: %p; expected: %p",
249                         d1.data.array.values, d2.data.array.values);
250         for (i = 0; i < SDB_STATIC_ARRAY_LEN(string_values); ++i) {
251                 char **s1 = d1.data.array.values;
252                 char **s2 = d2.data.array.values;
253                 fail_unless(s1[i] != s2[i],
254                                 "sdb_data_copy() didn't copy string value %d", i);
255                 fail_unless(!strcmp(s1[i], s2[i]),
256                                 "sdb_data_copy() modified string value %d: "
257                                 "got: %s; expected: %s", i, s1[i], s2[i]);
258         }
259         sdb_data_free_datum(&d1);
261 END_TEST
263 START_TEST(test_cmp)
265         regex_t dummy_re;
266         bool bool_values1[] = { true, false, false, true };
267         bool bool_values2[] = { true, false, true, false };
268         int64_t int_values1[] = { 1, 2, 3 };
269         int64_t int_values2[] = { 1, 3, 2 };
270         double dec_values1[] = { 12.34, 47.11 };
271         double dec_values2[] = { 47.11, 12.34 };
272         char *string_values1[] = { "a", "b", "c" };
273         char *string_values2[] = { "a", "c", "b" };
274         sdb_time_t dt_values1[] = { 4711, 1234567890123456789L };
275         sdb_time_t dt_values2[] = { 1234567890123456789L, 4711 };
276         struct {
277                 size_t length;
278                 unsigned char *datum;
279         } bin_values1[] = {
280                 { 3, (unsigned char *)"\x1\x2\x3" },
281                 { 4, (unsigned char *)"\x42\x0\xa\x1b" },
282         };
283         struct {
284                 size_t length;
285                 unsigned char *datum;
286         } bin_values2[] = {
287                 { 4, (unsigned char *)"\x42\x0\xa\x1b" },
288                 { 3, (unsigned char *)"\x1\x2\x3" },
289         };
290         struct {
291                 char *raw;
292                 regex_t regex;
293         } re_values1[] = {
294                 { "dummy regex A", dummy_re },
295         };
296         struct {
297                 char *raw;
298                 regex_t regex;
299         } re_values2[] = {
300                 { "dummy regex B", dummy_re },
301         };
303         struct {
304                 sdb_data_t d1;
305                 sdb_data_t d2;
306                 int expected;
307         } golden_data[] = {
308                 {
309                         { SDB_TYPE_BOOLEAN, { .boolean = false } },
310                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
311                         -1,
312                 },
313                 {
314                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
315                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
316                         0,
317                 },
318                 {
319                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
320                         { SDB_TYPE_BOOLEAN, { .boolean = false } },
321                         1,
322                 },
323                 {
324                         { SDB_TYPE_INTEGER, { .integer = 47 } },
325                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
326                         -1,
327                 },
328                 {
329                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
330                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
331                         0,
332                 },
333                 {
334                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
335                         { SDB_TYPE_INTEGER, { .integer = 47 } },
336                         1,
337                 },
338                 {
339                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
340                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
341                         -1,
342                 },
343                 {
344                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
345                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
346                         0,
347                 },
348                 {
349                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
350                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
351                         1,
352                 },
353                 {
354                         { SDB_TYPE_STRING, { .string = NULL } },
355                         { SDB_TYPE_STRING, { .string = "" } },
356                         -1,
357                 },
358                 {
359                         { SDB_TYPE_STRING, { .string = NULL } },
360                         { SDB_TYPE_STRING, { .string = NULL } },
361                         0,
362                 },
363                 {
364                         { SDB_TYPE_STRING, { .string = "" } },
365                         { SDB_TYPE_STRING, { .string = NULL } },
366                         1,
367                 },
368                 {
369                         { SDB_TYPE_STRING, { .string = "a" } },
370                         { SDB_TYPE_STRING, { .string = "b" } },
371                         -1,
372                 },
373                 {
374                         { SDB_TYPE_STRING, { .string = "a" } },
375                         { SDB_TYPE_STRING, { .string = "ab" } },
376                         -1,
377                 },
378                 {
379                         { SDB_TYPE_STRING, { .string = "a" } },
380                         { SDB_TYPE_STRING, { .string = "a" } },
381                         0,
382                 },
383                 {
384                         { SDB_TYPE_STRING, { .string = "b" } },
385                         { SDB_TYPE_STRING, { .string = "a" } },
386                         1,
387                 },
388                 {
389                         { SDB_TYPE_STRING, { .string = "ab" } },
390                         { SDB_TYPE_STRING, { .string = "a" } },
391                         1,
392                 },
393                 {
394                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
395                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
396                         -1,
397                 },
398                 {
399                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
400                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
401                         0,
402                 },
403                 {
404                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
405                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
406                         1,
407                 },
408                 {
409                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
410                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
411                         -1,
412                 },
413                 {
414                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
415                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
416                         0,
417                 },
418                 {
419                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
420                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
421                         1,
422                 },
423                 {
424                         {
425                                 SDB_TYPE_BINARY,
426                                 { .binary = { 3, (unsigned char *)"a\0a" } },
427                         },
428                         {
429                                 SDB_TYPE_BINARY,
430                                 { .binary = { 3, (unsigned char *)"a\0b" } },
431                         },
432                         -1,
433                 },
434                 {
435                         {
436                                 SDB_TYPE_BINARY,
437                                 { .binary = { 1, (unsigned char *)"a" } },
438                         },
439                         {
440                                 SDB_TYPE_BINARY,
441                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
442                         },
443                         -1,
444                 },
445                 {
446                         {
447                                 SDB_TYPE_BINARY,
448                                 { .binary = { 3, (unsigned char *)"a\0a" } },
449                         },
450                         {
451                                 SDB_TYPE_BINARY,
452                                 { .binary = { 3, (unsigned char *)"a\0a" } },
453                         },
454                         0,
455                 },
456                 {
457                         {
458                                 SDB_TYPE_BINARY,
459                                 { .binary = { 3, (unsigned char *)"a\0b" } },
460                         },
461                         {
462                                 SDB_TYPE_BINARY,
463                                 { .binary = { 3, (unsigned char *)"a\0a" } },
464                         },
465                         1,
466                 },
467                 {
468                         {
469                                 SDB_TYPE_BINARY,
470                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
471                         },
472                         {
473                                 SDB_TYPE_BINARY,
474                                 { .binary = { 1, (unsigned char *)"a" } },
475                         },
476                         1,
477                 },
478                 {
479                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
480                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
481                         0,
482                 },
483                 {
484                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
485                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
486                         -1,
487                 },
488                 {
489                         { SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN, { .array = { 0, NULL } } },
490                         { SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN, { .array = { 0, NULL } } },
491                         0,
492                 },
493                 {
494                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
495                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
496                         1,
497                 },
498                 {
499                         { SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN, { .array = { 0, NULL } } },
500                         {
501                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
502                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values1), bool_values1 } },
503                         },
504                         -1,
505                 },
506                 {
507                         {
508                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
509                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values1), bool_values1 } },
510                         },
511                         { SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN, { .array = { 0, NULL } } },
512                         1,
513                 },
514                 {
515                         {
516                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
517                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values1), bool_values1 } },
518                         },
519                         {
520                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
521                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values1), bool_values1 } },
522                         },
523                         0,
524                 },
525                 {
526                         {
527                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
528                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values1), bool_values1 } },
529                         },
530                         {
531                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
532                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values2), bool_values2 } },
533                         },
534                         -1,
535                 },
536                 {
537                         {
538                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
539                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values2), bool_values2 } },
540                         },
541                         {
542                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
543                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values1), bool_values1 } },
544                         },
545                         1,
546                 },
547                 {
548                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
549                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
550                         0,
551                 },
552                 {
553                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
554                         {
555                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
556                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
557                         },
558                         -1,
559                 },
560                 {
561                         {
562                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
563                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
564                         },
565                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
566                         1,
567                 },
568                 {
569                         {
570                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
571                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
572                         },
573                         {
574                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
575                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
576                         },
577                         0,
578                 },
579                 {
580                         {
581                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
582                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
583                         },
584                         {
585                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
586                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
587                         },
588                         -1,
589                 },
590                 {
591                         {
592                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
593                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
594                         },
595                         {
596                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
597                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
598                         },
599                         1,
600                 },
601                 {
602                         {
603                                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
604                                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values1), dec_values1 } },
605                         },
606                         {
607                                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
608                                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values1), dec_values1 } },
609                         },
610                         0,
611                 },
612                 {
613                         {
614                                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
615                                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values1), dec_values1 } },
616                         },
617                         {
618                                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
619                                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values2), dec_values2 } },
620                         },
621                         -1,
622                 },
623                 {
624                         {
625                                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
626                                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values2), dec_values2 } },
627                         },
628                         {
629                                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
630                                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values1), dec_values1 } },
631                         },
632                         1,
633                 },
634                 {
635                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
636                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
637                         0,
638                 },
639                 {
640                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
641                         {
642                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
643                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
644                         },
645                         -1,
646                 },
647                 {
648                         {
649                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
650                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
651                         },
652                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
653                         1,
654                 },
655                 {
656                         {
657                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
658                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
659                         },
660                         {
661                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
662                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
663                         },
664                         0,
665                 },
666                 {
667                         {
668                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
669                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
670                         },
671                         {
672                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
673                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
674                         },
675                         -1,
676                 },
677                 {
678                         {
679                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
680                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
681                         },
682                         {
683                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
684                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
685                         },
686                         1,
687                 },
688                 {
689                         {
690                                 SDB_TYPE_ARRAY | SDB_TYPE_DATETIME,
691                                 { .array = { SDB_STATIC_ARRAY_LEN(dt_values1), dt_values1 } },
692                         },
693                         {
694                                 SDB_TYPE_ARRAY | SDB_TYPE_DATETIME,
695                                 { .array = { SDB_STATIC_ARRAY_LEN(dt_values1), dt_values1 } },
696                         },
697                         0,
698                 },
699                 {
700                         {
701                                 SDB_TYPE_ARRAY | SDB_TYPE_DATETIME,
702                                 { .array = { SDB_STATIC_ARRAY_LEN(dt_values1), dt_values1 } },
703                         },
704                         {
705                                 SDB_TYPE_ARRAY | SDB_TYPE_DATETIME,
706                                 { .array = { SDB_STATIC_ARRAY_LEN(dt_values2), dt_values2 } },
707                         },
708                         -1,
709                 },
710                 {
711                         {
712                                 SDB_TYPE_ARRAY | SDB_TYPE_DATETIME,
713                                 { .array = { SDB_STATIC_ARRAY_LEN(dt_values2), dt_values2 } },
714                         },
715                         {
716                                 SDB_TYPE_ARRAY | SDB_TYPE_DATETIME,
717                                 { .array = { SDB_STATIC_ARRAY_LEN(dt_values1), dt_values1 } },
718                         },
719                         1,
720                 },
721                 {
722                         {
723                                 SDB_TYPE_ARRAY | SDB_TYPE_BINARY,
724                                 { .array = { SDB_STATIC_ARRAY_LEN(bin_values1), bin_values1 } },
725                         },
726                         {
727                                 SDB_TYPE_ARRAY | SDB_TYPE_BINARY,
728                                 { .array = { SDB_STATIC_ARRAY_LEN(bin_values1), bin_values1 } },
729                         },
730                         0,
731                 },
732                 {
733                         {
734                                 SDB_TYPE_ARRAY | SDB_TYPE_BINARY,
735                                 { .array = { SDB_STATIC_ARRAY_LEN(bin_values1), bin_values1 } },
736                         },
737                         {
738                                 SDB_TYPE_ARRAY | SDB_TYPE_BINARY,
739                                 { .array = { SDB_STATIC_ARRAY_LEN(bin_values2), bin_values2 } },
740                         },
741                         -1,
742                 },
743                 {
744                         {
745                                 SDB_TYPE_ARRAY | SDB_TYPE_BINARY,
746                                 { .array = { SDB_STATIC_ARRAY_LEN(bin_values2), bin_values2 } },
747                         },
748                         {
749                                 SDB_TYPE_ARRAY | SDB_TYPE_BINARY,
750                                 { .array = { SDB_STATIC_ARRAY_LEN(bin_values1), bin_values1 } },
751                         },
752                         1,
753                 },
754                 {
755                         {
756                                 SDB_TYPE_ARRAY | SDB_TYPE_REGEX,
757                                 { .array = { SDB_STATIC_ARRAY_LEN(re_values1), re_values1 } },
758                         },
759                         {
760                                 SDB_TYPE_ARRAY | SDB_TYPE_REGEX,
761                                 { .array = { SDB_STATIC_ARRAY_LEN(re_values1), re_values1 } },
762                         },
763                         0,
764                 },
765                 {
766                         {
767                                 SDB_TYPE_ARRAY | SDB_TYPE_REGEX,
768                                 { .array = { SDB_STATIC_ARRAY_LEN(re_values1), re_values1 } },
769                         },
770                         {
771                                 SDB_TYPE_ARRAY | SDB_TYPE_REGEX,
772                                 { .array = { SDB_STATIC_ARRAY_LEN(re_values2), re_values2 } },
773                         },
774                         -1,
775                 },
776                 {
777                         {
778                                 SDB_TYPE_ARRAY | SDB_TYPE_REGEX,
779                                 { .array = { SDB_STATIC_ARRAY_LEN(re_values2), re_values2 } },
780                         },
781                         {
782                                 SDB_TYPE_ARRAY | SDB_TYPE_REGEX,
783                                 { .array = { SDB_STATIC_ARRAY_LEN(re_values1), re_values1 } },
784                         },
785                         1,
786                 },
787         };
789         size_t i;
791         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
792                 int check = sdb_data_cmp(&golden_data[i].d1, &golden_data[i].d2);
793                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
794                 if (check != golden_data[i].expected) {
795                         char d1_str[64] = "", d2_str[64] = "";
796                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
797                                         SDB_DOUBLE_QUOTED);
798                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
799                                         SDB_DOUBLE_QUOTED);
800                         fail("sdb_data_cmp(%s, %s) = %d; expected: %d",
801                                         d1_str, d2_str, check, golden_data[i].expected);
802                 }
803         }
805 END_TEST
807 START_TEST(test_strcmp)
809         struct {
810                 sdb_data_t d1;
811                 sdb_data_t d2;
812                 int expected;
813         } golden_data[] = {
814                 /* same data as for the sdb_data_cmp test; in case the types match,
815                  * both functions should behave the same (except for some loss in
816                  * precision, e.g. when formatting datetime values) */
817                 {
818                         { SDB_TYPE_BOOLEAN, { .boolean = false } },
819                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
820                         -1,
821                 },
822                 {
823                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
824                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
825                         0,
826                 },
827                 {
828                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
829                         { SDB_TYPE_BOOLEAN, { .boolean = false } },
830                         1,
831                 },
832                 {
833                         { SDB_TYPE_INTEGER, { .integer = 47 } },
834                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
835                         -1,
836                 },
837                 {
838                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
839                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
840                         0,
841                 },
842                 {
843                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
844                         { SDB_TYPE_INTEGER, { .integer = 47 } },
845                         1,
846                 },
847                 {
848                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
849                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
850                         -1,
851                 },
852                 {
853                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
854                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
855                         0,
856                 },
857                 {
858                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
859                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
860                         1,
861                 },
862                 {
863                         { SDB_TYPE_STRING, { .string = NULL } },
864                         { SDB_TYPE_STRING, { .string = "" } },
865                         -1,
866                 },
867                 {
868                         { SDB_TYPE_STRING, { .string = NULL } },
869                         { SDB_TYPE_STRING, { .string = NULL } },
870                         0,
871                 },
872                 {
873                         { SDB_TYPE_STRING, { .string = "" } },
874                         { SDB_TYPE_STRING, { .string = NULL } },
875                         1,
876                 },
877                 {
878                         { SDB_TYPE_STRING, { .string = "a" } },
879                         { SDB_TYPE_STRING, { .string = "b" } },
880                         -1,
881                 },
882                 {
883                         { SDB_TYPE_STRING, { .string = "a" } },
884                         { SDB_TYPE_STRING, { .string = "ab" } },
885                         -1,
886                 },
887                 {
888                         { SDB_TYPE_STRING, { .string = "a" } },
889                         { SDB_TYPE_STRING, { .string = "a" } },
890                         0,
891                 },
892                 {
893                         { SDB_TYPE_STRING, { .string = "b" } },
894                         { SDB_TYPE_STRING, { .string = "a" } },
895                         1,
896                 },
897                 {
898                         { SDB_TYPE_STRING, { .string = "ab" } },
899                         { SDB_TYPE_STRING, { .string = "a" } },
900                         1,
901                 },
902                 {
903                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
904                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
905                         -1,
906                 },
907                 {
908                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
909                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
910                         0,
911                 },
912                 {
913                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
914                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
915                         1,
916                 },
917                 {
918                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
919                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
920                         -1,
921                 },
922                 {
923                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
924                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
925                         0,
926                 },
927                 {
928                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
929                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
930                         1,
931                 },
932                 {
933                         {
934                                 SDB_TYPE_BINARY,
935                                 { .binary = { 3, (unsigned char *)"a\0a" } },
936                         },
937                         {
938                                 SDB_TYPE_BINARY,
939                                 { .binary = { 3, (unsigned char *)"a\0b" } },
940                         },
941                         -1,
942                 },
943                 {
944                         {
945                                 SDB_TYPE_BINARY,
946                                 { .binary = { 1, (unsigned char *)"a" } },
947                         },
948                         {
949                                 SDB_TYPE_BINARY,
950                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
951                         },
952                         -1,
953                 },
954                 {
955                         {
956                                 SDB_TYPE_BINARY,
957                                 { .binary = { 3, (unsigned char *)"a\0a" } },
958                         },
959                         {
960                                 SDB_TYPE_BINARY,
961                                 { .binary = { 3, (unsigned char *)"a\0a" } },
962                         },
963                         0,
964                 },
965                 {
966                         {
967                                 SDB_TYPE_BINARY,
968                                 { .binary = { 3, (unsigned char *)"a\0b" } },
969                         },
970                         {
971                                 SDB_TYPE_BINARY,
972                                 { .binary = { 3, (unsigned char *)"a\0a" } },
973                         },
974                         1,
975                 },
976                 {
977                         {
978                                 SDB_TYPE_BINARY,
979                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
980                         },
981                         {
982                                 SDB_TYPE_BINARY,
983                                 { .binary = { 1, (unsigned char *)"a" } },
984                         },
985                         1,
986                 },
987                 {
988                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
989                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
990                         0,
991                 },
992                 {
993                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
994                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
995                         -1,
996                 },
997                 {
998                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
999                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
1000                         1,
1001                 },
1002                 /* type mismatches */
1003                 {
1004                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1005                         { SDB_TYPE_INTEGER, { .integer = 1 } },
1006                         1,
1007                 },
1008                 {
1009                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1010                         { SDB_TYPE_STRING, { .string = "true" } },
1011                         0,
1012                 },
1013                 {
1014                         { SDB_TYPE_INTEGER, { .integer = 123 } },
1015                         { SDB_TYPE_STRING, { .string = "123" } },
1016                         0,
1017                 },
1018                 {
1019                         { SDB_TYPE_INTEGER, { .integer = 120 } },
1020                         { SDB_TYPE_STRING, { .string = "123" } },
1021                         -1,
1022                 },
1023                 {
1024                         { SDB_TYPE_STRING, { .string = "123" } },
1025                         { SDB_TYPE_INTEGER, { .integer = 120 } },
1026                         1,
1027                 },
1028                 {
1029                         { SDB_TYPE_STRING, { .string = "12.3" } },
1030                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
1031                         0,
1032                 },
1033                 {
1034                         { SDB_TYPE_STRING, { .string = "12.0" } },
1035                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
1036                         -1,
1037                 },
1038                 {
1039                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
1040                         { SDB_TYPE_STRING, { .string = "12.0" } },
1041                         1,
1042                 },
1043                 {
1044                         { SDB_TYPE_REGEX, { .re = { "regex", empty_re } } },
1045                         { SDB_TYPE_STRING, { .string = "/regex/" } },
1046                         0,
1047                 },
1048                 /* TODO: add support for arrays */
1049         };
1051         size_t i;
1053         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1054                 int check = sdb_data_strcmp(&golden_data[i].d1, &golden_data[i].d2);
1055                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
1056                 if (check != golden_data[i].expected) {
1057                         char d1_str[64] = "", d2_str[64] = "";
1058                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
1059                                         SDB_DOUBLE_QUOTED);
1060                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
1061                                         SDB_DOUBLE_QUOTED);
1062                         fail("sdb_data_strcmp(%s, %s) = %d; expected: %d",
1063                                         d1_str, d2_str, check, golden_data[i].expected);
1064                 }
1065         }
1067 END_TEST
1069 START_TEST(test_inarray)
1071         bool bool_values[] = { true, false, true };
1072         bool bool_values2[] = { false, true };
1073         bool bool_values3[] = { true, true, true };
1074         bool bool_values4[] = { false, false };
1075         int64_t int_values[] = { 47, 11, 64 };
1076         int64_t int_values2[] = { 64, 11 };
1077         int64_t int_values3[] = { 47, 11, 42 };
1078         double dec_values[] = { 12.3, 47.11, 64.0 };
1079         double dec_values2[] = { 12.3, 47.11 };
1080         double dec_values3[] = { 2.3, 47.11 };
1081         char *string_values[] = { "foo", "bar", "qux", "baz" };
1082         char *string_values2[] = { "qux", "bar" };
1083         char *string_values3[] = { "foo", "bar", "qux", "baz", "bay" };
1085         sdb_data_t bool_array = {
1086                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1087                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values), bool_values } }
1088         };
1089         sdb_data_t bool_array2 = {
1090                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1091                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values2), bool_values2 } }
1092         };
1093         sdb_data_t bool_array3 = {
1094                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1095                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values3), bool_values3 } }
1096         };
1097         sdb_data_t bool_array4 = {
1098                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1099                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values4), bool_values4 } }
1100         };
1101         sdb_data_t int_array = {
1102                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1103                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } }
1104         };
1105         sdb_data_t int_array2 = {
1106                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1107                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } }
1108         };
1109         sdb_data_t int_array3 = {
1110                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1111                 { .array = { SDB_STATIC_ARRAY_LEN(int_values3), int_values3 } }
1112         };
1113         sdb_data_t dec_array = {
1114                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
1115                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } }
1116         };
1117         sdb_data_t dec_array2 = {
1118                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
1119                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values2), dec_values2 } }
1120         };
1121         sdb_data_t dec_array3 = {
1122                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
1123                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values3), dec_values3 } }
1124         };
1125         sdb_data_t string_array = {
1126                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1127                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } }
1128         };
1129         sdb_data_t string_array2 = {
1130                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1131                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } }
1132         };
1133         sdb_data_t string_array3 = {
1134                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1135                 { .array = { SDB_STATIC_ARRAY_LEN(string_values3), string_values3 } }
1136         };
1138         struct {
1139                 sdb_data_t value;
1140                 sdb_data_t array;
1141                 _Bool expected;
1142         } golden_data[] = {
1143                 { { SDB_TYPE_BOOLEAN, { .boolean = true  } }, bool_array,   1 },
1144                 { { SDB_TYPE_BOOLEAN, { .boolean = true  } }, bool_array4,  0 },
1145                 { { SDB_TYPE_BOOLEAN, { .boolean = false } }, bool_array,   1 },
1146                 { { SDB_TYPE_INTEGER, { .integer = 47    } }, int_array,    1 },
1147                 { { SDB_TYPE_INTEGER, { .integer = 11    } }, int_array,    1 },
1148                 { { SDB_TYPE_INTEGER, { .integer = 64    } }, int_array,    1 },
1149                 { { SDB_TYPE_INTEGER, { .integer = 65    } }, int_array,    0 },
1150                 { { SDB_TYPE_NULL,    { .integer = 0     } }, int_array,    0 },
1151                 { { SDB_TYPE_DECIMAL, { .decimal = 12.3  } }, dec_array,    1 },
1152                 { { SDB_TYPE_DECIMAL, { .decimal = 47.11 } }, dec_array,    1 },
1153                 { { SDB_TYPE_DECIMAL, { .decimal = 64.0  } }, dec_array,    1 },
1154                 { { SDB_TYPE_DECIMAL, { .decimal = 60.0  } }, dec_array,    0 },
1155                 { { SDB_TYPE_INTEGER, { .integer = 64    } }, dec_array,    0 },
1156                 { { SDB_TYPE_NULL,    { .integer = 0     } }, dec_array,    0 },
1157                 { { SDB_TYPE_STRING,  { .string  = "Foo" } }, string_array, 1 },
1158                 { { SDB_TYPE_STRING,  { .string  = "FOO" } }, string_array, 1 },
1159                 { { SDB_TYPE_STRING,  { .string  = "foo" } }, string_array, 1 },
1160                 { { SDB_TYPE_STRING,  { .string  = "bar" } }, string_array, 1 },
1161                 { { SDB_TYPE_STRING,  { .string  = "qux" } }, string_array, 1 },
1162                 { { SDB_TYPE_STRING,  { .string  = "baz" } }, string_array, 1 },
1163                 { { SDB_TYPE_STRING,  { .string  = "ba"  } }, string_array, 0 },
1164                 { { SDB_TYPE_STRING,  { .string  = "abc" } }, string_array, 0 },
1165                 { { SDB_TYPE_NULL,    { .integer = 0     } }, string_array, 0 },
1166                 { bool_array, { SDB_TYPE_BOOLEAN, { .boolean = true } },    0 },
1167                 { int_array, { SDB_TYPE_INTEGER, { .integer = 47 } },       0 },
1168                 { bool_array,    bool_array,   1 },
1169                 { bool_array2,   bool_array,   1 },
1170                 { bool_array,    bool_array2,  1 },
1171                 { bool_array,    bool_array3,  0 },
1172                 { bool_array,    bool_array4,  0 },
1173                 { bool_array2,   bool_array3,  0 },
1174                 { bool_array2,   bool_array4,  0 },
1175                 { bool_array3,   bool_array4,  0 },
1176                 { bool_array4,   bool_array3,  0 },
1177                 { int_array,     int_array,    1 },
1178                 { int_array2,    int_array,    1 },
1179                 { int_array3,    int_array,    0 },
1180                 { dec_array2,    int_array,    0 },
1181                 { string_array2, int_array,    0 },
1182                 { dec_array,     dec_array,    1 },
1183                 { dec_array2,    dec_array,    1 },
1184                 { dec_array3,    dec_array,    0 },
1185                 { int_array2,    dec_array,    0 },
1186                 { string_array2, dec_array,    0 },
1187                 { string_array,  string_array, 1 },
1188                 { string_array2, string_array, 1 },
1189                 { string_array3, string_array, 0 },
1190                 { int_array2,    string_array, 0 },
1191                 { dec_array2,    string_array, 0 },
1192                 {
1193                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1194                         int_array, 1,
1195                 },
1196                 {
1197                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1198                         dec_array, 0,
1199                 },
1200                 {
1201                         { SDB_TYPE_DECIMAL | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1202                         dec_array, 1,
1203                 },
1204                 {
1205                         { SDB_TYPE_DECIMAL | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1206                         int_array, 0,
1207                 },
1208                 {
1209                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1210                         string_array, 1,
1211                 },
1212                 {
1213                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1214                         dec_array, 0,
1215                 },
1216         };
1218         size_t i;
1220         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1221                 char v_str[1024] = "", a_str[1024] = "";
1222                 _Bool check;
1224                 sdb_data_format(&golden_data[i].value,
1225                                 v_str, sizeof(v_str), SDB_UNQUOTED);
1226                 sdb_data_format(&golden_data[i].array,
1227                                 a_str, sizeof(a_str), SDB_UNQUOTED);
1229                 check = sdb_data_inarray(&golden_data[i].value, &golden_data[i].array);
1230                 fail_unless(check == golden_data[i].expected,
1231                                 "sdb_data_inarray(%s, %s) = %d; expected: %d",
1232                                 v_str, a_str, check, golden_data[i].expected);
1233         }
1235 END_TEST
1237 START_TEST(test_array_get)
1239         bool bool_values[] = { true, false, false };
1240         int64_t int_values[] = { 47, 11, 64 };
1241         double dec_values[] = { 12.3, 47.11, 64.0 };
1242         char *string_values[] = { "foo", "bar", "qux", "baz" };
1244         sdb_data_t bool_array = {
1245                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1246                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values), bool_values } }
1247         };
1248         sdb_data_t int_array = {
1249                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1250                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } }
1251         };
1252         sdb_data_t dec_array = {
1253                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
1254                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } }
1255         };
1256         sdb_data_t string_array = {
1257                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1258                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } }
1259         };
1261         struct {
1262                 sdb_data_t array;
1263                 size_t i;
1264                 sdb_data_t expected;
1265         } golden_data[] = {
1266                 { bool_array, 0, { SDB_TYPE_BOOLEAN, { .boolean = true } } },
1267                 { bool_array, 1, { SDB_TYPE_BOOLEAN, { .boolean = false } } },
1268                 { bool_array, 2, { SDB_TYPE_BOOLEAN, { .boolean = false } } },
1269                 { bool_array, 3, { -1, { .integer = 0 } } },
1270                 { int_array, 0, { SDB_TYPE_INTEGER, { .integer = 47 } } },
1271                 { int_array, 1, { SDB_TYPE_INTEGER, { .integer = 11 } } },
1272                 { int_array, 2, { SDB_TYPE_INTEGER, { .integer = 64 } } },
1273                 { int_array, 3, { -1, { .integer = 0 } } },
1274                 { dec_array, 0, { SDB_TYPE_DECIMAL, { .decimal = 12.3 } } },
1275                 { dec_array, 1, { SDB_TYPE_DECIMAL, { .decimal = 47.11 } } },
1276                 { dec_array, 2, { SDB_TYPE_DECIMAL, { .decimal = 64.0 } } },
1277                 { dec_array, 3, { -1, { .integer = 0 } } },
1278                 { string_array, 0, { SDB_TYPE_STRING, { .string = "foo" } } },
1279                 { string_array, 1, { SDB_TYPE_STRING, { .string = "bar" } } },
1280                 { string_array, 2, { SDB_TYPE_STRING, { .string = "qux" } } },
1281                 { string_array, 3, { SDB_TYPE_STRING, { .string = "baz" } } },
1282                 { string_array, 4, { -1, { .integer = 0 } } },
1283                 { { SDB_TYPE_INTEGER, { .integer = 666 } }, 0, { -1, { .integer = 0 } } },
1284                 { { SDB_TYPE_INTEGER, { .integer = 666 } }, 1, { -1, { .integer = 0 } } },
1285                 {
1286                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
1287                         0, { -1, { .integer = 0 } },
1288                 },
1289                 {
1290                         { SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL, { .array = { 0, NULL } } },
1291                         0, { -1, { .integer = 0 } },
1292                 },
1293                 {
1294                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
1295                         0, { -1, { .integer = 0 } },
1296                 },
1297         };
1299         size_t i;
1301         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1302                 char a_str[1024] = "", v_str[1024] = "", exp_str[1024] = "";
1303                 sdb_data_t value = SDB_DATA_INIT;
1304                 int check;
1306                 sdb_data_format(&golden_data[i].array,
1307                                 a_str, sizeof(a_str), SDB_UNQUOTED);
1308                 sdb_data_format(&golden_data[i].expected,
1309                                 exp_str, sizeof(exp_str), SDB_UNQUOTED);
1311                 check = sdb_data_array_get(&golden_data[i].array,
1312                                 golden_data[i].i, &value);
1314                 sdb_data_format(&value, v_str, sizeof(v_str), SDB_UNQUOTED);
1316                 if (golden_data[i].expected.type < 0) {
1317                         fail_unless(check < 0,
1318                                         "sdb_data_array_get(%s, %zu) = %d (%s); expected: <0",
1319                                         a_str, golden_data[i].i, check, v_str);
1320                         continue;
1321                 }
1323                 fail_unless(check == 0,
1324                                 "sdb_data_array_get(%s, %zu) = %d; expected: 0",
1325                                 a_str, golden_data[i].i, check);
1326                 fail_unless(! sdb_data_cmp(&value, &golden_data[i].expected),
1327                                 "sdb_data_array_get(%s, %zu) -> '%s'; expected: '%s'",
1328                                 a_str, golden_data[i].i, v_str, exp_str);
1329         }
1331 END_TEST
1333 START_TEST(test_parse_op)
1335         struct {
1336                 const char *op;
1337                 int id;
1338         } golden_data[] = {
1339                 { "+",  SDB_DATA_ADD },
1340                 { "-",  SDB_DATA_SUB },
1341                 { "*",  SDB_DATA_MUL },
1342                 { "/",  SDB_DATA_DIV },
1343                 { "%",  SDB_DATA_MOD },
1344                 { "||", SDB_DATA_CONCAT },
1345                 { "&&", -1 },
1346         };
1348         size_t i;
1350         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1351                 const char *op;
1352                 int id;
1354                 id = sdb_data_parse_op(golden_data[i].op);
1355                 fail_unless(id == golden_data[i].id,
1356                                 "sdb_data_parse_op(%s) = %d; expected: %d",
1357                                 golden_data[i].op, id, golden_data[i].id);
1359                 if (id <= 0)
1360                         continue;
1362                 op = SDB_DATA_OP_TO_STRING(id);
1363                 fail_unless(!strcmp(op, golden_data[i].op),
1364                                 "SDB_DATA_OP_TO_STRING(%d) = '%s'; expected: '%s'",
1365                                 id, op, golden_data[i].op);
1366         }
1368 END_TEST
1370 START_TEST(test_expr_eval)
1372         sdb_data_t err = { -1, { .integer = 0 } };
1374         bool bool_values[] = { true, false, true };
1375         bool expected_bool_append[] = { true, false, true, true };
1376         bool expected_bool_prepend[] = { true, true, false, true };
1377         bool expected_bool_concat[] = { true, false, true, true, false, true };
1378         int64_t int_values[] = { 47, 11, 23 };
1379         int64_t expected_int_append[] = { 47, 11, 23, 42 };
1380         int64_t expected_int_prepend[] = { 42, 47, 11, 23 };
1381         int64_t expected_int_concat[] = { 47, 11, 23, 47, 11, 23 };
1382         char *string_values[] = { "foo", "bar", "qux" "baz" };
1383         char *expected_string_append[] = { "foo", "bar", "qux" "baz", "bay" };
1384         char *expected_string_prepend[] = { "bay", "foo", "bar", "qux" "baz" };
1385         char *expected_string_concat[] =
1386                 { "foo", "bar", "qux" "baz", "foo", "bar", "qux" "baz" };
1388         struct {
1389                 sdb_data_t d1;
1390                 sdb_data_t d2;
1391                 sdb_data_t expected_add;
1392                 sdb_data_t expected_sub;
1393                 sdb_data_t expected_mul;
1394                 sdb_data_t expected_div;
1395                 sdb_data_t expected_mod;
1396                 sdb_data_t expected_concat;
1397         } golden_data[] = {
1398                 {
1399                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1400                         { SDB_TYPE_BOOLEAN, { .boolean = false } },
1401                         err,
1402                         err,
1403                         err,
1404                         err,
1405                         err,
1406                         err,
1407                 },
1408                 {
1409                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
1410                         { SDB_TYPE_INTEGER, { .integer = 47 } },
1411                         { SDB_TYPE_INTEGER, { .integer = 4758 } },
1412                         { SDB_TYPE_INTEGER, { .integer = 4664 } },
1413                         { SDB_TYPE_INTEGER, { .integer = 221417 } },
1414                         { SDB_TYPE_INTEGER, { .integer = 100 } },
1415                         { SDB_TYPE_INTEGER, { .integer = 11 } },
1416                         err,
1417                 },
1418                 {
1419                         { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
1420                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
1421                         { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
1422                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
1423                         { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
1424                         { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
1425                         { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
1426                         err,
1427                 },
1428                 {
1429                         { SDB_TYPE_STRING, { .string = NULL } },
1430                         { SDB_TYPE_STRING, { .string = "" } },
1431                         SDB_DATA_NULL,
1432                         SDB_DATA_NULL,
1433                         SDB_DATA_NULL,
1434                         SDB_DATA_NULL,
1435                         SDB_DATA_NULL,
1436                         SDB_DATA_NULL,
1437                 },
1438                 {
1439                         { SDB_TYPE_STRING, { .string = NULL } },
1440                         { SDB_TYPE_STRING, { .string = NULL } },
1441                         SDB_DATA_NULL,
1442                         SDB_DATA_NULL,
1443                         SDB_DATA_NULL,
1444                         SDB_DATA_NULL,
1445                         SDB_DATA_NULL,
1446                         SDB_DATA_NULL,
1447                 },
1448                 {
1449                         { SDB_TYPE_STRING, { .string = "" } },
1450                         { SDB_TYPE_STRING, { .string = NULL } },
1451                         SDB_DATA_NULL,
1452                         SDB_DATA_NULL,
1453                         SDB_DATA_NULL,
1454                         SDB_DATA_NULL,
1455                         SDB_DATA_NULL,
1456                         SDB_DATA_NULL,
1457                 },
1458                 {
1459                         { SDB_TYPE_STRING, { .string = "a" } },
1460                         { SDB_TYPE_STRING, { .string = "b" } },
1461                         err,
1462                         err,
1463                         err,
1464                         err,
1465                         err,
1466                         { SDB_TYPE_STRING, { .string = "ab" } },
1467                 },
1468                 {
1469                         { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
1470                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1471                         { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
1472                         { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
1473                         { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
1474                         { SDB_TYPE_DATETIME, { .datetime = 10001 } },
1475                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1476                         err,
1477                 },
1478                 {
1479                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1480                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1481                         SDB_DATA_NULL,
1482                         SDB_DATA_NULL,
1483                         SDB_DATA_NULL,
1484                         SDB_DATA_NULL,
1485                         SDB_DATA_NULL,
1486                         SDB_DATA_NULL,
1487                 },
1488                 {
1489                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1490                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1491                         SDB_DATA_NULL,
1492                         SDB_DATA_NULL,
1493                         SDB_DATA_NULL,
1494                         SDB_DATA_NULL,
1495                         SDB_DATA_NULL,
1496                         SDB_DATA_NULL,
1497                 },
1498                 {
1499                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1500                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1501                         SDB_DATA_NULL,
1502                         SDB_DATA_NULL,
1503                         SDB_DATA_NULL,
1504                         SDB_DATA_NULL,
1505                         SDB_DATA_NULL,
1506                         SDB_DATA_NULL,
1507                 },
1508                 {
1509                         {
1510                                 SDB_TYPE_BINARY,
1511                                 { .binary = { 3, (unsigned char *)"a\0a" } },
1512                         },
1513                         {
1514                                 SDB_TYPE_BINARY,
1515                                 { .binary = { 3, (unsigned char *)"b\0b" } },
1516                         },
1517                         err,
1518                         err,
1519                         err,
1520                         err,
1521                         err,
1522                         {
1523                                 SDB_TYPE_BINARY,
1524                                 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
1525                         },
1526                 },
1527                 {
1528                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1529                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1530                         err,
1531                         err,
1532                         err,
1533                         err,
1534                         err,
1535                         err,
1536                 },
1537                 {
1538                         {
1539                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1540                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values), bool_values } },
1541                         },
1542                         {
1543                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1544                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values), bool_values } },
1545                         },
1546                         err,
1547                         err,
1548                         err,
1549                         err,
1550                         err,
1551                         {
1552                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1553                                 { .array = {
1554                                                 SDB_STATIC_ARRAY_LEN(expected_bool_concat),
1555                                                 expected_bool_concat
1556                                 } },
1557                         },
1558                 },
1559                 {
1560                         {
1561                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1562                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values), bool_values } },
1563                         },
1564                         { SDB_TYPE_BOOLEAN, { .boolean = true }, },
1565                         err,
1566                         err,
1567                         err,
1568                         err,
1569                         err,
1570                         {
1571                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1572                                 { .array = {
1573                                                 SDB_STATIC_ARRAY_LEN(expected_bool_append),
1574                                                 expected_bool_append
1575                                 } },
1576                         },
1577                 },
1578                 {
1579                         { SDB_TYPE_BOOLEAN, { .boolean = true }, },
1580                         {
1581                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1582                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values), bool_values } },
1583                         },
1584                         err,
1585                         err,
1586                         err,
1587                         err,
1588                         err,
1589                         {
1590                                 SDB_TYPE_ARRAY | SDB_TYPE_BOOLEAN,
1591                                 { .array = {
1592                                                 SDB_STATIC_ARRAY_LEN(expected_bool_prepend),
1593                                                 expected_bool_prepend
1594                                 } },
1595                         },
1596                 },
1597                 {
1598                         {
1599                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1600                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1601                         },
1602                         {
1603                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1604                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1605                         },
1606                         err,
1607                         err,
1608                         err,
1609                         err,
1610                         err,
1611                         {
1612                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1613                                 { .array = {
1614                                                 SDB_STATIC_ARRAY_LEN(expected_int_concat),
1615                                                 expected_int_concat
1616                                 } },
1617                         },
1618                 },
1619                 {
1620                         {
1621                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1622                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1623                         },
1624                         { SDB_TYPE_INTEGER, { .integer = 42 }, },
1625                         err,
1626                         err,
1627                         err,
1628                         err,
1629                         err,
1630                         {
1631                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1632                                 { .array = {
1633                                                 SDB_STATIC_ARRAY_LEN(expected_int_append),
1634                                                 expected_int_append
1635                                 } },
1636                         },
1637                 },
1638                 {
1639                         { SDB_TYPE_INTEGER, { .integer = 42 }, },
1640                         {
1641                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1642                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1643                         },
1644                         err,
1645                         err,
1646                         err,
1647                         err,
1648                         err,
1649                         {
1650                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1651                                 { .array = {
1652                                                 SDB_STATIC_ARRAY_LEN(expected_int_prepend),
1653                                                 expected_int_prepend
1654                                 } },
1655                         },
1656                 },
1657                 {
1658                         {
1659                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1660                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1661                         },
1662                         {
1663                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1664                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1665                         },
1666                         err,
1667                         err,
1668                         err,
1669                         err,
1670                         err,
1671                         {
1672                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1673                                 { .array = {
1674                                                 SDB_STATIC_ARRAY_LEN(expected_string_concat),
1675                                                 expected_string_concat
1676                                 } },
1677                         },
1678                 },
1679                 {
1680                         {
1681                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1682                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1683                         },
1684                         { SDB_TYPE_STRING, { .string = "bay" } },
1685                         err,
1686                         err,
1687                         err,
1688                         err,
1689                         err,
1690                         {
1691                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1692                                 { .array = {
1693                                                 SDB_STATIC_ARRAY_LEN(expected_string_append),
1694                                                 expected_string_append
1695                                 } },
1696                         },
1697                 },
1698                 {
1699                         { SDB_TYPE_STRING, { .string = "bay" } },
1700                         {
1701                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1702                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1703                         },
1704                         err,
1705                         err,
1706                         err,
1707                         err,
1708                         err,
1709                         {
1710                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1711                                 { .array = {
1712                                                 SDB_STATIC_ARRAY_LEN(expected_string_prepend),
1713                                                 expected_string_prepend
1714                                 } },
1715                         },
1716                 },
1717                 {
1718                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1719                         {
1720                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1721                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1722                         },
1723                         err,
1724                         err,
1725                         err,
1726                         err,
1727                         err,
1728                         {
1729                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1730                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1731                         },
1732                 },
1733                 {
1734                         {
1735                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1736                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1737                         },
1738                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1739                         err,
1740                         err,
1741                         err,
1742                         err,
1743                         err,
1744                         {
1745                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1746                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1747                         },
1748                 },
1749                 {
1750                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1751                         {
1752                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1753                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1754                         },
1755                         err,
1756                         err,
1757                         err,
1758                         err,
1759                         err,
1760                         {
1761                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1762                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1763                         },
1764                 },
1765                 {
1766                         {
1767                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1768                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1769                         },
1770                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1771                         err,
1772                         err,
1773                         err,
1774                         err,
1775                         err,
1776                         {
1777                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1778                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1779                         },
1780                 },
1781                 {
1782                         { SDB_TYPE_NULL, { .integer = 0 } },
1783                         { SDB_TYPE_NULL, { .integer = 0 } },
1784                         SDB_DATA_NULL,
1785                         SDB_DATA_NULL,
1786                         SDB_DATA_NULL,
1787                         SDB_DATA_NULL,
1788                         SDB_DATA_NULL,
1789                         SDB_DATA_NULL,
1790                 },
1791                 {
1792                         { SDB_TYPE_NULL, { .integer = 0 } },
1793                         { SDB_TYPE_INTEGER, { .integer = 42 } },
1794                         SDB_DATA_NULL,
1795                         SDB_DATA_NULL,
1796                         SDB_DATA_NULL,
1797                         SDB_DATA_NULL,
1798                         SDB_DATA_NULL,
1799                         SDB_DATA_NULL,
1800                 },
1801                 {
1802                         { SDB_TYPE_INTEGER, { .integer = 42 } },
1803                         { SDB_TYPE_NULL, { .integer = 0 } },
1804                         SDB_DATA_NULL,
1805                         SDB_DATA_NULL,
1806                         SDB_DATA_NULL,
1807                         SDB_DATA_NULL,
1808                         SDB_DATA_NULL,
1809                         SDB_DATA_NULL,
1810                 },
1811                 {
1812                         { SDB_TYPE_NULL, { .integer = 0 } },
1813                         { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
1814                         SDB_DATA_NULL,
1815                         SDB_DATA_NULL,
1816                         SDB_DATA_NULL,
1817                         SDB_DATA_NULL,
1818                         SDB_DATA_NULL,
1819                         SDB_DATA_NULL,
1820                 },
1821                 {
1822                         { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
1823                         { SDB_TYPE_NULL, { .integer = 0 } },
1824                         SDB_DATA_NULL,
1825                         SDB_DATA_NULL,
1826                         SDB_DATA_NULL,
1827                         SDB_DATA_NULL,
1828                         SDB_DATA_NULL,
1829                         SDB_DATA_NULL,
1830                 },
1831                 {
1832                         { SDB_TYPE_NULL, { .integer = 0 } },
1833                         { SDB_TYPE_STRING, { .string = "47.11" } },
1834                         SDB_DATA_NULL,
1835                         SDB_DATA_NULL,
1836                         SDB_DATA_NULL,
1837                         SDB_DATA_NULL,
1838                         SDB_DATA_NULL,
1839                         SDB_DATA_NULL,
1840                 },
1841                 {
1842                         { SDB_TYPE_STRING, { .string = "47.11" } },
1843                         { SDB_TYPE_NULL, { .integer = 0 } },
1844                         SDB_DATA_NULL,
1845                         SDB_DATA_NULL,
1846                         SDB_DATA_NULL,
1847                         SDB_DATA_NULL,
1848                         SDB_DATA_NULL,
1849                         SDB_DATA_NULL,
1850                 },
1851                 {
1852                         { SDB_TYPE_NULL, { .integer = 0 } },
1853                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1854                         SDB_DATA_NULL,
1855                         SDB_DATA_NULL,
1856                         SDB_DATA_NULL,
1857                         SDB_DATA_NULL,
1858                         SDB_DATA_NULL,
1859                         SDB_DATA_NULL,
1860                 },
1861                 {
1862                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1863                         { SDB_TYPE_NULL, { .integer = 0 } },
1864                         SDB_DATA_NULL,
1865                         SDB_DATA_NULL,
1866                         SDB_DATA_NULL,
1867                         SDB_DATA_NULL,
1868                         SDB_DATA_NULL,
1869                         SDB_DATA_NULL,
1870                 },
1871                 {
1872                         { SDB_TYPE_NULL, { .integer = 0 } },
1873                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1874                         SDB_DATA_NULL,
1875                         SDB_DATA_NULL,
1876                         SDB_DATA_NULL,
1877                         SDB_DATA_NULL,
1878                         SDB_DATA_NULL,
1879                         SDB_DATA_NULL,
1880                 },
1881                 {
1882                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1883                         { SDB_TYPE_NULL, { .integer = 0 } },
1884                         SDB_DATA_NULL,
1885                         SDB_DATA_NULL,
1886                         SDB_DATA_NULL,
1887                         SDB_DATA_NULL,
1888                         SDB_DATA_NULL,
1889                         SDB_DATA_NULL,
1890                 },
1891                 {
1892                         { SDB_TYPE_NULL, { .integer = 0 } },
1893                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1894                         SDB_DATA_NULL,
1895                         SDB_DATA_NULL,
1896                         SDB_DATA_NULL,
1897                         SDB_DATA_NULL,
1898                         SDB_DATA_NULL,
1899                         SDB_DATA_NULL,
1900                 },
1901                 {
1902                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1903                         { SDB_TYPE_NULL, { .integer = 0 } },
1904                         SDB_DATA_NULL,
1905                         SDB_DATA_NULL,
1906                         SDB_DATA_NULL,
1907                         SDB_DATA_NULL,
1908                         SDB_DATA_NULL,
1909                         SDB_DATA_NULL,
1910                 },
1911                 /* supported type-mismatches */
1912                 {
1913                         /* int * datetime */
1914                         { SDB_TYPE_INTEGER,  { .integer  = 20 } },
1915                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
1916                         err,
1917                         err,
1918                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1919                         err,
1920                         err,
1921                         err,
1922                 },
1923                 {
1924                         /* datetime * int, datetime / int, datetime % int */
1925                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1926                         { SDB_TYPE_INTEGER,  { .integer  = 2 } },
1927                         err,
1928                         err,
1929                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1930                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
1931                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1932                         err,
1933                 },
1934                 {
1935                         /* float * datetime */
1936                         { SDB_TYPE_DECIMAL,  { .decimal  = 20.0 } },
1937                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
1938                         err,
1939                         err,
1940                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1941                         err,
1942                         err,
1943                         err,
1944                 },
1945                 {
1946                         /* datetime * float, datetime / float, datetime % float */
1947                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1948                         { SDB_TYPE_DECIMAL,  { .decimal  = 2.0 } },
1949                         err,
1950                         err,
1951                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1952                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
1953                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1954                         err,
1955                 },
1956                 /* unsupported type-mismatches */
1957                 {
1958                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1959                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1960                         err, err, err, err, err, err,
1961                 },
1962                 {
1963                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1964                         { SDB_TYPE_STRING, { .string = "20" } },
1965                         err, err, err, err, err, err,
1966                 },
1967                 {
1968                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1969                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1970                         err, err, err, err, err, err,
1971                 },
1972                 {
1973                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1974                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1975                         err, err, err, err, err, err,
1976                 },
1977                 {
1978                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1979                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1980                         err, err, err, err, err, err,
1981                 },
1982                 {
1983                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1984                         { SDB_TYPE_REGEX + 1, { .boolean = 0 } },
1985                         err, err, err, err, err, err,
1986                 },
1987                 {
1988                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1989                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
1990                         err, err, err, err, err, err,
1991                 },
1992                 {
1993                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1994                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1995                         err, err, err, err, err, err,
1996                 },
1997                 {
1998                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1999                         { SDB_TYPE_STRING, { .string = "20" } },
2000                         err, err, err, err, err, err,
2001                 },
2002                 {
2003                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2004                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2005                         err, err, err, err, err, err,
2006                 },
2007                 {
2008                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2009                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2010                         err, err, err, err, err, err,
2011                 },
2012                 {
2013                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2014                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2015                         err, err, err, err, err, err,
2016                 },
2017                 {
2018                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2019                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
2020                         err, err, err, err, err, err,
2021                 },
2022                 {
2023                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2024                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2025                         err, err, err, err, err, err,
2026                 },
2027                 {
2028                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2029                         { SDB_TYPE_STRING, { .string = "20.0" } },
2030                         err, err, err, err, err, err,
2031                 },
2032                 {
2033                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2034                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2035                         err, err, err, err, err, err,
2036                 },
2037                 {
2038                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2039                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2040                         err, err, err, err, err, err,
2041                 },
2042                 {
2043                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2044                         { SDB_TYPE_BINARY, { .binary = { 4, (unsigned char *)"20.0" } } },
2045                         err, err, err, err, err, err,
2046                 },
2047                 {
2048                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2049                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2050                         err, err, err, err, err, err,
2051                 },
2052                 {
2053                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2054                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
2055                         err, err, err, err, err, err,
2056                 },
2057                 {
2058                         { SDB_TYPE_STRING, { .string = "20" } },
2059                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2060                         err, err, err, err, err, err,
2061                 },
2062                 {
2063                         { SDB_TYPE_STRING, { .string = "20" } },
2064                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2065                         err, err, err, err, err, err,
2066                 },
2067                 {
2068                         { SDB_TYPE_STRING, { .string = "20" } },
2069                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2070                         err, err, err, err, err, err,
2071                 },
2072                 {
2073                         { SDB_TYPE_STRING, { .string = "20" } },
2074                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2075                         err, err, err, err, err, err,
2076                 },
2077                 {
2078                         { SDB_TYPE_STRING, { .string = "20" } },
2079                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2080                         err, err, err, err, err, err,
2081                 },
2082                 {
2083                         { SDB_TYPE_STRING, { .string = "20" } },
2084                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2085                         err, err, err, err, err, err,
2086                 },
2087                 {
2088                         { SDB_TYPE_STRING, { .string = "20" } },
2089                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
2090                         err, err, err, err, err, err,
2091                 },
2092                 {
2093                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2094                         { SDB_TYPE_STRING, { .string = "20" } },
2095                         err, err, err, err, err, err,
2096                 },
2097                 {
2098                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2099                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2100                         err, err, err, err, err, err,
2101                 },
2102                 {
2103                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2104                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2105                         err, err, err, err, err, err,
2106                 },
2107                 {
2108                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2109                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2110                         err, err, err, err, err, err,
2111                 },
2112                 {
2113                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2114                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
2115                         err, err, err, err, err, err,
2116                 },
2117                 {
2118                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2119                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2120                         err, err, err, err, err, err,
2121                 },
2122                 {
2123                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2124                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2125                         err, err, err, err, err, err,
2126                 },
2127                 {
2128                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2129                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2130                         err, err, err, err, err, err,
2131                 },
2132                 {
2133                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2134                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2135                         err, err, err, err, err, err,
2136                 },
2137                 {
2138                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2139                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2140                         err, err, err, err, err, err,
2141                 },
2142                 {
2143                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2144                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2145                         err, err, err, err, err, err,
2146                 },
2147                 {
2148                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2149                         { SDB_TYPE_STRING, { .string = "20" } },
2150                         err, err, err, err, err, err,
2151                 },
2152                 {
2153                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2154                         { SDB_TYPE_STRING, { .string = "20" } },
2155                         err, err, err, err, err, err,
2156                 },
2157                 {
2158                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2159                         { SDB_TYPE_STRING, { .string = "20" } },
2160                         err, err, err, err, err, err,
2161                 },
2162                 {
2163                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2164                         { SDB_TYPE_STRING, { .string = "20" } },
2165                         err, err, err, err, err, err,
2166                 },
2167                 {
2168                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2169                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2170                         err, err, err, err, err, err,
2171                 },
2172                 {
2173                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2174                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2175                         err, err, err, err, err, err,
2176                 },
2177                 {
2178                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2179                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
2180                         err, err, err, err, err, err,
2181                 },
2182                 {
2183                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2184                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
2185                         err, err, err, err, err, err,
2186                 },
2187                 {
2188                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2189                         { SDB_TYPE_INTEGER, { .integer = 20 } },
2190                         err, err, err, err, err, err,
2191                 },
2192                 {
2193                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2194                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
2195                         err, err, err, err, err, err,
2196                 },
2197                 {
2198                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2199                         { SDB_TYPE_STRING, { .string = "20" } },
2200                         err, err, err, err, err, err,
2201                 },
2202                 {
2203                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2204                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
2205                         err, err, err, err, err, err,
2206                 },
2207                 {
2208                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2209                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
2210                         err, err, err, err, err, err,
2211                 },
2212                 {
2213                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2214                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
2215                         err, err, err, err, err, err,
2216                 },
2217                 {
2218                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
2219                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
2220                         err, err, err, err, err, err,
2221                 },
2222         };
2224         size_t i;
2226         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
2227                 struct {
2228                         int op;
2229                         sdb_data_t expected;
2230                 } tests[] = {
2231                         { SDB_DATA_ADD, golden_data[i].expected_add },
2232                         { SDB_DATA_SUB, golden_data[i].expected_sub },
2233                         { SDB_DATA_MUL, golden_data[i].expected_mul },
2234                         { SDB_DATA_DIV, golden_data[i].expected_div },
2235                         { SDB_DATA_MOD, golden_data[i].expected_mod },
2236                         { SDB_DATA_CONCAT, golden_data[i].expected_concat },
2237                 };
2239                 size_t j;
2240                 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
2241                         sdb_data_t res;
2242                         int check;
2243                         int type1, type2, type;
2245                         char d1_str[64] = "", d2_str[64] = "";
2246                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
2247                                         SDB_DOUBLE_QUOTED);
2248                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
2249                                         SDB_DOUBLE_QUOTED);
2251                         type1 = golden_data[i].d1.type;
2252                         type2 = golden_data[i].d2.type;
2253                         if (sdb_data_isnull(&golden_data[i].d1))
2254                                 type1 = SDB_TYPE_NULL;
2255                         if (sdb_data_isnull(&golden_data[i].d2))
2256                                 type2 = SDB_TYPE_NULL;
2257                         type = sdb_data_expr_type(tests[j].op, type1, type2);
2259                         check = sdb_data_expr_eval(tests[j].op,
2260                                         &golden_data[i].d1, &golden_data[i].d2, &res);
2261                         fail_unless((check == 0) == (tests[j].expected.type != -1),
2262                                         "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
2263                                         SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
2264                                         tests[j].expected.type == -1 ? -1 : 0);
2266                         fail_unless(tests[j].expected.type == type,
2267                                         "sdb_data_expr_eval(%s, %s, %s) expected to evaluate "
2268                                         "to type %d while sdb_data_expr_type(%d, %d, %d) "
2269                                         "predicted type %d", SDB_DATA_OP_TO_STRING(tests[j].op),
2270                                         d1_str, d2_str, tests[j].expected.type,
2271                                         tests[j].op, golden_data[i].d1.type,
2272                                         golden_data[i].d2.type, type);
2274                         if (tests[j].expected.type == -1)
2275                                 continue;
2277                         if (tests[j].expected.type == SDB_TYPE_NULL) {
2278                                 fail_unless(res.type == SDB_TYPE_NULL,
2279                                                 "sdb_data_expr_eval(%s, %s, %s) evaluated to "
2280                                                 "type %d; expected: SDB_TYPE_NULL",
2281                                                 SDB_DATA_OP_TO_STRING(tests[j].op),
2282                                                 d1_str, d2_str, res.type);
2283                                 continue;
2284                         }
2286                         check = sdb_data_cmp(&res, &tests[j].expected);
2287                         if (check != 0) {
2288                                 char res_str[64] = "", expected_str[64] = "";
2289                                 sdb_data_format(&res, res_str, sizeof(res_str),
2290                                                 SDB_DOUBLE_QUOTED);
2291                                 sdb_data_format(&tests[j].expected, expected_str,
2292                                                 sizeof(expected_str), SDB_DOUBLE_QUOTED);
2293                                 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s "
2294                                                 "(type %d); expected: %s (type %d)",
2295                                                 SDB_DATA_OP_TO_STRING(tests[j].op),
2296                                                 d1_str, d2_str, res_str, res.type,
2297                                                 expected_str, tests[j].expected.type);
2298                         }
2300                         sdb_data_free_datum(&res);
2301                 }
2302         }
2304 END_TEST
2306 START_TEST(test_format)
2308         bool bool_values[] = { false, true, false };
2309         int64_t int_values[] = { 47, 11, 23 };
2310         char *string_values[] = { "foo", "bar", "qux", "baz" };
2312         struct {
2313                 sdb_data_t datum;
2314                 const char *expected;
2315         } golden_data[] = {
2316                 {
2317                         { SDB_TYPE_NULL, { .integer = 0 } },
2318                         "NULL",
2319                 },
2320                 {
2321                         { SDB_TYPE_BOOLEAN, { .boolean = true } },
2322                         "true",
2323                 },
2324                 {
2325                         { SDB_TYPE_BOOLEAN, { .boolean = false } },
2326                         "false",
2327                 },
2328                 {
2329                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
2330                         "4711",
2331                 },
2332                 {
2333                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
2334                         "65536",
2335                 },
2336                 {
2337                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
2338                         "12.3",
2339                 },
2340                 {
2341                         { SDB_TYPE_STRING, { .string = NULL } },
2342                         "NULL",
2343                 },
2344                 {
2345                         { SDB_TYPE_STRING, { .string = "this is a test" } },
2346                         "\"this is a test\"",
2347                 },
2348                 {
2349                         { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
2350                         "\"special \\\\ \\\" characters\"",
2351                 },
2352                 {
2353                         { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
2354                         "\"1984-12-06 02:11:54 +0000\"",
2355                 },
2356                 {
2357                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
2358                         "NULL",
2359                 },
2360                 {
2361                         {
2362                                 SDB_TYPE_BINARY,
2363                                 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
2364                         },
2365                         "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
2366                 },
2367                 {
2368                         { SDB_TYPE_REGEX, { .re = { "some regex", empty_re } } },
2369                         "\"/some regex/\"",
2370                 },
2371                 {
2372                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
2373                         "[]",
2374                 },
2375                 {
2376                         {
2377                                 SDB_TYPE_BOOLEAN | SDB_TYPE_ARRAY,
2378                                 { .array = { SDB_STATIC_ARRAY_LEN(bool_values), bool_values } },
2379                         },
2380                         "[false, true, false]",
2381                 },
2382                 {
2383                         {
2384                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
2385                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
2386                         },
2387                         "[47, 11, 23]",
2388                 },
2389                 {
2390                         {
2391                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
2392                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
2393                         },
2394                         "[\"foo\", \"bar\", \"qux\", \"baz\"]",
2395                 },
2396         };
2398         size_t i;
2400         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
2401                 sdb_data_t *datum = &golden_data[i].datum;
2402                 char buf[sdb_data_strlen(datum) + 2];
2403                 size_t check_null, check;
2405                 memset(buf, (int)'A', sizeof(buf));
2407                 check_null = sdb_data_format(datum, NULL, 0, SDB_DOUBLE_QUOTED);
2408                 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
2409                                 SDB_DOUBLE_QUOTED);
2410                 fail_unless(check > 0,
2411                                 "sdb_data_format(type=%s) = %d; expected: >0",
2412                                 SDB_TYPE_TO_STRING(datum->type), check);
2413                 fail_unless(! strcmp(buf, golden_data[i].expected),
2414                                 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
2415                                 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
2417                 fail_unless(check_null == check,
2418                                 "sdb_data_format(type=%s, NULL) = %d; "
2419                                 "expected %d (matching sdb_data_format(type=%s, <buf>))",
2420                                 SDB_TYPE_TO_STRING(datum->type), check_null,
2421                                 check, SDB_TYPE_TO_STRING(datum->type));
2422                 fail_unless(check == strlen(golden_data[i].expected),
2423                                 "sdb_data_format(type=%s) = %d; expected %zu (strlen)",
2424                                 SDB_TYPE_TO_STRING(datum->type), check,
2425                                 strlen(golden_data[i].expected));
2427                 fail_unless(check <= sizeof(buf) - 2,
2428                                 "sdb_data_format(type=%s) wrote %d bytes; "
2429                                 "expected <= %zu based on sdb_data_strlen()",
2430                                 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
2432                 fail_unless(buf[sizeof(buf) - 2] == '\0',
2433                                 "sdb_data_format(type=%s) did not nul-terminate the buffer",
2434                                 SDB_TYPE_TO_STRING(datum->type));
2435                 fail_unless(buf[sizeof(buf) - 1] == 'A',
2436                                 "sdb_data_format(type=%s) wrote past the end of the buffer",
2437                                 SDB_TYPE_TO_STRING(datum->type));
2438         }
2440 END_TEST
2442 START_TEST(test_parse)
2444         struct {
2445                 char *input;
2446                 sdb_data_t result;
2447                 int expected;
2448         } golden_data[] = {
2449                 { "true",    { SDB_TYPE_BOOLEAN,  { .boolean  = true } },          0 },
2450                 { "FALSE",   { SDB_TYPE_BOOLEAN,  { .boolean  = false } },         0 },
2451                 { "yes",     { SDB_TYPE_BOOLEAN,  { .boolean  = false } },        -1 },
2452                 { "4711",    { SDB_TYPE_INTEGER,  { .integer  = 4711 } },          0 },
2453                 { "0x10",    { SDB_TYPE_INTEGER,  { .integer  = 16 } },            0 },
2454                 { "010",     { SDB_TYPE_INTEGER,  { .integer  = 8 } },             0 },
2455                 { "abc",     { SDB_TYPE_INTEGER,  { .integer  = 0 } },            -1 },
2456                 { "1.2",     { SDB_TYPE_DECIMAL,  { .decimal  = 1.2 } },           0 },
2457                 { "0x1p+16", { SDB_TYPE_DECIMAL,  { .decimal  = 65536.0 } },       0 },
2458                 { "abc",     { SDB_TYPE_DECIMAL,  { .decimal  = 0.0 } },          -1 },
2459                 { "abc",     { SDB_TYPE_STRING,   { .string   = "abc" } },         0 },
2460                 { ".4",      { SDB_TYPE_DATETIME, { .datetime = 400000000 } },     0 },
2461                 { "abc",     { SDB_TYPE_DATETIME, { .datetime = 0 } },            -1 },
2462                 { "abc",     { SDB_TYPE_BINARY,
2463                                          { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
2464                 { "abc",     { SDB_TYPE_REGEX,    { .re = { "abc", empty_re } } }, 0 },
2465                 { "(|",      { SDB_TYPE_REGEX,    { .re = { "", empty_re } } },   -1 },
2466         };
2468         size_t i;
2470         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
2471                 sdb_data_t result;
2472                 int type, check;
2474                 memset(&result, 0, sizeof(result));
2475                 type = golden_data[i].result.type;
2476                 check = sdb_data_parse(golden_data[i].input, type, &result);
2477                 fail_unless(check == golden_data[i].expected,
2478                                 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
2479                                 golden_data[i].input, type, check, golden_data[i].expected);
2481                 if (check)
2482                         continue;
2484                 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
2485                                 "sdb_data_parse(%s, %d, <d>) did not create expected result",
2486                                 golden_data[i].input, type);
2488                 if (type == SDB_TYPE_STRING)
2489                         fail_unless(golden_data[i].input != result.data.string,
2490                                         "sdb_data_parse(%s, %d, <d>) copied input string",
2491                                         golden_data[i].input, type);
2492                 if (type == SDB_TYPE_BINARY)
2493                         fail_unless(golden_data[i].input != (char *)result.data.binary.datum,
2494                                         "sdb_data_parse(%s, %d, <d>) copied input string",
2495                                         golden_data[i].input, type);
2496                 if (type == SDB_TYPE_REGEX)
2497                         fail_unless(golden_data[i].input != result.data.re.raw,
2498                                         "sdb_data_parse(%s, %d, <d>) copied input string",
2499                                         golden_data[i].input, type);
2500                 sdb_data_free_datum(&result);
2501         }
2503 END_TEST
2505 TEST_MAIN("core::data")
2507         TCase *tc = tcase_create("core");
2508         tcase_add_test(tc, test_data);
2509         tcase_add_test(tc, test_cmp);
2510         tcase_add_test(tc, test_strcmp);
2511         tcase_add_test(tc, test_inarray);
2512         tcase_add_test(tc, test_array_get);
2513         tcase_add_test(tc, test_parse_op);
2514         tcase_add_test(tc, test_expr_eval);
2515         tcase_add_test(tc, test_format);
2516         tcase_add_test(tc, test_parse);
2517         ADD_TCASE(tc);
2519 TEST_MAIN_END
2521 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */