Code

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