Code

data: Let concat support empty arrays; add various tests for empty arrays.
[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 #include "core/data.h"
29 #include "libsysdb_test.h"
31 #include <assert.h>
32 #include <check.h>
34 static regex_t empty_re;
36 START_TEST(test_data)
37 {
38         sdb_data_t d1, d2;
39         int check;
41         int64_t int_values[] = { 47, 11, 23 };
42         char *string_values[] = { "foo", "bar", "qux" "baz" };
43         size_t i;
45         d2.type = SDB_TYPE_INTEGER;
46         d2.data.integer = 4711;
47         memset(&d1, 0, sizeof(d1));
48         check = sdb_data_copy(&d1, &d2);
49         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
50         fail_unless(d1.type == d2.type,
51                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
52                         d1.type, d2.type);
53         fail_unless(d1.data.integer == d2.data.integer,
54                         "sdb_data_copy() didn't copy integer data: got: %d; expected: %d",
55                         d1.data.integer, d2.data.integer);
57         d2.type = SDB_TYPE_DECIMAL;
58         d2.data.decimal = 47.11;
59         check = sdb_data_copy(&d1, &d2);
60         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
61         fail_unless(d1.type == d2.type,
62                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
63                         d1.type, d2.type);
64         fail_unless(d1.data.decimal == d2.data.decimal,
65                         "sdb_data_copy() didn't copy decimal data: got: %f; expected: %f",
66                         d1.data.decimal, d2.data.decimal);
68         d2.type = SDB_TYPE_STRING;
69         d2.data.string = "some string";
70         check = sdb_data_copy(&d1, &d2);
71         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
72         fail_unless(d1.type == d2.type,
73                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
74                         d1.type, d2.type);
75         fail_unless(!strcmp(d1.data.string, d2.data.string),
76                         "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
77                         d1.data.string, d2.data.string);
79         sdb_data_free_datum(&d1);
80         fail_unless(d1.data.string == NULL,
81                         "sdb_data_free_datum() didn't free string data");
83         d1.type = 0;
84         d2.type = SDB_TYPE_STRING;
85         d2.data.string = NULL;
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(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         d2.type = SDB_TYPE_DATETIME;
100         d2.data.datetime = 4711;
101         check = sdb_data_copy(&d1, &d2);
102         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
103         fail_unless(d1.type == d2.type,
104                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
105                         d1.type, d2.type);
106         fail_unless(d1.data.datetime == d2.data.datetime,
107                         "sdb_data_copy() didn't copy datetime data: got: %d; expected: %d",
108                         d1.data.datetime, d2.data.datetime);
110         d2.type = SDB_TYPE_BINARY;
111         d2.data.binary.datum = (unsigned char *)"some string";
112         d2.data.binary.length = strlen((const char *)d2.data.binary.datum);
113         check = sdb_data_copy(&d1, &d2);
114         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
115         fail_unless(d1.type == d2.type,
116                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
117                         d1.type, d2.type);
118         fail_unless(d1.data.binary.length == d2.data.binary.length,
119                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
120                         d1.data.binary.length, d2.data.binary.length);
121         fail_unless(!memcmp(d1.data.binary.datum, d2.data.binary.datum,
122                                 d2.data.binary.length),
123                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
124                         d1.data.binary.datum, d2.data.binary.datum);
126         sdb_data_free_datum(&d1);
127         fail_unless(d1.data.binary.length == 0,
128                         "sdb_data_free_datum() didn't reset binary datum length");
129         fail_unless(d1.data.binary.datum == NULL,
130                         "sdb_data_free_datum() didn't free binary datum");
132         d1.type = 0;
133         d2.type = SDB_TYPE_BINARY;
134         d2.data.binary.datum = NULL;
135         d2.data.binary.length = 0;
136         check = sdb_data_copy(&d1, &d2);
137         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
138         fail_unless(d1.type == d2.type,
139                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
140                         d1.type, d2.type);
141         fail_unless(d1.data.binary.length == d2.data.binary.length,
142                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
143                         d1.data.binary.length, d2.data.binary.length);
144         fail_unless(d1.data.binary.datum == d2.data.binary.datum,
145                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
146                         d1.data.binary.datum, d2.data.binary.datum);
148         sdb_data_free_datum(&d1);
149         fail_unless(d1.data.binary.length == 0,
150                         "sdb_data_free_datum() didn't reset binary datum length");
151         fail_unless(d1.data.binary.datum == NULL,
152                         "sdb_data_free_datum() didn't free binary datum");
154         check = sdb_data_parse(".", SDB_TYPE_REGEX, &d2);
155         fail_unless(check == 0,
156                         "INTERNAL ERROR: Failed to parse regex '.'");
157         assert(d2.type == SDB_TYPE_REGEX);
158         check = sdb_data_copy(&d1, &d2);
159         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
160         fail_unless(d1.type == d2.type,
161                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
162                         d1.type, d2.type);
163         fail_unless(d1.data.re.raw != d2.data.re.raw,
164                         "sdb_data_copy() copy string pointer");
165         fail_unless(!strcmp(d1.data.re.raw, d2.data.re.raw),
166                         "sdb_data_copy() didn't copy raw regex: got: %s; expected: %s",
167                         d1.data.re.raw, d2.data.re.raw);
168         sdb_data_free_datum(&d2);
170         sdb_data_free_datum(&d1);
171         fail_unless(d1.data.re.raw == NULL,
172                         "sdb_data_free_datum() didn't reset raw regex");
174         d2.type = SDB_TYPE_REGEX;
175         d2.data.re.raw = NULL;
176         check = sdb_data_copy(&d1, &d2);
177         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
178         fail_unless(d1.type == d2.type,
179                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
180                         d1.type, d2.type);
182         d2.type = SDB_TYPE_ARRAY | SDB_TYPE_INTEGER;
183         d2.data.array.length = SDB_STATIC_ARRAY_LEN(int_values);
184         d2.data.array.values = int_values;
185         check = sdb_data_copy(&d1, &d2);
186         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
187         fail_unless(d1.type == d2.type,
188                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
189                         d1.type, d2.type);
190         fail_unless(d1.data.array.values != d2.data.array.values,
191                         "sdb_data_copy() didn't copy values: got: %p; expected: %p",
192                         d1.data.array.values, d2.data.array.values);
193         for (i = 0; i < SDB_STATIC_ARRAY_LEN(int_values); ++i) {
194                 int *i1 = d1.data.array.values;
195                 int *i2 = d2.data.array.values;
196                 fail_unless(i1[i] == i2[i],
197                                 "sdb_data_copy() modified integer value %d: "
198                                 "got: %d; expected: %d", i, i1[i], i2[i]);
199         }
200         sdb_data_free_datum(&d1);
202         d2.type = SDB_TYPE_ARRAY | SDB_TYPE_STRING;
203         d2.data.array.length = SDB_STATIC_ARRAY_LEN(string_values);
204         d2.data.array.values = string_values;
205         check = sdb_data_copy(&d1, &d2);
206         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
207         fail_unless(d1.type == d2.type,
208                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
209                         d1.type, d2.type);
210         fail_unless(d1.data.array.values != d2.data.array.values,
211                         "sdb_data_copy() didn't copy values: got: %p; expected: %p",
212                         d1.data.array.values, d2.data.array.values);
213         for (i = 0; i < SDB_STATIC_ARRAY_LEN(string_values); ++i) {
214                 char **s1 = d1.data.array.values;
215                 char **s2 = d2.data.array.values;
216                 fail_unless(s1[i] != s2[i],
217                                 "sdb_data_copy() didn't copy string value %d", i);
218                 fail_unless(!strcmp(s1[i], s2[i]),
219                                 "sdb_data_copy() modified string value %d: "
220                                 "got: %s; expected: %s", i, s1[i], s2[i]);
221         }
222         sdb_data_free_datum(&d1);
224 END_TEST
226 START_TEST(test_cmp)
228         int64_t int_values1[] = { 1, 2, 3 };
229         int64_t int_values2[] = { 1, 3, 2 };
230         char *string_values1[] = { "a", "b", "c" };
231         char *string_values2[] = { "a", "c", "b" };
233         struct {
234                 sdb_data_t d1;
235                 sdb_data_t d2;
236                 int expected;
237         } golden_data[] = {
238                 {
239                         { SDB_TYPE_INTEGER, { .integer = 47 } },
240                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
241                         -1,
242                 },
243                 {
244                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
245                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
246                         0,
247                 },
248                 {
249                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
250                         { SDB_TYPE_INTEGER, { .integer = 47 } },
251                         1,
252                 },
253                 {
254                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
255                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
256                         -1,
257                 },
258                 {
259                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
260                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
261                         0,
262                 },
263                 {
264                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
265                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
266                         1,
267                 },
268                 {
269                         { SDB_TYPE_STRING, { .string = NULL } },
270                         { SDB_TYPE_STRING, { .string = "" } },
271                         -1,
272                 },
273                 {
274                         { SDB_TYPE_STRING, { .string = NULL } },
275                         { SDB_TYPE_STRING, { .string = NULL } },
276                         0,
277                 },
278                 {
279                         { SDB_TYPE_STRING, { .string = "" } },
280                         { SDB_TYPE_STRING, { .string = NULL } },
281                         1,
282                 },
283                 {
284                         { SDB_TYPE_STRING, { .string = "a" } },
285                         { SDB_TYPE_STRING, { .string = "b" } },
286                         -1,
287                 },
288                 {
289                         { SDB_TYPE_STRING, { .string = "a" } },
290                         { SDB_TYPE_STRING, { .string = "ab" } },
291                         -1,
292                 },
293                 {
294                         { SDB_TYPE_STRING, { .string = "a" } },
295                         { SDB_TYPE_STRING, { .string = "a" } },
296                         0,
297                 },
298                 {
299                         { SDB_TYPE_STRING, { .string = "b" } },
300                         { SDB_TYPE_STRING, { .string = "a" } },
301                         1,
302                 },
303                 {
304                         { SDB_TYPE_STRING, { .string = "ab" } },
305                         { SDB_TYPE_STRING, { .string = "a" } },
306                         1,
307                 },
308                 {
309                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
310                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
311                         -1,
312                 },
313                 {
314                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
315                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
316                         0,
317                 },
318                 {
319                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
320                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
321                         1,
322                 },
323                 {
324                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
325                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
326                         -1,
327                 },
328                 {
329                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
330                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
331                         0,
332                 },
333                 {
334                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
335                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
336                         1,
337                 },
338                 {
339                         {
340                                 SDB_TYPE_BINARY,
341                                 { .binary = { 3, (unsigned char *)"a\0a" } },
342                         },
343                         {
344                                 SDB_TYPE_BINARY,
345                                 { .binary = { 3, (unsigned char *)"a\0b" } },
346                         },
347                         -1,
348                 },
349                 {
350                         {
351                                 SDB_TYPE_BINARY,
352                                 { .binary = { 1, (unsigned char *)"a" } },
353                         },
354                         {
355                                 SDB_TYPE_BINARY,
356                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
357                         },
358                         -1,
359                 },
360                 {
361                         {
362                                 SDB_TYPE_BINARY,
363                                 { .binary = { 3, (unsigned char *)"a\0a" } },
364                         },
365                         {
366                                 SDB_TYPE_BINARY,
367                                 { .binary = { 3, (unsigned char *)"a\0a" } },
368                         },
369                         0,
370                 },
371                 {
372                         {
373                                 SDB_TYPE_BINARY,
374                                 { .binary = { 3, (unsigned char *)"a\0b" } },
375                         },
376                         {
377                                 SDB_TYPE_BINARY,
378                                 { .binary = { 3, (unsigned char *)"a\0a" } },
379                         },
380                         1,
381                 },
382                 {
383                         {
384                                 SDB_TYPE_BINARY,
385                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
386                         },
387                         {
388                                 SDB_TYPE_BINARY,
389                                 { .binary = { 1, (unsigned char *)"a" } },
390                         },
391                         1,
392                 },
393                 {
394                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
395                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
396                         0,
397                 },
398                 {
399                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
400                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
401                         -1,
402                 },
403                 {
404                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
405                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
406                         1,
407                 },
408                 {
409                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
410                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
411                         0,
412                 },
413                 {
414                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
415                         {
416                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
417                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
418                         },
419                         -1,
420                 },
421                 {
422                         {
423                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
424                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
425                         },
426                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
427                         1,
428                 },
429                 {
430                         {
431                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
432                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
433                         },
434                         {
435                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
436                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
437                         },
438                         0,
439                 },
440                 {
441                         {
442                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
443                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
444                         },
445                         {
446                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
447                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
448                         },
449                         -1,
450                 },
451                 {
452                         {
453                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
454                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
455                         },
456                         {
457                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
458                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
459                         },
460                         1,
461                 },
462                 {
463                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
464                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
465                         0,
466                 },
467                 {
468                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
469                         {
470                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
471                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
472                         },
473                         -1,
474                 },
475                 {
476                         {
477                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
478                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
479                         },
480                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
481                         1,
482                 },
483                 {
484                         {
485                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
486                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
487                         },
488                         {
489                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
490                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
491                         },
492                         0,
493                 },
494                 {
495                         {
496                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
497                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
498                         },
499                         {
500                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
501                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
502                         },
503                         -1,
504                 },
505                 {
506                         {
507                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
508                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
509                         },
510                         {
511                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
512                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
513                         },
514                         1,
515                 },
516         };
518         size_t i;
520         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
521                 int check = sdb_data_cmp(&golden_data[i].d1, &golden_data[i].d2);
522                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
523                 if (check != golden_data[i].expected) {
524                         char d1_str[64] = "", d2_str[64] = "";
525                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
526                                         SDB_DOUBLE_QUOTED);
527                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
528                                         SDB_DOUBLE_QUOTED);
529                         fail("sdb_data_cmp(%s, %s) = %d; expected: %d",
530                                         d1_str, d2_str, check, golden_data[i].expected);
531                 }
532         }
534 END_TEST
536 START_TEST(test_strcmp)
538         struct {
539                 sdb_data_t d1;
540                 sdb_data_t d2;
541                 int expected;
542         } golden_data[] = {
543                 /* same data as for the sdb_data_cmp test; in case the types match,
544                  * both functions should behave the same (except for some loss in
545                  * precision, e.g. when formatting datetime values) */
546                 {
547                         { SDB_TYPE_INTEGER, { .integer = 47 } },
548                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
549                         -1,
550                 },
551                 {
552                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
553                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
554                         0,
555                 },
556                 {
557                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
558                         { SDB_TYPE_INTEGER, { .integer = 47 } },
559                         1,
560                 },
561                 {
562                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
563                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
564                         -1,
565                 },
566                 {
567                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
568                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
569                         0,
570                 },
571                 {
572                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
573                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
574                         1,
575                 },
576                 {
577                         { SDB_TYPE_STRING, { .string = NULL } },
578                         { SDB_TYPE_STRING, { .string = "" } },
579                         -1,
580                 },
581                 {
582                         { SDB_TYPE_STRING, { .string = NULL } },
583                         { SDB_TYPE_STRING, { .string = NULL } },
584                         0,
585                 },
586                 {
587                         { SDB_TYPE_STRING, { .string = "" } },
588                         { SDB_TYPE_STRING, { .string = NULL } },
589                         1,
590                 },
591                 {
592                         { SDB_TYPE_STRING, { .string = "a" } },
593                         { SDB_TYPE_STRING, { .string = "b" } },
594                         -1,
595                 },
596                 {
597                         { SDB_TYPE_STRING, { .string = "a" } },
598                         { SDB_TYPE_STRING, { .string = "ab" } },
599                         -1,
600                 },
601                 {
602                         { SDB_TYPE_STRING, { .string = "a" } },
603                         { SDB_TYPE_STRING, { .string = "a" } },
604                         0,
605                 },
606                 {
607                         { SDB_TYPE_STRING, { .string = "b" } },
608                         { SDB_TYPE_STRING, { .string = "a" } },
609                         1,
610                 },
611                 {
612                         { SDB_TYPE_STRING, { .string = "ab" } },
613                         { SDB_TYPE_STRING, { .string = "a" } },
614                         1,
615                 },
616                 {
617                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
618                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
619                         -1,
620                 },
621                 {
622                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
623                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
624                         0,
625                 },
626                 {
627                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
628                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
629                         1,
630                 },
631                 {
632                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
633                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
634                         -1,
635                 },
636                 {
637                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
638                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
639                         0,
640                 },
641                 {
642                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
643                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
644                         1,
645                 },
646                 {
647                         {
648                                 SDB_TYPE_BINARY,
649                                 { .binary = { 3, (unsigned char *)"a\0a" } },
650                         },
651                         {
652                                 SDB_TYPE_BINARY,
653                                 { .binary = { 3, (unsigned char *)"a\0b" } },
654                         },
655                         -1,
656                 },
657                 {
658                         {
659                                 SDB_TYPE_BINARY,
660                                 { .binary = { 1, (unsigned char *)"a" } },
661                         },
662                         {
663                                 SDB_TYPE_BINARY,
664                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
665                         },
666                         -1,
667                 },
668                 {
669                         {
670                                 SDB_TYPE_BINARY,
671                                 { .binary = { 3, (unsigned char *)"a\0a" } },
672                         },
673                         {
674                                 SDB_TYPE_BINARY,
675                                 { .binary = { 3, (unsigned char *)"a\0a" } },
676                         },
677                         0,
678                 },
679                 {
680                         {
681                                 SDB_TYPE_BINARY,
682                                 { .binary = { 3, (unsigned char *)"a\0b" } },
683                         },
684                         {
685                                 SDB_TYPE_BINARY,
686                                 { .binary = { 3, (unsigned char *)"a\0a" } },
687                         },
688                         1,
689                 },
690                 {
691                         {
692                                 SDB_TYPE_BINARY,
693                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
694                         },
695                         {
696                                 SDB_TYPE_BINARY,
697                                 { .binary = { 1, (unsigned char *)"a" } },
698                         },
699                         1,
700                 },
701                 {
702                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
703                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
704                         0,
705                 },
706                 {
707                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
708                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
709                         -1,
710                 },
711                 {
712                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
713                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
714                         1,
715                 },
716                 /* type mismatches */
717                 {
718                         { SDB_TYPE_INTEGER, { .integer = 123 } },
719                         { SDB_TYPE_STRING, { .string = "123" } },
720                         0,
721                 },
722                 {
723                         { SDB_TYPE_INTEGER, { .integer = 120 } },
724                         { SDB_TYPE_STRING, { .string = "123" } },
725                         -1,
726                 },
727                 {
728                         { SDB_TYPE_STRING, { .string = "123" } },
729                         { SDB_TYPE_INTEGER, { .integer = 120 } },
730                         1,
731                 },
732                 {
733                         { SDB_TYPE_STRING, { .string = "12.3" } },
734                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
735                         0,
736                 },
737                 {
738                         { SDB_TYPE_STRING, { .string = "12.0" } },
739                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
740                         -1,
741                 },
742                 {
743                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
744                         { SDB_TYPE_STRING, { .string = "12.0" } },
745                         1,
746                 },
747                 {
748                         { SDB_TYPE_REGEX, { .re = { "regex", empty_re } } },
749                         { SDB_TYPE_STRING, { .string = "/regex/" } },
750                         0,
751                 },
752                 /* TODO: add support for arrays */
753         };
755         size_t i;
757         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
758                 int check = sdb_data_strcmp(&golden_data[i].d1, &golden_data[i].d2);
759                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
760                 if (check != golden_data[i].expected) {
761                         char d1_str[64] = "", d2_str[64] = "";
762                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
763                                         SDB_DOUBLE_QUOTED);
764                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
765                                         SDB_DOUBLE_QUOTED);
766                         fail("sdb_data_strcmp(%s, %s) = %d; expected: %d",
767                                         d1_str, d2_str, check, golden_data[i].expected);
768                 }
769         }
771 END_TEST
773 START_TEST(test_inarray)
775         int64_t int_values[] = { 47, 11, 64 };
776         int64_t int_values2[] = { 64, 11 };
777         int64_t int_values3[] = { 47, 11, 42 };
778         double dec_values[] = { 12.3, 47.11, 64.0 };
779         double dec_values2[] = { 12.3, 47.11 };
780         double dec_values3[] = { 2.3, 47.11 };
781         char *string_values[] = { "foo", "bar", "qux", "baz" };
782         char *string_values2[] = { "qux", "bar" };
783         char *string_values3[] = { "foo", "bar", "qux", "baz", "bay" };
785         sdb_data_t int_array = {
786                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
787                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } }
788         };
789         sdb_data_t int_array2 = {
790                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
791                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } }
792         };
793         sdb_data_t int_array3 = {
794                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
795                 { .array = { SDB_STATIC_ARRAY_LEN(int_values3), int_values3 } }
796         };
797         sdb_data_t dec_array = {
798                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
799                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } }
800         };
801         sdb_data_t dec_array2 = {
802                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
803                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values2), dec_values2 } }
804         };
805         sdb_data_t dec_array3 = {
806                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
807                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values3), dec_values3 } }
808         };
809         sdb_data_t string_array = {
810                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
811                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } }
812         };
813         sdb_data_t string_array2 = {
814                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
815                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } }
816         };
817         sdb_data_t string_array3 = {
818                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
819                 { .array = { SDB_STATIC_ARRAY_LEN(string_values3), string_values3 } }
820         };
822         struct {
823                 sdb_data_t value;
824                 sdb_data_t array;
825                 _Bool expected;
826         } golden_data[] = {
827                 { { SDB_TYPE_INTEGER, { .integer = 47    } }, int_array,    1 },
828                 { { SDB_TYPE_INTEGER, { .integer = 11    } }, int_array,    1 },
829                 { { SDB_TYPE_INTEGER, { .integer = 64    } }, int_array,    1 },
830                 { { SDB_TYPE_INTEGER, { .integer = 65    } }, int_array,    0 },
831                 { { SDB_TYPE_NULL,    { .integer = 0     } }, int_array,    0 },
832                 { { SDB_TYPE_DECIMAL, { .decimal = 12.3  } }, dec_array,    1 },
833                 { { SDB_TYPE_DECIMAL, { .decimal = 47.11 } }, dec_array,    1 },
834                 { { SDB_TYPE_DECIMAL, { .decimal = 64.0  } }, dec_array,    1 },
835                 { { SDB_TYPE_DECIMAL, { .decimal = 60.0  } }, dec_array,    0 },
836                 { { SDB_TYPE_INTEGER, { .integer = 64    } }, dec_array,    0 },
837                 { { SDB_TYPE_NULL,    { .integer = 0     } }, dec_array,    0 },
838                 { { SDB_TYPE_STRING,  { .string  = "Foo" } }, string_array, 1 },
839                 { { SDB_TYPE_STRING,  { .string  = "FOO" } }, string_array, 1 },
840                 { { SDB_TYPE_STRING,  { .string  = "foo" } }, string_array, 1 },
841                 { { SDB_TYPE_STRING,  { .string  = "bar" } }, string_array, 1 },
842                 { { SDB_TYPE_STRING,  { .string  = "qux" } }, string_array, 1 },
843                 { { SDB_TYPE_STRING,  { .string  = "baz" } }, string_array, 1 },
844                 { { SDB_TYPE_STRING,  { .string  = "ba"  } }, string_array, 0 },
845                 { { SDB_TYPE_STRING,  { .string  = "abc" } }, string_array, 0 },
846                 { { SDB_TYPE_NULL,    { .integer = 0     } }, string_array, 0 },
847                 { int_array, { SDB_TYPE_INTEGER, { .integer = 47 } },       0 },
848                 { int_array,     int_array,    1 },
849                 { int_array2,    int_array,    1 },
850                 { int_array3,    int_array,    0 },
851                 { dec_array2,    int_array,    0 },
852                 { string_array2, int_array,    0 },
853                 { dec_array,     dec_array,    1 },
854                 { dec_array2,    dec_array,    1 },
855                 { dec_array3,    dec_array,    0 },
856                 { int_array2,    dec_array,    0 },
857                 { string_array2, dec_array,    0 },
858                 { string_array,  string_array, 1 },
859                 { string_array2, string_array, 1 },
860                 { string_array3, string_array, 0 },
861                 { int_array2,    string_array, 0 },
862                 { dec_array2,    string_array, 0 },
863                 {
864                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
865                         int_array, 1,
866                 },
867                 {
868                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
869                         dec_array, 0,
870                 },
871                 {
872                         { SDB_TYPE_DECIMAL | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
873                         dec_array, 1,
874                 },
875                 {
876                         { SDB_TYPE_DECIMAL | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
877                         int_array, 0,
878                 },
879                 {
880                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
881                         string_array, 1,
882                 },
883                 {
884                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
885                         dec_array, 0,
886                 },
887         };
889         size_t i;
891         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
892                 char v_str[1024] = "", a_str[1024] = "";
893                 _Bool check;
895                 sdb_data_format(&golden_data[i].value,
896                                 v_str, sizeof(v_str), SDB_UNQUOTED);
897                 sdb_data_format(&golden_data[i].array,
898                                 a_str, sizeof(a_str), SDB_UNQUOTED);
900                 check = sdb_data_inarray(&golden_data[i].value, &golden_data[i].array);
901                 fail_unless(check == golden_data[i].expected,
902                                 "sdb_data_inarray(%s, %s) = %d; expected: %d",
903                                 v_str, a_str, check, golden_data[i].expected);
904         }
906 END_TEST
908 START_TEST(test_array_get)
910         int64_t int_values[] = { 47, 11, 64 };
911         double dec_values[] = { 12.3, 47.11, 64.0 };
912         char *string_values[] = { "foo", "bar", "qux", "baz" };
914         sdb_data_t int_array = {
915                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
916                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } }
917         };
918         sdb_data_t dec_array = {
919                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
920                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } }
921         };
922         sdb_data_t string_array = {
923                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
924                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } }
925         };
927         struct {
928                 sdb_data_t array;
929                 size_t i;
930                 sdb_data_t expected;
931         } golden_data[] = {
932                 { int_array, 0, { SDB_TYPE_INTEGER, { .integer = 47 } } },
933                 { int_array, 1, { SDB_TYPE_INTEGER, { .integer = 11 } } },
934                 { int_array, 2, { SDB_TYPE_INTEGER, { .integer = 64 } } },
935                 { int_array, 3, { -1, { .integer = 0 } } },
936                 { dec_array, 0, { SDB_TYPE_DECIMAL, { .decimal = 12.3 } } },
937                 { dec_array, 1, { SDB_TYPE_DECIMAL, { .decimal = 47.11 } } },
938                 { dec_array, 2, { SDB_TYPE_DECIMAL, { .decimal = 64.0 } } },
939                 { dec_array, 3, { -1, { .integer = 0 } } },
940                 { string_array, 0, { SDB_TYPE_STRING, { .string = "foo" } } },
941                 { string_array, 1, { SDB_TYPE_STRING, { .string = "bar" } } },
942                 { string_array, 2, { SDB_TYPE_STRING, { .string = "qux" } } },
943                 { string_array, 3, { SDB_TYPE_STRING, { .string = "baz" } } },
944                 { string_array, 4, { -1, { .integer = 0 } } },
945                 { { SDB_TYPE_INTEGER, { .integer = 666 } }, 0, { -1, { .integer = 0 } } },
946                 { { SDB_TYPE_INTEGER, { .integer = 666 } }, 1, { -1, { .integer = 0 } } },
947                 {
948                         { SDB_TYPE_ARRAY | SDB_TYPE_INTEGER, { .array = { 0, NULL } } },
949                         0, { -1, { .integer = 0 } },
950                 },
951                 {
952                         { SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL, { .array = { 0, NULL } } },
953                         0, { -1, { .integer = 0 } },
954                 },
955                 {
956                         { SDB_TYPE_ARRAY | SDB_TYPE_STRING, { .array = { 0, NULL } } },
957                         0, { -1, { .integer = 0 } },
958                 },
959         };
961         size_t i;
963         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
964                 char a_str[1024] = "", v_str[1024] = "", exp_str[1024] = "";
965                 sdb_data_t value = SDB_DATA_INIT;
966                 int check;
968                 sdb_data_format(&golden_data[i].array,
969                                 a_str, sizeof(a_str), SDB_UNQUOTED);
970                 sdb_data_format(&golden_data[i].expected,
971                                 exp_str, sizeof(exp_str), SDB_UNQUOTED);
973                 check = sdb_data_array_get(&golden_data[i].array,
974                                 golden_data[i].i, &value);
976                 sdb_data_format(&value, v_str, sizeof(v_str), SDB_UNQUOTED);
978                 if (golden_data[i].expected.type < 0) {
979                         fail_unless(check < 0,
980                                         "sdb_data_array_get(%s, %zu) = %d (%s); expected: <0",
981                                         a_str, golden_data[i].i, check, v_str);
982                         continue;
983                 }
985                 fail_unless(check == 0,
986                                 "sdb_data_array_get(%s, %zu) = %d; expected: 0",
987                                 a_str, golden_data[i].i, check);
988                 fail_unless(! sdb_data_cmp(&value, &golden_data[i].expected),
989                                 "sdb_data_array_get(%s, %zu) -> '%s'; expected: '%s'",
990                                 a_str, golden_data[i].i, v_str, exp_str);
991         }
993 END_TEST
995 START_TEST(test_parse_op)
997         struct {
998                 const char *op;
999                 int id;
1000         } golden_data[] = {
1001                 { "+",  SDB_DATA_ADD },
1002                 { "-",  SDB_DATA_SUB },
1003                 { "*",  SDB_DATA_MUL },
1004                 { "/",  SDB_DATA_DIV },
1005                 { "%",  SDB_DATA_MOD },
1006                 { "||", SDB_DATA_CONCAT },
1007                 { "&&", -1 },
1008         };
1010         size_t i;
1012         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1013                 const char *op;
1014                 int id;
1016                 id = sdb_data_parse_op(golden_data[i].op);
1017                 fail_unless(id == golden_data[i].id,
1018                                 "sdb_data_parse_op(%s) = %d; expected: %d",
1019                                 golden_data[i].op, id, golden_data[i].id);
1021                 if (id <= 0)
1022                         continue;
1024                 op = SDB_DATA_OP_TO_STRING(id);
1025                 fail_unless(!strcmp(op, golden_data[i].op),
1026                                 "SDB_DATA_OP_TO_STRING(%d) = '%s'; expected: '%s'",
1027                                 id, op, golden_data[i].op);
1028         }
1030 END_TEST
1032 START_TEST(test_expr_eval)
1034         sdb_data_t err = { -1, { .integer = 0 } };
1036         int64_t int_values[] = { 47, 11, 23 };
1037         int64_t expected_int_append[] = { 47, 11, 23, 42 };
1038         int64_t expected_int_prepend[] = { 42, 47, 11, 23 };
1039         int64_t expected_int_concat[] = { 47, 11, 23, 47, 11, 23 };
1040         char *string_values[] = { "foo", "bar", "qux" "baz" };
1041         char *expected_string_append[] = { "foo", "bar", "qux" "baz", "bay" };
1042         char *expected_string_prepend[] = { "bay", "foo", "bar", "qux" "baz" };
1043         char *expected_string_concat[] =
1044                 { "foo", "bar", "qux" "baz", "foo", "bar", "qux" "baz" };
1046         struct {
1047                 sdb_data_t d1;
1048                 sdb_data_t d2;
1049                 sdb_data_t expected_add;
1050                 sdb_data_t expected_sub;
1051                 sdb_data_t expected_mul;
1052                 sdb_data_t expected_div;
1053                 sdb_data_t expected_mod;
1054                 sdb_data_t expected_concat;
1055         } golden_data[] = {
1056                 {
1057                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
1058                         { SDB_TYPE_INTEGER, { .integer = 47 } },
1059                         { SDB_TYPE_INTEGER, { .integer = 4758 } },
1060                         { SDB_TYPE_INTEGER, { .integer = 4664 } },
1061                         { SDB_TYPE_INTEGER, { .integer = 221417 } },
1062                         { SDB_TYPE_INTEGER, { .integer = 100 } },
1063                         { SDB_TYPE_INTEGER, { .integer = 11 } },
1064                         err,
1065                 },
1066                 {
1067                         { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
1068                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
1069                         { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
1070                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
1071                         { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
1072                         { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
1073                         { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
1074                         err,
1075                 },
1076                 {
1077                         { SDB_TYPE_STRING, { .string = NULL } },
1078                         { SDB_TYPE_STRING, { .string = "" } },
1079                         SDB_DATA_NULL,
1080                         SDB_DATA_NULL,
1081                         SDB_DATA_NULL,
1082                         SDB_DATA_NULL,
1083                         SDB_DATA_NULL,
1084                         SDB_DATA_NULL,
1085                 },
1086                 {
1087                         { SDB_TYPE_STRING, { .string = NULL } },
1088                         { SDB_TYPE_STRING, { .string = NULL } },
1089                         SDB_DATA_NULL,
1090                         SDB_DATA_NULL,
1091                         SDB_DATA_NULL,
1092                         SDB_DATA_NULL,
1093                         SDB_DATA_NULL,
1094                         SDB_DATA_NULL,
1095                 },
1096                 {
1097                         { SDB_TYPE_STRING, { .string = "" } },
1098                         { SDB_TYPE_STRING, { .string = NULL } },
1099                         SDB_DATA_NULL,
1100                         SDB_DATA_NULL,
1101                         SDB_DATA_NULL,
1102                         SDB_DATA_NULL,
1103                         SDB_DATA_NULL,
1104                         SDB_DATA_NULL,
1105                 },
1106                 {
1107                         { SDB_TYPE_STRING, { .string = "a" } },
1108                         { SDB_TYPE_STRING, { .string = "b" } },
1109                         err,
1110                         err,
1111                         err,
1112                         err,
1113                         err,
1114                         { SDB_TYPE_STRING, { .string = "ab" } },
1115                 },
1116                 {
1117                         { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
1118                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1119                         { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
1120                         { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
1121                         { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
1122                         { SDB_TYPE_DATETIME, { .datetime = 10001 } },
1123                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1124                         err,
1125                 },
1126                 {
1127                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1128                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1129                         SDB_DATA_NULL,
1130                         SDB_DATA_NULL,
1131                         SDB_DATA_NULL,
1132                         SDB_DATA_NULL,
1133                         SDB_DATA_NULL,
1134                         SDB_DATA_NULL,
1135                 },
1136                 {
1137                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1138                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1139                         SDB_DATA_NULL,
1140                         SDB_DATA_NULL,
1141                         SDB_DATA_NULL,
1142                         SDB_DATA_NULL,
1143                         SDB_DATA_NULL,
1144                         SDB_DATA_NULL,
1145                 },
1146                 {
1147                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1148                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1149                         SDB_DATA_NULL,
1150                         SDB_DATA_NULL,
1151                         SDB_DATA_NULL,
1152                         SDB_DATA_NULL,
1153                         SDB_DATA_NULL,
1154                         SDB_DATA_NULL,
1155                 },
1156                 {
1157                         {
1158                                 SDB_TYPE_BINARY,
1159                                 { .binary = { 3, (unsigned char *)"a\0a" } },
1160                         },
1161                         {
1162                                 SDB_TYPE_BINARY,
1163                                 { .binary = { 3, (unsigned char *)"b\0b" } },
1164                         },
1165                         err,
1166                         err,
1167                         err,
1168                         err,
1169                         err,
1170                         {
1171                                 SDB_TYPE_BINARY,
1172                                 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
1173                         },
1174                 },
1175                 {
1176                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1177                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1178                         err,
1179                         err,
1180                         err,
1181                         err,
1182                         err,
1183                         err,
1184                 },
1185                 {
1186                         {
1187                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1188                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1189                         },
1190                         {
1191                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1192                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1193                         },
1194                         err,
1195                         err,
1196                         err,
1197                         err,
1198                         err,
1199                         {
1200                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1201                                 { .array = {
1202                                                 SDB_STATIC_ARRAY_LEN(expected_int_concat),
1203                                                 expected_int_concat
1204                                 } },
1205                         },
1206                 },
1207                 {
1208                         {
1209                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1210                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1211                         },
1212                         { SDB_TYPE_INTEGER, { .integer = 42 }, },
1213                         err,
1214                         err,
1215                         err,
1216                         err,
1217                         err,
1218                         {
1219                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1220                                 { .array = {
1221                                                 SDB_STATIC_ARRAY_LEN(expected_int_append),
1222                                                 expected_int_append
1223                                 } },
1224                         },
1225                 },
1226                 {
1227                         { SDB_TYPE_INTEGER, { .integer = 42 }, },
1228                         {
1229                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1230                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1231                         },
1232                         err,
1233                         err,
1234                         err,
1235                         err,
1236                         err,
1237                         {
1238                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1239                                 { .array = {
1240                                                 SDB_STATIC_ARRAY_LEN(expected_int_prepend),
1241                                                 expected_int_prepend
1242                                 } },
1243                         },
1244                 },
1245                 {
1246                         {
1247                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1248                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1249                         },
1250                         {
1251                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1252                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1253                         },
1254                         err,
1255                         err,
1256                         err,
1257                         err,
1258                         err,
1259                         {
1260                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1261                                 { .array = {
1262                                                 SDB_STATIC_ARRAY_LEN(expected_string_concat),
1263                                                 expected_string_concat
1264                                 } },
1265                         },
1266                 },
1267                 {
1268                         {
1269                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1270                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1271                         },
1272                         { SDB_TYPE_STRING, { .string = "bay" } },
1273                         err,
1274                         err,
1275                         err,
1276                         err,
1277                         err,
1278                         {
1279                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1280                                 { .array = {
1281                                                 SDB_STATIC_ARRAY_LEN(expected_string_append),
1282                                                 expected_string_append
1283                                 } },
1284                         },
1285                 },
1286                 {
1287                         { SDB_TYPE_STRING, { .string = "bay" } },
1288                         {
1289                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1290                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1291                         },
1292                         err,
1293                         err,
1294                         err,
1295                         err,
1296                         err,
1297                         {
1298                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1299                                 { .array = {
1300                                                 SDB_STATIC_ARRAY_LEN(expected_string_prepend),
1301                                                 expected_string_prepend
1302                                 } },
1303                         },
1304                 },
1305                 {
1306                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1307                         {
1308                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1309                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1310                         },
1311                         err,
1312                         err,
1313                         err,
1314                         err,
1315                         err,
1316                         {
1317                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1318                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1319                         },
1320                 },
1321                 {
1322                         {
1323                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1324                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1325                         },
1326                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1327                         err,
1328                         err,
1329                         err,
1330                         err,
1331                         err,
1332                         {
1333                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1334                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1335                         },
1336                 },
1337                 {
1338                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1339                         {
1340                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1341                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1342                         },
1343                         err,
1344                         err,
1345                         err,
1346                         err,
1347                         err,
1348                         {
1349                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1350                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1351                         },
1352                 },
1353                 {
1354                         {
1355                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1356                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1357                         },
1358                         { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1359                         err,
1360                         err,
1361                         err,
1362                         err,
1363                         err,
1364                         {
1365                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1366                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1367                         },
1368                 },
1369                 {
1370                         { SDB_TYPE_NULL, { .integer = 0 } },
1371                         { SDB_TYPE_NULL, { .integer = 0 } },
1372                         SDB_DATA_NULL,
1373                         SDB_DATA_NULL,
1374                         SDB_DATA_NULL,
1375                         SDB_DATA_NULL,
1376                         SDB_DATA_NULL,
1377                         SDB_DATA_NULL,
1378                 },
1379                 {
1380                         { SDB_TYPE_NULL, { .integer = 0 } },
1381                         { SDB_TYPE_INTEGER, { .integer = 42 } },
1382                         SDB_DATA_NULL,
1383                         SDB_DATA_NULL,
1384                         SDB_DATA_NULL,
1385                         SDB_DATA_NULL,
1386                         SDB_DATA_NULL,
1387                         SDB_DATA_NULL,
1388                 },
1389                 {
1390                         { SDB_TYPE_INTEGER, { .integer = 42 } },
1391                         { SDB_TYPE_NULL, { .integer = 0 } },
1392                         SDB_DATA_NULL,
1393                         SDB_DATA_NULL,
1394                         SDB_DATA_NULL,
1395                         SDB_DATA_NULL,
1396                         SDB_DATA_NULL,
1397                         SDB_DATA_NULL,
1398                 },
1399                 {
1400                         { SDB_TYPE_NULL, { .integer = 0 } },
1401                         { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
1402                         SDB_DATA_NULL,
1403                         SDB_DATA_NULL,
1404                         SDB_DATA_NULL,
1405                         SDB_DATA_NULL,
1406                         SDB_DATA_NULL,
1407                         SDB_DATA_NULL,
1408                 },
1409                 {
1410                         { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
1411                         { SDB_TYPE_NULL, { .integer = 0 } },
1412                         SDB_DATA_NULL,
1413                         SDB_DATA_NULL,
1414                         SDB_DATA_NULL,
1415                         SDB_DATA_NULL,
1416                         SDB_DATA_NULL,
1417                         SDB_DATA_NULL,
1418                 },
1419                 {
1420                         { SDB_TYPE_NULL, { .integer = 0 } },
1421                         { SDB_TYPE_STRING, { .string = "47.11" } },
1422                         SDB_DATA_NULL,
1423                         SDB_DATA_NULL,
1424                         SDB_DATA_NULL,
1425                         SDB_DATA_NULL,
1426                         SDB_DATA_NULL,
1427                         SDB_DATA_NULL,
1428                 },
1429                 {
1430                         { SDB_TYPE_STRING, { .string = "47.11" } },
1431                         { SDB_TYPE_NULL, { .integer = 0 } },
1432                         SDB_DATA_NULL,
1433                         SDB_DATA_NULL,
1434                         SDB_DATA_NULL,
1435                         SDB_DATA_NULL,
1436                         SDB_DATA_NULL,
1437                         SDB_DATA_NULL,
1438                 },
1439                 {
1440                         { SDB_TYPE_NULL, { .integer = 0 } },
1441                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1442                         SDB_DATA_NULL,
1443                         SDB_DATA_NULL,
1444                         SDB_DATA_NULL,
1445                         SDB_DATA_NULL,
1446                         SDB_DATA_NULL,
1447                         SDB_DATA_NULL,
1448                 },
1449                 {
1450                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1451                         { SDB_TYPE_NULL, { .integer = 0 } },
1452                         SDB_DATA_NULL,
1453                         SDB_DATA_NULL,
1454                         SDB_DATA_NULL,
1455                         SDB_DATA_NULL,
1456                         SDB_DATA_NULL,
1457                         SDB_DATA_NULL,
1458                 },
1459                 {
1460                         { SDB_TYPE_NULL, { .integer = 0 } },
1461                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1462                         SDB_DATA_NULL,
1463                         SDB_DATA_NULL,
1464                         SDB_DATA_NULL,
1465                         SDB_DATA_NULL,
1466                         SDB_DATA_NULL,
1467                         SDB_DATA_NULL,
1468                 },
1469                 {
1470                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1471                         { SDB_TYPE_NULL, { .integer = 0 } },
1472                         SDB_DATA_NULL,
1473                         SDB_DATA_NULL,
1474                         SDB_DATA_NULL,
1475                         SDB_DATA_NULL,
1476                         SDB_DATA_NULL,
1477                         SDB_DATA_NULL,
1478                 },
1479                 {
1480                         { SDB_TYPE_NULL, { .integer = 0 } },
1481                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1482                         SDB_DATA_NULL,
1483                         SDB_DATA_NULL,
1484                         SDB_DATA_NULL,
1485                         SDB_DATA_NULL,
1486                         SDB_DATA_NULL,
1487                         SDB_DATA_NULL,
1488                 },
1489                 {
1490                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1491                         { SDB_TYPE_NULL, { .integer = 0 } },
1492                         SDB_DATA_NULL,
1493                         SDB_DATA_NULL,
1494                         SDB_DATA_NULL,
1495                         SDB_DATA_NULL,
1496                         SDB_DATA_NULL,
1497                         SDB_DATA_NULL,
1498                 },
1499                 /* supported type-mismatches */
1500                 {
1501                         /* int * datetime */
1502                         { SDB_TYPE_INTEGER,  { .integer  = 20 } },
1503                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
1504                         err,
1505                         err,
1506                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1507                         err,
1508                         err,
1509                         err,
1510                 },
1511                 {
1512                         /* datetime * int, datetime / int, datetime % int */
1513                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1514                         { SDB_TYPE_INTEGER,  { .integer  = 2 } },
1515                         err,
1516                         err,
1517                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1518                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
1519                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1520                         err,
1521                 },
1522                 {
1523                         /* float * datetime */
1524                         { SDB_TYPE_DECIMAL,  { .decimal  = 20.0 } },
1525                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
1526                         err,
1527                         err,
1528                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1529                         err,
1530                         err,
1531                         err,
1532                 },
1533                 {
1534                         /* datetime * float, datetime / float, datetime % float */
1535                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1536                         { SDB_TYPE_DECIMAL,  { .decimal  = 2.0 } },
1537                         err,
1538                         err,
1539                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1540                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
1541                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1542                         err,
1543                 },
1544                 /* unsupported type-mismatches */
1545                 {
1546                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1547                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1548                         err, err, err, err, err, err,
1549                 },
1550                 {
1551                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1552                         { SDB_TYPE_STRING, { .string = "20" } },
1553                         err, err, err, err, err, err,
1554                 },
1555                 {
1556                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1557                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1558                         err, err, err, err, err, err,
1559                 },
1560                 {
1561                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1562                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1563                         err, err, err, err, err, err,
1564                 },
1565                 {
1566                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1567                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1568                         err, err, err, err, err, err,
1569                 },
1570                 {
1571                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1572                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1573                         err, err, err, err, err, err,
1574                 },
1575                 {
1576                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1577                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1578                         err, err, err, err, err, err,
1579                 },
1580                 {
1581                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1582                         { SDB_TYPE_STRING, { .string = "20.0" } },
1583                         err, err, err, err, err, err,
1584                 },
1585                 {
1586                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1587                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1588                         err, err, err, err, err, err,
1589                 },
1590                 {
1591                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1592                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1593                         err, err, err, err, err, err,
1594                 },
1595                 {
1596                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1597                         { SDB_TYPE_BINARY, { .binary = { 4, (unsigned char *)"20.0" } } },
1598                         err, err, err, err, err, err,
1599                 },
1600                 {
1601                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1602                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1603                         err, err, err, err, err, err,
1604                 },
1605                 {
1606                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1607                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1608                         err, err, err, err, err, err,
1609                 },
1610                 {
1611                         { SDB_TYPE_STRING, { .string = "20" } },
1612                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1613                         err, err, err, err, err, err,
1614                 },
1615                 {
1616                         { SDB_TYPE_STRING, { .string = "20" } },
1617                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1618                         err, err, err, err, err, err,
1619                 },
1620                 {
1621                         { SDB_TYPE_STRING, { .string = "20" } },
1622                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1623                         err, err, err, err, err, err,
1624                 },
1625                 {
1626                         { SDB_TYPE_STRING, { .string = "20" } },
1627                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1628                         err, err, err, err, err, err,
1629                 },
1630                 {
1631                         { SDB_TYPE_STRING, { .string = "20" } },
1632                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1633                         err, err, err, err, err, err,
1634                 },
1635                 {
1636                         { SDB_TYPE_STRING, { .string = "20" } },
1637                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1638                         err, err, err, err, err, err,
1639                 },
1640                 {
1641                         { SDB_TYPE_STRING, { .string = "20" } },
1642                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1643                         err, err, err, err, err, err,
1644                 },
1645                 {
1646                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1647                         { SDB_TYPE_STRING, { .string = "20" } },
1648                         err, err, err, err, err, err,
1649                 },
1650                 {
1651                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1652                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1653                         err, err, err, err, err, err,
1654                 },
1655                 {
1656                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1657                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1658                         err, err, err, err, err, err,
1659                 },
1660                 {
1661                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1662                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1663                         err, err, err, err, err, err,
1664                 },
1665                 {
1666                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1667                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1668                         err, err, err, err, err, err,
1669                 },
1670                 {
1671                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1672                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1673                         err, err, err, err, err, err,
1674                 },
1675                 {
1676                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1677                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1678                         err, err, err, err, err, err,
1679                 },
1680                 {
1681                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1682                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1683                         err, err, err, err, err, err,
1684                 },
1685                 {
1686                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1687                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1688                         err, err, err, err, err, err,
1689                 },
1690                 {
1691                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1692                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1693                         err, err, err, err, err, err,
1694                 },
1695                 {
1696                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1697                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1698                         err, err, err, err, err, err,
1699                 },
1700                 {
1701                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1702                         { SDB_TYPE_STRING, { .string = "20" } },
1703                         err, err, err, err, err, err,
1704                 },
1705                 {
1706                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1707                         { SDB_TYPE_STRING, { .string = "20" } },
1708                         err, err, err, err, err, err,
1709                 },
1710                 {
1711                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1712                         { SDB_TYPE_STRING, { .string = "20" } },
1713                         err, err, err, err, err, err,
1714                 },
1715                 {
1716                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1717                         { SDB_TYPE_STRING, { .string = "20" } },
1718                         err, err, err, err, err, err,
1719                 },
1720                 {
1721                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1722                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1723                         err, err, err, err, err, err,
1724                 },
1725                 {
1726                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1727                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1728                         err, err, err, err, err, err,
1729                 },
1730                 {
1731                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1732                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1733                         err, err, err, err, err, err,
1734                 },
1735                 {
1736                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1737                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1738                         err, err, err, err, err, err,
1739                 },
1740                 {
1741                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1742                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1743                         err, err, err, err, err, err,
1744                 },
1745                 {
1746                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1747                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1748                         err, err, err, err, err, err,
1749                 },
1750                 {
1751                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1752                         { SDB_TYPE_STRING, { .string = "20" } },
1753                         err, err, err, err, err, err,
1754                 },
1755                 {
1756                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1757                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1758                         err, err, err, err, err, err,
1759                 },
1760                 {
1761                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1762                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1763                         err, err, err, err, err, err,
1764                 },
1765                 {
1766                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1767                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1768                         err, err, err, err, err, err,
1769                 },
1770                 {
1771                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1772                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1773                         err, err, err, err, err, err,
1774                 },
1775         };
1777         size_t i;
1779         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1780                 struct {
1781                         int op;
1782                         sdb_data_t expected;
1783                 } tests[] = {
1784                         { SDB_DATA_ADD, golden_data[i].expected_add },
1785                         { SDB_DATA_SUB, golden_data[i].expected_sub },
1786                         { SDB_DATA_MUL, golden_data[i].expected_mul },
1787                         { SDB_DATA_DIV, golden_data[i].expected_div },
1788                         { SDB_DATA_MOD, golden_data[i].expected_mod },
1789                         { SDB_DATA_CONCAT, golden_data[i].expected_concat },
1790                 };
1792                 size_t j;
1793                 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
1794                         sdb_data_t res;
1795                         int check;
1796                         int type1, type2, type;
1798                         char d1_str[64] = "", d2_str[64] = "";
1799                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
1800                                         SDB_DOUBLE_QUOTED);
1801                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
1802                                         SDB_DOUBLE_QUOTED);
1804                         type1 = golden_data[i].d1.type;
1805                         type2 = golden_data[i].d2.type;
1806                         if (sdb_data_isnull(&golden_data[i].d1))
1807                                 type1 = SDB_TYPE_NULL;
1808                         if (sdb_data_isnull(&golden_data[i].d2))
1809                                 type2 = SDB_TYPE_NULL;
1810                         type = sdb_data_expr_type(tests[j].op, type1, type2);
1812                         check = sdb_data_expr_eval(tests[j].op,
1813                                         &golden_data[i].d1, &golden_data[i].d2, &res);
1814                         fail_unless((check == 0) == (tests[j].expected.type != -1),
1815                                         "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
1816                                         SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
1817                                         tests[j].expected.type == -1 ? -1 : 0);
1819                         fail_unless(tests[j].expected.type == type,
1820                                         "sdb_data_expr_eval(%s, %s, %s) expected to evaluate "
1821                                         "to type %d while sdb_data_expr_type(%d, %d, %d) "
1822                                         "predicted type %d", SDB_DATA_OP_TO_STRING(tests[j].op),
1823                                         d1_str, d2_str, tests[j].expected.type,
1824                                         tests[j].op, golden_data[i].d1.type,
1825                                         golden_data[i].d2.type, type);
1827                         if (tests[j].expected.type == -1)
1828                                 continue;
1830                         if (tests[j].expected.type == SDB_TYPE_NULL) {
1831                                 fail_unless(res.type == SDB_TYPE_NULL,
1832                                                 "sdb_data_expr_eval(%s, %s, %s) evaluated to "
1833                                                 "type %d; expected: SDB_TYPE_NULL",
1834                                                 SDB_DATA_OP_TO_STRING(tests[j].op),
1835                                                 d1_str, d2_str, res.type);
1836                                 continue;
1837                         }
1839                         check = sdb_data_cmp(&res, &tests[j].expected);
1840                         if (check != 0) {
1841                                 char res_str[64] = "", expected_str[64] = "";
1842                                 sdb_data_format(&res, res_str, sizeof(res_str),
1843                                                 SDB_DOUBLE_QUOTED);
1844                                 sdb_data_format(&tests[j].expected, expected_str,
1845                                                 sizeof(expected_str), SDB_DOUBLE_QUOTED);
1846                                 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s "
1847                                                 "(type %d); expected: %s (type %d)",
1848                                                 SDB_DATA_OP_TO_STRING(tests[j].op),
1849                                                 d1_str, d2_str, res_str, res.type,
1850                                                 expected_str, tests[j].expected.type);
1851                         }
1853                         sdb_data_free_datum(&res);
1854                 }
1855         }
1857 END_TEST
1859 START_TEST(test_format)
1861         int64_t int_values[] = { 47, 11, 23 };
1862         char *string_values[] = { "foo", "bar", "qux", "baz" };
1864         struct {
1865                 sdb_data_t datum;
1866                 const char *expected;
1867         } golden_data[] = {
1868                 {
1869                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
1870                         "4711",
1871                 },
1872                 {
1873                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
1874                         "65536",
1875                 },
1876                 {
1877                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
1878                         "12.3",
1879                 },
1880                 {
1881                         { SDB_TYPE_STRING, { .string = NULL } },
1882                         "NULL",
1883                 },
1884                 {
1885                         { SDB_TYPE_STRING, { .string = "this is a test" } },
1886                         "\"this is a test\"",
1887                 },
1888                 {
1889                         { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
1890                         "\"special \\\\ \\\" characters\"",
1891                 },
1892                 {
1893                         { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
1894                         "\"1984-12-06 02:11:54 +0000\"",
1895                 },
1896                 {
1897                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1898                         "NULL",
1899                 },
1900                 {
1901                         {
1902                                 SDB_TYPE_BINARY,
1903                                 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
1904                         },
1905                         "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
1906                 },
1907                 {
1908                         { SDB_TYPE_REGEX, { .re = { "some regex", empty_re } } },
1909                         "\"/some regex/\"",
1910                 },
1911                 {
1912                         { SDB_TYPE_INTEGER | SDB_TYPE_ARRAY, { .array = { 0, NULL } } },
1913                         "[]",
1914                 },
1915                 {
1916                         {
1917                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1918                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1919                         },
1920                         "[47, 11, 23]",
1921                 },
1922                 {
1923                         {
1924                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1925                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1926                         },
1927                         "[\"foo\", \"bar\", \"qux\", \"baz\"]",
1928                 },
1929         };
1931         size_t i;
1933         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1934                 sdb_data_t *datum = &golden_data[i].datum;
1935                 char buf[sdb_data_strlen(datum) + 2];
1936                 int check;
1938                 memset(buf, (int)'A', sizeof(buf));
1940                 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
1941                                 SDB_DOUBLE_QUOTED);
1942                 fail_unless(check > 0,
1943                                 "sdb_data_format(type=%s) = %d; expected: >0",
1944                                 SDB_TYPE_TO_STRING(datum->type), check);
1945                 fail_unless(! strcmp(buf, golden_data[i].expected),
1946                                 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
1947                                 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
1949                 fail_unless((size_t)check <= sizeof(buf) - 2,
1950                                 "sdb_data_format(type=%s) wrote %d bytes; "
1951                                 "expected <= %zu based on sdb_data_strlen()",
1952                                 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
1954                 fail_unless(buf[sizeof(buf) - 2] == '\0',
1955                                 "sdb_data_format(type=%s) did not nul-terminate the buffer",
1956                                 SDB_TYPE_TO_STRING(datum->type));
1957                 fail_unless(buf[sizeof(buf) - 1] == 'A',
1958                                 "sdb_data_format(type=%s) wrote past the end of the buffer",
1959                                 SDB_TYPE_TO_STRING(datum->type));
1960         }
1962 END_TEST
1964 START_TEST(test_parse)
1966         struct {
1967                 char *input;
1968                 sdb_data_t result;
1969                 int expected;
1970         } golden_data[] = {
1971                 { "4711",    { SDB_TYPE_INTEGER,  { .integer  = 4711 } },          0 },
1972                 { "0x10",    { SDB_TYPE_INTEGER,  { .integer  = 16 } },            0 },
1973                 { "010",     { SDB_TYPE_INTEGER,  { .integer  = 8 } },             0 },
1974                 { "abc",     { SDB_TYPE_INTEGER,  { .integer  = 0 } },            -1 },
1975                 { "1.2",     { SDB_TYPE_DECIMAL,  { .decimal  = 1.2 } },           0 },
1976                 { "0x1p+16", { SDB_TYPE_DECIMAL,  { .decimal  = 65536.0 } },       0 },
1977                 { "abc",     { SDB_TYPE_DECIMAL,  { .decimal  = 0.0 } },          -1 },
1978                 { "abc",     { SDB_TYPE_STRING,   { .string   = "abc" } },         0 },
1979                 { ".4",      { SDB_TYPE_DATETIME, { .datetime = 400000000 } },     0 },
1980                 { "abc",     { SDB_TYPE_DATETIME, { .datetime = 0 } },            -1 },
1981                 { "abc",     { SDB_TYPE_BINARY,
1982                                          { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
1983                 { "abc",     { SDB_TYPE_REGEX,    { .re = { "abc", empty_re } } }, 0 },
1984                 { "(|",      { SDB_TYPE_REGEX,    { .re = { "", empty_re } } },   -1 },
1985         };
1987         size_t i;
1989         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1990                 sdb_data_t result;
1991                 int type, check;
1993                 memset(&result, 0, sizeof(result));
1994                 type = golden_data[i].result.type;
1995                 check = sdb_data_parse(golden_data[i].input, type, &result);
1996                 fail_unless(check == golden_data[i].expected,
1997                                 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
1998                                 golden_data[i].input, type, check, golden_data[i].expected);
2000                 if (check)
2001                         continue;
2003                 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
2004                                 "sdb_data_parse(%s, %d, <d>) did not create expected result",
2005                                 golden_data[i].input, type);
2007                 if (type == SDB_TYPE_STRING)
2008                         fail_unless(golden_data[i].input == result.data.string,
2009                                         "sdb_data_parse(%s, %d, <d>) modified input string",
2010                                         golden_data[i].input, type);
2011                 if (type == SDB_TYPE_BINARY)
2012                         fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
2013                                         "sdb_data_parse(%s, %d, <d>) modified input string",
2014                                         golden_data[i].input, type);
2015                 if (type == SDB_TYPE_REGEX) {
2016                         fail_unless(golden_data[i].input != result.data.re.raw,
2017                                         "sdb_data_parse(%s, %d, <d>) copied input string",
2018                                         golden_data[i].input, type);
2019                         sdb_data_free_datum(&result);
2020                 }
2021         }
2023 END_TEST
2025 Suite *
2026 core_data_suite(void)
2028         Suite *s = suite_create("core::data");
2029         TCase *tc;
2031         tc = tcase_create("core");
2032         tcase_add_test(tc, test_data);
2033         tcase_add_test(tc, test_cmp);
2034         tcase_add_test(tc, test_strcmp);
2035         tcase_add_test(tc, test_inarray);
2036         tcase_add_test(tc, test_array_get);
2037         tcase_add_test(tc, test_parse_op);
2038         tcase_add_test(tc, test_expr_eval);
2039         tcase_add_test(tc, test_format);
2040         tcase_add_test(tc, test_parse);
2041         suite_add_tcase(s, tc);
2043         return s;
2044 } /* core_data_suite */
2046 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */