Code

data: Let inarray() support <array> IN <array> checks.
[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                         {
410                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
411                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
412                         },
413                         {
414                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
415                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
416                         },
417                         0,
418                 },
419                 {
420                         {
421                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
422                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
423                         },
424                         {
425                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
426                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
427                         },
428                         -1,
429                 },
430                 {
431                         {
432                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
433                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } },
434                         },
435                         {
436                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
437                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values1), int_values1 } },
438                         },
439                         1,
440                 },
441                 {
442                         {
443                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
444                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
445                         },
446                         {
447                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
448                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
449                         },
450                         0,
451                 },
452                 {
453                         {
454                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
455                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
456                         },
457                         {
458                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
459                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
460                         },
461                         -1,
462                 },
463                 {
464                         {
465                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
466                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } },
467                         },
468                         {
469                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
470                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values1), string_values1 } },
471                         },
472                         1,
473                 },
474         };
476         size_t i;
478         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
479                 int check = sdb_data_cmp(&golden_data[i].d1, &golden_data[i].d2);
480                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
481                 if (check != golden_data[i].expected) {
482                         char d1_str[64] = "", d2_str[64] = "";
483                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
484                                         SDB_DOUBLE_QUOTED);
485                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
486                                         SDB_DOUBLE_QUOTED);
487                         fail("sdb_data_cmp(%s, %s) = %d; expected: %d",
488                                         d1_str, d2_str, check, golden_data[i].expected);
489                 }
490         }
492 END_TEST
494 START_TEST(test_strcmp)
496         struct {
497                 sdb_data_t d1;
498                 sdb_data_t d2;
499                 int expected;
500         } golden_data[] = {
501                 /* same data as for the sdb_data_cmp test; in case the types match,
502                  * both functions should behave the same (except for some loss in
503                  * precision, e.g. when formatting datetime values) */
504                 {
505                         { SDB_TYPE_INTEGER, { .integer = 47 } },
506                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
507                         -1,
508                 },
509                 {
510                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
511                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
512                         0,
513                 },
514                 {
515                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
516                         { SDB_TYPE_INTEGER, { .integer = 47 } },
517                         1,
518                 },
519                 {
520                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
521                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
522                         -1,
523                 },
524                 {
525                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
526                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
527                         0,
528                 },
529                 {
530                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
531                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
532                         1,
533                 },
534                 {
535                         { SDB_TYPE_STRING, { .string = NULL } },
536                         { SDB_TYPE_STRING, { .string = "" } },
537                         -1,
538                 },
539                 {
540                         { SDB_TYPE_STRING, { .string = NULL } },
541                         { SDB_TYPE_STRING, { .string = NULL } },
542                         0,
543                 },
544                 {
545                         { SDB_TYPE_STRING, { .string = "" } },
546                         { SDB_TYPE_STRING, { .string = NULL } },
547                         1,
548                 },
549                 {
550                         { SDB_TYPE_STRING, { .string = "a" } },
551                         { SDB_TYPE_STRING, { .string = "b" } },
552                         -1,
553                 },
554                 {
555                         { SDB_TYPE_STRING, { .string = "a" } },
556                         { SDB_TYPE_STRING, { .string = "ab" } },
557                         -1,
558                 },
559                 {
560                         { SDB_TYPE_STRING, { .string = "a" } },
561                         { SDB_TYPE_STRING, { .string = "a" } },
562                         0,
563                 },
564                 {
565                         { SDB_TYPE_STRING, { .string = "b" } },
566                         { SDB_TYPE_STRING, { .string = "a" } },
567                         1,
568                 },
569                 {
570                         { SDB_TYPE_STRING, { .string = "ab" } },
571                         { SDB_TYPE_STRING, { .string = "a" } },
572                         1,
573                 },
574                 {
575                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
576                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
577                         -1,
578                 },
579                 {
580                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
581                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
582                         0,
583                 },
584                 {
585                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
586                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
587                         1,
588                 },
589                 {
590                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
591                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
592                         -1,
593                 },
594                 {
595                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
596                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
597                         0,
598                 },
599                 {
600                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
601                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
602                         1,
603                 },
604                 {
605                         {
606                                 SDB_TYPE_BINARY,
607                                 { .binary = { 3, (unsigned char *)"a\0a" } },
608                         },
609                         {
610                                 SDB_TYPE_BINARY,
611                                 { .binary = { 3, (unsigned char *)"a\0b" } },
612                         },
613                         -1,
614                 },
615                 {
616                         {
617                                 SDB_TYPE_BINARY,
618                                 { .binary = { 1, (unsigned char *)"a" } },
619                         },
620                         {
621                                 SDB_TYPE_BINARY,
622                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
623                         },
624                         -1,
625                 },
626                 {
627                         {
628                                 SDB_TYPE_BINARY,
629                                 { .binary = { 3, (unsigned char *)"a\0a" } },
630                         },
631                         {
632                                 SDB_TYPE_BINARY,
633                                 { .binary = { 3, (unsigned char *)"a\0a" } },
634                         },
635                         0,
636                 },
637                 {
638                         {
639                                 SDB_TYPE_BINARY,
640                                 { .binary = { 3, (unsigned char *)"a\0b" } },
641                         },
642                         {
643                                 SDB_TYPE_BINARY,
644                                 { .binary = { 3, (unsigned char *)"a\0a" } },
645                         },
646                         1,
647                 },
648                 {
649                         {
650                                 SDB_TYPE_BINARY,
651                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
652                         },
653                         {
654                                 SDB_TYPE_BINARY,
655                                 { .binary = { 1, (unsigned char *)"a" } },
656                         },
657                         1,
658                 },
659                 {
660                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
661                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
662                         0,
663                 },
664                 {
665                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
666                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
667                         -1,
668                 },
669                 {
670                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
671                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
672                         1,
673                 },
674                 /* type mismatches */
675                 {
676                         { SDB_TYPE_INTEGER, { .integer = 123 } },
677                         { SDB_TYPE_STRING, { .string = "123" } },
678                         0,
679                 },
680                 {
681                         { SDB_TYPE_INTEGER, { .integer = 120 } },
682                         { SDB_TYPE_STRING, { .string = "123" } },
683                         -1,
684                 },
685                 {
686                         { SDB_TYPE_STRING, { .string = "123" } },
687                         { SDB_TYPE_INTEGER, { .integer = 120 } },
688                         1,
689                 },
690                 {
691                         { SDB_TYPE_STRING, { .string = "12.3" } },
692                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
693                         0,
694                 },
695                 {
696                         { SDB_TYPE_STRING, { .string = "12.0" } },
697                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
698                         -1,
699                 },
700                 {
701                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
702                         { SDB_TYPE_STRING, { .string = "12.0" } },
703                         1,
704                 },
705                 {
706                         { SDB_TYPE_REGEX, { .re = { "regex", empty_re } } },
707                         { SDB_TYPE_STRING, { .string = "/regex/" } },
708                         0,
709                 },
710         };
712         size_t i;
714         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
715                 int check = sdb_data_strcmp(&golden_data[i].d1, &golden_data[i].d2);
716                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
717                 if (check != golden_data[i].expected) {
718                         char d1_str[64] = "", d2_str[64] = "";
719                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
720                                         SDB_DOUBLE_QUOTED);
721                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
722                                         SDB_DOUBLE_QUOTED);
723                         fail("sdb_data_strcmp(%s, %s) = %d; expected: %d",
724                                         d1_str, d2_str, check, golden_data[i].expected);
725                 }
726         }
728 END_TEST
730 START_TEST(test_inarray)
732         int64_t int_values[] = { 47, 11, 64 };
733         int64_t int_values2[] = { 64, 11 };
734         int64_t int_values3[] = { 47, 11, 42 };
735         double dec_values[] = { 12.3, 47.11, 64.0 };
736         double dec_values2[] = { 12.3, 47.11 };
737         double dec_values3[] = { 2.3, 47.11 };
738         char *string_values[] = { "foo", "bar", "qux", "baz" };
739         char *string_values2[] = { "qux", "bar" };
740         char *string_values3[] = { "foo", "bar", "qux", "baz", "bay" };
742         sdb_data_t int_array = {
743                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
744                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } }
745         };
746         sdb_data_t int_array2 = {
747                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
748                 { .array = { SDB_STATIC_ARRAY_LEN(int_values2), int_values2 } }
749         };
750         sdb_data_t int_array3 = {
751                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
752                 { .array = { SDB_STATIC_ARRAY_LEN(int_values3), int_values3 } }
753         };
754         sdb_data_t dec_array = {
755                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
756                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } }
757         };
758         sdb_data_t dec_array2 = {
759                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
760                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values2), dec_values2 } }
761         };
762         sdb_data_t dec_array3 = {
763                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
764                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values3), dec_values3 } }
765         };
766         sdb_data_t string_array = {
767                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
768                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } }
769         };
770         sdb_data_t string_array2 = {
771                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
772                 { .array = { SDB_STATIC_ARRAY_LEN(string_values2), string_values2 } }
773         };
774         sdb_data_t string_array3 = {
775                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
776                 { .array = { SDB_STATIC_ARRAY_LEN(string_values3), string_values3 } }
777         };
779         struct {
780                 sdb_data_t value;
781                 sdb_data_t array;
782                 _Bool expected;
783         } golden_data[] = {
784                 { { SDB_TYPE_INTEGER, { .integer = 47    } }, int_array,    1 },
785                 { { SDB_TYPE_INTEGER, { .integer = 11    } }, int_array,    1 },
786                 { { SDB_TYPE_INTEGER, { .integer = 64    } }, int_array,    1 },
787                 { { SDB_TYPE_INTEGER, { .integer = 65    } }, int_array,    0 },
788                 { { SDB_TYPE_NULL,    { .integer = 0     } }, int_array,    0 },
789                 { { SDB_TYPE_DECIMAL, { .decimal = 12.3  } }, dec_array,    1 },
790                 { { SDB_TYPE_DECIMAL, { .decimal = 47.11 } }, dec_array,    1 },
791                 { { SDB_TYPE_DECIMAL, { .decimal = 64.0  } }, dec_array,    1 },
792                 { { SDB_TYPE_DECIMAL, { .decimal = 60.0  } }, dec_array,    0 },
793                 { { SDB_TYPE_INTEGER, { .integer = 64    } }, dec_array,    0 },
794                 { { SDB_TYPE_NULL,    { .integer = 0     } }, dec_array,    0 },
795                 { { SDB_TYPE_STRING,  { .string  = "Foo" } }, string_array, 1 },
796                 { { SDB_TYPE_STRING,  { .string  = "FOO" } }, string_array, 1 },
797                 { { SDB_TYPE_STRING,  { .string  = "foo" } }, string_array, 1 },
798                 { { SDB_TYPE_STRING,  { .string  = "bar" } }, string_array, 1 },
799                 { { SDB_TYPE_STRING,  { .string  = "qux" } }, string_array, 1 },
800                 { { SDB_TYPE_STRING,  { .string  = "baz" } }, string_array, 1 },
801                 { { SDB_TYPE_STRING,  { .string  = "ba"  } }, string_array, 0 },
802                 { { SDB_TYPE_STRING,  { .string  = "abc" } }, string_array, 0 },
803                 { { SDB_TYPE_NULL,    { .integer = 0     } }, string_array, 0 },
804                 { int_array, { SDB_TYPE_INTEGER, { .integer = 47 } },       0 },
805                 { int_array,     int_array,    1 },
806                 { int_array2,    int_array,    1 },
807                 { int_array3,    int_array,    0 },
808                 { dec_array2,    int_array,    0 },
809                 { string_array2, int_array,    0 },
810                 { dec_array,     dec_array,    1 },
811                 { dec_array2,    dec_array,    1 },
812                 { dec_array3,    dec_array,    0 },
813                 { int_array2,    dec_array,    0 },
814                 { string_array2, dec_array,    0 },
815                 { string_array,  string_array, 1 },
816                 { string_array2, string_array, 1 },
817                 { string_array3, string_array, 0 },
818                 { int_array2,    string_array, 0 },
819                 { dec_array2,    string_array, 0 },
820         };
822         size_t i;
824         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
825                 char v_str[1024] = "", a_str[1024] = "";
826                 _Bool check;
828                 sdb_data_format(&golden_data[i].value,
829                                 v_str, sizeof(v_str), SDB_UNQUOTED);
830                 sdb_data_format(&golden_data[i].array,
831                                 a_str, sizeof(a_str), SDB_UNQUOTED);
833                 check = sdb_data_inarray(&golden_data[i].value, &golden_data[i].array);
834                 fail_unless(check == golden_data[i].expected,
835                                 "sdb_data_inarray(%s, %s) = %d; expected: %d",
836                                 v_str, a_str, check, golden_data[i].expected);
837         }
839 END_TEST
841 START_TEST(test_array_get)
843         int64_t int_values[] = { 47, 11, 64 };
844         double dec_values[] = { 12.3, 47.11, 64.0 };
845         char *string_values[] = { "foo", "bar", "qux", "baz" };
847         sdb_data_t int_array = {
848                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
849                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } }
850         };
851         sdb_data_t dec_array = {
852                 SDB_TYPE_ARRAY | SDB_TYPE_DECIMAL,
853                 { .array = { SDB_STATIC_ARRAY_LEN(dec_values), dec_values } }
854         };
855         sdb_data_t string_array = {
856                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
857                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } }
858         };
860         struct {
861                 sdb_data_t array;
862                 size_t i;
863                 sdb_data_t expected;
864         } golden_data[] = {
865                 { int_array, 0, { SDB_TYPE_INTEGER, { .integer = 47 } } },
866                 { int_array, 1, { SDB_TYPE_INTEGER, { .integer = 11 } } },
867                 { int_array, 2, { SDB_TYPE_INTEGER, { .integer = 64 } } },
868                 { int_array, 3, { -1, { .integer = 0 } } },
869                 { dec_array, 0, { SDB_TYPE_DECIMAL, { .decimal = 12.3 } } },
870                 { dec_array, 1, { SDB_TYPE_DECIMAL, { .decimal = 47.11 } } },
871                 { dec_array, 2, { SDB_TYPE_DECIMAL, { .decimal = 64.0 } } },
872                 { dec_array, 3, { -1, { .integer = 0 } } },
873                 { string_array, 0, { SDB_TYPE_STRING, { .string = "foo" } } },
874                 { string_array, 1, { SDB_TYPE_STRING, { .string = "bar" } } },
875                 { string_array, 2, { SDB_TYPE_STRING, { .string = "qux" } } },
876                 { string_array, 3, { SDB_TYPE_STRING, { .string = "baz" } } },
877                 { string_array, 4, { -1, { .integer = 0 } } },
878                 { { SDB_TYPE_INTEGER, { .integer = 666 } }, 0, { -1, { .integer = 0 } } },
879                 { { SDB_TYPE_INTEGER, { .integer = 666 } }, 1, { -1, { .integer = 0 } } },
880         };
882         size_t i;
884         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
885                 char a_str[1024] = "", v_str[1024] = "", exp_str[1024] = "";
886                 sdb_data_t value = SDB_DATA_INIT;
887                 int check;
889                 sdb_data_format(&golden_data[i].array,
890                                 a_str, sizeof(a_str), SDB_UNQUOTED);
891                 sdb_data_format(&golden_data[i].expected,
892                                 exp_str, sizeof(exp_str), SDB_UNQUOTED);
894                 check = sdb_data_array_get(&golden_data[i].array,
895                                 golden_data[i].i, &value);
897                 sdb_data_format(&value, v_str, sizeof(v_str), SDB_UNQUOTED);
899                 if (golden_data[i].expected.type < 0) {
900                         fail_unless(check < 0,
901                                         "sdb_data_array_get(%s, %zu) = %d (%s); expected: <0",
902                                         a_str, golden_data[i].i, check, v_str);
903                         continue;
904                 }
906                 fail_unless(check == 0,
907                                 "sdb_data_array_get(%s, %zu) = %d; expected: 0",
908                                 a_str, golden_data[i].i, check);
909                 fail_unless(! sdb_data_cmp(&value, &golden_data[i].expected),
910                                 "sdb_data_array_get(%s, %zu) -> '%s'; expected: '%s'",
911                                 a_str, golden_data[i].i, v_str, exp_str);
912         }
914 END_TEST
916 START_TEST(test_parse_op)
918         struct {
919                 const char *op;
920                 int id;
921         } golden_data[] = {
922                 { "+",  SDB_DATA_ADD },
923                 { "-",  SDB_DATA_SUB },
924                 { "*",  SDB_DATA_MUL },
925                 { "/",  SDB_DATA_DIV },
926                 { "%",  SDB_DATA_MOD },
927                 { "||", SDB_DATA_CONCAT },
928                 { "&&", -1 },
929         };
931         size_t i;
933         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
934                 const char *op;
935                 int id;
937                 id = sdb_data_parse_op(golden_data[i].op);
938                 fail_unless(id == golden_data[i].id,
939                                 "sdb_data_parse_op(%s) = %d; expected: %d",
940                                 golden_data[i].op, id, golden_data[i].id);
942                 if (id <= 0)
943                         continue;
945                 op = SDB_DATA_OP_TO_STRING(id);
946                 fail_unless(!strcmp(op, golden_data[i].op),
947                                 "SDB_DATA_OP_TO_STRING(%d) = '%s'; expected: '%s'",
948                                 id, op, golden_data[i].op);
949         }
951 END_TEST
953 START_TEST(test_expr_eval)
955         sdb_data_t err = { -1, { .integer = 0 } };
957         int64_t int_values[] = { 47, 11, 23 };
958         int64_t expected_int_append[] = { 47, 11, 23, 42 };
959         int64_t expected_int_prepend[] = { 42, 47, 11, 23 };
960         int64_t expected_int_concat[] = { 47, 11, 23, 47, 11, 23 };
961         char *string_values[] = { "foo", "bar", "qux" "baz" };
962         char *expected_string_append[] = { "foo", "bar", "qux" "baz", "bay" };
963         char *expected_string_prepend[] = { "bay", "foo", "bar", "qux" "baz" };
964         char *expected_string_concat[] =
965                 { "foo", "bar", "qux" "baz", "foo", "bar", "qux" "baz" };
967         struct {
968                 sdb_data_t d1;
969                 sdb_data_t d2;
970                 sdb_data_t expected_add;
971                 sdb_data_t expected_sub;
972                 sdb_data_t expected_mul;
973                 sdb_data_t expected_div;
974                 sdb_data_t expected_mod;
975                 sdb_data_t expected_concat;
976         } golden_data[] = {
977                 {
978                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
979                         { SDB_TYPE_INTEGER, { .integer = 47 } },
980                         { SDB_TYPE_INTEGER, { .integer = 4758 } },
981                         { SDB_TYPE_INTEGER, { .integer = 4664 } },
982                         { SDB_TYPE_INTEGER, { .integer = 221417 } },
983                         { SDB_TYPE_INTEGER, { .integer = 100 } },
984                         { SDB_TYPE_INTEGER, { .integer = 11 } },
985                         err,
986                 },
987                 {
988                         { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
989                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
990                         { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
991                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
992                         { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
993                         { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
994                         { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
995                         err,
996                 },
997                 {
998                         { SDB_TYPE_STRING, { .string = NULL } },
999                         { SDB_TYPE_STRING, { .string = "" } },
1000                         SDB_DATA_NULL,
1001                         SDB_DATA_NULL,
1002                         SDB_DATA_NULL,
1003                         SDB_DATA_NULL,
1004                         SDB_DATA_NULL,
1005                         SDB_DATA_NULL,
1006                 },
1007                 {
1008                         { SDB_TYPE_STRING, { .string = NULL } },
1009                         { SDB_TYPE_STRING, { .string = NULL } },
1010                         SDB_DATA_NULL,
1011                         SDB_DATA_NULL,
1012                         SDB_DATA_NULL,
1013                         SDB_DATA_NULL,
1014                         SDB_DATA_NULL,
1015                         SDB_DATA_NULL,
1016                 },
1017                 {
1018                         { SDB_TYPE_STRING, { .string = "" } },
1019                         { SDB_TYPE_STRING, { .string = NULL } },
1020                         SDB_DATA_NULL,
1021                         SDB_DATA_NULL,
1022                         SDB_DATA_NULL,
1023                         SDB_DATA_NULL,
1024                         SDB_DATA_NULL,
1025                         SDB_DATA_NULL,
1026                 },
1027                 {
1028                         { SDB_TYPE_STRING, { .string = "a" } },
1029                         { SDB_TYPE_STRING, { .string = "b" } },
1030                         err,
1031                         err,
1032                         err,
1033                         err,
1034                         err,
1035                         { SDB_TYPE_STRING, { .string = "ab" } },
1036                 },
1037                 {
1038                         { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
1039                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1040                         { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
1041                         { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
1042                         { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
1043                         { SDB_TYPE_DATETIME, { .datetime = 10001 } },
1044                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1045                         err,
1046                 },
1047                 {
1048                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1049                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1050                         SDB_DATA_NULL,
1051                         SDB_DATA_NULL,
1052                         SDB_DATA_NULL,
1053                         SDB_DATA_NULL,
1054                         SDB_DATA_NULL,
1055                         SDB_DATA_NULL,
1056                 },
1057                 {
1058                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1059                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1060                         SDB_DATA_NULL,
1061                         SDB_DATA_NULL,
1062                         SDB_DATA_NULL,
1063                         SDB_DATA_NULL,
1064                         SDB_DATA_NULL,
1065                         SDB_DATA_NULL,
1066                 },
1067                 {
1068                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1069                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1070                         SDB_DATA_NULL,
1071                         SDB_DATA_NULL,
1072                         SDB_DATA_NULL,
1073                         SDB_DATA_NULL,
1074                         SDB_DATA_NULL,
1075                         SDB_DATA_NULL,
1076                 },
1077                 {
1078                         {
1079                                 SDB_TYPE_BINARY,
1080                                 { .binary = { 3, (unsigned char *)"a\0a" } },
1081                         },
1082                         {
1083                                 SDB_TYPE_BINARY,
1084                                 { .binary = { 3, (unsigned char *)"b\0b" } },
1085                         },
1086                         err,
1087                         err,
1088                         err,
1089                         err,
1090                         err,
1091                         {
1092                                 SDB_TYPE_BINARY,
1093                                 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
1094                         },
1095                 },
1096                 {
1097                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1098                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1099                         err,
1100                         err,
1101                         err,
1102                         err,
1103                         err,
1104                         err,
1105                 },
1106                 {
1107                         {
1108                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1109                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1110                         },
1111                         {
1112                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1113                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1114                         },
1115                         err,
1116                         err,
1117                         err,
1118                         err,
1119                         err,
1120                         {
1121                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1122                                 { .array = {
1123                                                 SDB_STATIC_ARRAY_LEN(expected_int_concat),
1124                                                 expected_int_concat
1125                                 } },
1126                         },
1127                 },
1128                 {
1129                         {
1130                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1131                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1132                         },
1133                         { SDB_TYPE_INTEGER, { .integer = 42 }, },
1134                         err,
1135                         err,
1136                         err,
1137                         err,
1138                         err,
1139                         {
1140                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1141                                 { .array = {
1142                                                 SDB_STATIC_ARRAY_LEN(expected_int_append),
1143                                                 expected_int_append
1144                                 } },
1145                         },
1146                 },
1147                 {
1148                         { SDB_TYPE_INTEGER, { .integer = 42 }, },
1149                         {
1150                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1151                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1152                         },
1153                         err,
1154                         err,
1155                         err,
1156                         err,
1157                         err,
1158                         {
1159                                 SDB_TYPE_ARRAY | SDB_TYPE_INTEGER,
1160                                 { .array = {
1161                                                 SDB_STATIC_ARRAY_LEN(expected_int_prepend),
1162                                                 expected_int_prepend
1163                                 } },
1164                         },
1165                 },
1166                 {
1167                         {
1168                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1169                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1170                         },
1171                         {
1172                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1173                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1174                         },
1175                         err,
1176                         err,
1177                         err,
1178                         err,
1179                         err,
1180                         {
1181                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1182                                 { .array = {
1183                                                 SDB_STATIC_ARRAY_LEN(expected_string_concat),
1184                                                 expected_string_concat
1185                                 } },
1186                         },
1187                 },
1188                 {
1189                         {
1190                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1191                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1192                         },
1193                         { SDB_TYPE_STRING, { .string = "bay" } },
1194                         err,
1195                         err,
1196                         err,
1197                         err,
1198                         err,
1199                         {
1200                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1201                                 { .array = {
1202                                                 SDB_STATIC_ARRAY_LEN(expected_string_append),
1203                                                 expected_string_append
1204                                 } },
1205                         },
1206                 },
1207                 {
1208                         { SDB_TYPE_STRING, { .string = "bay" } },
1209                         {
1210                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1211                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1212                         },
1213                         err,
1214                         err,
1215                         err,
1216                         err,
1217                         err,
1218                         {
1219                                 SDB_TYPE_ARRAY | SDB_TYPE_STRING,
1220                                 { .array = {
1221                                                 SDB_STATIC_ARRAY_LEN(expected_string_prepend),
1222                                                 expected_string_prepend
1223                                 } },
1224                         },
1225                 },
1226                 {
1227                         { SDB_TYPE_NULL, { .integer = 0 } },
1228                         { SDB_TYPE_NULL, { .integer = 0 } },
1229                         SDB_DATA_NULL,
1230                         SDB_DATA_NULL,
1231                         SDB_DATA_NULL,
1232                         SDB_DATA_NULL,
1233                         SDB_DATA_NULL,
1234                         SDB_DATA_NULL,
1235                 },
1236                 {
1237                         { SDB_TYPE_NULL, { .integer = 0 } },
1238                         { SDB_TYPE_INTEGER, { .integer = 42 } },
1239                         SDB_DATA_NULL,
1240                         SDB_DATA_NULL,
1241                         SDB_DATA_NULL,
1242                         SDB_DATA_NULL,
1243                         SDB_DATA_NULL,
1244                         SDB_DATA_NULL,
1245                 },
1246                 {
1247                         { SDB_TYPE_INTEGER, { .integer = 42 } },
1248                         { SDB_TYPE_NULL, { .integer = 0 } },
1249                         SDB_DATA_NULL,
1250                         SDB_DATA_NULL,
1251                         SDB_DATA_NULL,
1252                         SDB_DATA_NULL,
1253                         SDB_DATA_NULL,
1254                         SDB_DATA_NULL,
1255                 },
1256                 {
1257                         { SDB_TYPE_NULL, { .integer = 0 } },
1258                         { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
1259                         SDB_DATA_NULL,
1260                         SDB_DATA_NULL,
1261                         SDB_DATA_NULL,
1262                         SDB_DATA_NULL,
1263                         SDB_DATA_NULL,
1264                         SDB_DATA_NULL,
1265                 },
1266                 {
1267                         { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
1268                         { SDB_TYPE_NULL, { .integer = 0 } },
1269                         SDB_DATA_NULL,
1270                         SDB_DATA_NULL,
1271                         SDB_DATA_NULL,
1272                         SDB_DATA_NULL,
1273                         SDB_DATA_NULL,
1274                         SDB_DATA_NULL,
1275                 },
1276                 {
1277                         { SDB_TYPE_NULL, { .integer = 0 } },
1278                         { SDB_TYPE_STRING, { .string = "47.11" } },
1279                         SDB_DATA_NULL,
1280                         SDB_DATA_NULL,
1281                         SDB_DATA_NULL,
1282                         SDB_DATA_NULL,
1283                         SDB_DATA_NULL,
1284                         SDB_DATA_NULL,
1285                 },
1286                 {
1287                         { SDB_TYPE_STRING, { .string = "47.11" } },
1288                         { SDB_TYPE_NULL, { .integer = 0 } },
1289                         SDB_DATA_NULL,
1290                         SDB_DATA_NULL,
1291                         SDB_DATA_NULL,
1292                         SDB_DATA_NULL,
1293                         SDB_DATA_NULL,
1294                         SDB_DATA_NULL,
1295                 },
1296                 {
1297                         { SDB_TYPE_NULL, { .integer = 0 } },
1298                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1299                         SDB_DATA_NULL,
1300                         SDB_DATA_NULL,
1301                         SDB_DATA_NULL,
1302                         SDB_DATA_NULL,
1303                         SDB_DATA_NULL,
1304                         SDB_DATA_NULL,
1305                 },
1306                 {
1307                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
1308                         { SDB_TYPE_NULL, { .integer = 0 } },
1309                         SDB_DATA_NULL,
1310                         SDB_DATA_NULL,
1311                         SDB_DATA_NULL,
1312                         SDB_DATA_NULL,
1313                         SDB_DATA_NULL,
1314                         SDB_DATA_NULL,
1315                 },
1316                 {
1317                         { SDB_TYPE_NULL, { .integer = 0 } },
1318                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1319                         SDB_DATA_NULL,
1320                         SDB_DATA_NULL,
1321                         SDB_DATA_NULL,
1322                         SDB_DATA_NULL,
1323                         SDB_DATA_NULL,
1324                         SDB_DATA_NULL,
1325                 },
1326                 {
1327                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
1328                         { SDB_TYPE_NULL, { .integer = 0 } },
1329                         SDB_DATA_NULL,
1330                         SDB_DATA_NULL,
1331                         SDB_DATA_NULL,
1332                         SDB_DATA_NULL,
1333                         SDB_DATA_NULL,
1334                         SDB_DATA_NULL,
1335                 },
1336                 {
1337                         { SDB_TYPE_NULL, { .integer = 0 } },
1338                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1339                         SDB_DATA_NULL,
1340                         SDB_DATA_NULL,
1341                         SDB_DATA_NULL,
1342                         SDB_DATA_NULL,
1343                         SDB_DATA_NULL,
1344                         SDB_DATA_NULL,
1345                 },
1346                 {
1347                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1348                         { SDB_TYPE_NULL, { .integer = 0 } },
1349                         SDB_DATA_NULL,
1350                         SDB_DATA_NULL,
1351                         SDB_DATA_NULL,
1352                         SDB_DATA_NULL,
1353                         SDB_DATA_NULL,
1354                         SDB_DATA_NULL,
1355                 },
1356                 /* supported type-mismatches */
1357                 {
1358                         /* int * datetime */
1359                         { SDB_TYPE_INTEGER,  { .integer  = 20 } },
1360                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
1361                         err,
1362                         err,
1363                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1364                         err,
1365                         err,
1366                         err,
1367                 },
1368                 {
1369                         /* datetime * int, datetime / int, datetime % int */
1370                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1371                         { SDB_TYPE_INTEGER,  { .integer  = 2 } },
1372                         err,
1373                         err,
1374                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1375                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
1376                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1377                         err,
1378                 },
1379                 {
1380                         /* float * datetime */
1381                         { SDB_TYPE_DECIMAL,  { .decimal  = 20.0 } },
1382                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
1383                         err,
1384                         err,
1385                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1386                         err,
1387                         err,
1388                         err,
1389                 },
1390                 {
1391                         /* datetime * float, datetime / float, datetime % float */
1392                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1393                         { SDB_TYPE_DECIMAL,  { .decimal  = 2.0 } },
1394                         err,
1395                         err,
1396                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
1397                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
1398                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
1399                         err,
1400                 },
1401                 /* unsupported type-mismatches */
1402                 {
1403                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1404                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1405                         err, err, err, err, err, err,
1406                 },
1407                 {
1408                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1409                         { SDB_TYPE_STRING, { .string = "20" } },
1410                         err, err, err, err, err, err,
1411                 },
1412                 {
1413                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1414                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1415                         err, err, err, err, err, err,
1416                 },
1417                 {
1418                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1419                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1420                         err, err, err, err, err, err,
1421                 },
1422                 {
1423                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1424                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1425                         err, err, err, err, err, err,
1426                 },
1427                 {
1428                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1429                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1430                         err, err, err, err, err, err,
1431                 },
1432                 {
1433                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1434                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1435                         err, err, err, err, err, err,
1436                 },
1437                 {
1438                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1439                         { SDB_TYPE_STRING, { .string = "20.0" } },
1440                         err, err, err, err, err, err,
1441                 },
1442                 {
1443                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1444                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1445                         err, err, err, err, err, err,
1446                 },
1447                 {
1448                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1449                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1450                         err, err, err, err, err, err,
1451                 },
1452                 {
1453                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1454                         { SDB_TYPE_BINARY, { .binary = { 4, (unsigned char *)"20.0" } } },
1455                         err, err, err, err, err, err,
1456                 },
1457                 {
1458                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1459                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1460                         err, err, err, err, err, err,
1461                 },
1462                 {
1463                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1464                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1465                         err, err, err, err, err, err,
1466                 },
1467                 {
1468                         { SDB_TYPE_STRING, { .string = "20" } },
1469                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1470                         err, err, err, err, err, err,
1471                 },
1472                 {
1473                         { SDB_TYPE_STRING, { .string = "20" } },
1474                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1475                         err, err, err, err, err, err,
1476                 },
1477                 {
1478                         { SDB_TYPE_STRING, { .string = "20" } },
1479                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1480                         err, err, err, err, err, err,
1481                 },
1482                 {
1483                         { SDB_TYPE_STRING, { .string = "20" } },
1484                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1485                         err, err, err, err, err, err,
1486                 },
1487                 {
1488                         { SDB_TYPE_STRING, { .string = "20" } },
1489                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1490                         err, err, err, err, err, err,
1491                 },
1492                 {
1493                         { SDB_TYPE_STRING, { .string = "20" } },
1494                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1495                         err, err, err, err, err, err,
1496                 },
1497                 {
1498                         { SDB_TYPE_STRING, { .string = "20" } },
1499                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1500                         err, err, err, err, err, err,
1501                 },
1502                 {
1503                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1504                         { SDB_TYPE_STRING, { .string = "20" } },
1505                         err, err, err, err, err, err,
1506                 },
1507                 {
1508                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1509                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1510                         err, err, err, err, err, err,
1511                 },
1512                 {
1513                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1514                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1515                         err, err, err, err, err, err,
1516                 },
1517                 {
1518                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1519                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1520                         err, err, err, err, err, err,
1521                 },
1522                 {
1523                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1524                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1525                         err, err, err, err, err, err,
1526                 },
1527                 {
1528                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1529                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1530                         err, err, err, err, err, err,
1531                 },
1532                 {
1533                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1534                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1535                         err, err, err, err, err, err,
1536                 },
1537                 {
1538                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1539                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1540                         err, err, err, err, err, err,
1541                 },
1542                 {
1543                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1544                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1545                         err, err, err, err, err, err,
1546                 },
1547                 {
1548                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1549                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1550                         err, err, err, err, err, err,
1551                 },
1552                 {
1553                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1554                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1555                         err, err, err, err, err, err,
1556                 },
1557                 {
1558                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1559                         { SDB_TYPE_STRING, { .string = "20" } },
1560                         err, err, err, err, err, err,
1561                 },
1562                 {
1563                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1564                         { SDB_TYPE_STRING, { .string = "20" } },
1565                         err, err, err, err, err, err,
1566                 },
1567                 {
1568                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1569                         { SDB_TYPE_STRING, { .string = "20" } },
1570                         err, err, err, err, err, err,
1571                 },
1572                 {
1573                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1574                         { SDB_TYPE_STRING, { .string = "20" } },
1575                         err, err, err, err, err, err,
1576                 },
1577                 {
1578                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1579                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1580                         err, err, err, err, err, err,
1581                 },
1582                 {
1583                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1584                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1585                         err, err, err, err, err, err,
1586                 },
1587                 {
1588                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1589                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1590                         err, err, err, err, err, err,
1591                 },
1592                 {
1593                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1594                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1595                         err, err, err, err, err, err,
1596                 },
1597                 {
1598                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1599                         { SDB_TYPE_INTEGER, { .integer = 20 } },
1600                         err, err, err, err, err, err,
1601                 },
1602                 {
1603                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1604                         { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
1605                         err, err, err, err, err, err,
1606                 },
1607                 {
1608                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1609                         { SDB_TYPE_STRING, { .string = "20" } },
1610                         err, err, err, err, err, err,
1611                 },
1612                 {
1613                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1614                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
1615                         err, err, err, err, err, err,
1616                 },
1617                 {
1618                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1619                         { SDB_TYPE_BINARY, { .binary = { 2, (unsigned char *)"20" } } },
1620                         err, err, err, err, err, err,
1621                 },
1622                 {
1623                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1624                         { SDB_TYPE_BINARY, { .binary = { 3, (unsigned char *)"20" } } },
1625                         err, err, err, err, err, err,
1626                 },
1627                 {
1628                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
1629                         { SDB_TYPE_REGEX + 1, { .integer = 0 } },
1630                         err, err, err, err, err, err,
1631                 },
1632         };
1634         size_t i;
1636         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1637                 struct {
1638                         int op;
1639                         sdb_data_t expected;
1640                 } tests[] = {
1641                         { SDB_DATA_ADD, golden_data[i].expected_add },
1642                         { SDB_DATA_SUB, golden_data[i].expected_sub },
1643                         { SDB_DATA_MUL, golden_data[i].expected_mul },
1644                         { SDB_DATA_DIV, golden_data[i].expected_div },
1645                         { SDB_DATA_MOD, golden_data[i].expected_mod },
1646                         { SDB_DATA_CONCAT, golden_data[i].expected_concat },
1647                 };
1649                 size_t j;
1650                 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
1651                         sdb_data_t res;
1652                         int check;
1653                         int type1, type2, type;
1655                         char d1_str[64] = "", d2_str[64] = "";
1656                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
1657                                         SDB_DOUBLE_QUOTED);
1658                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
1659                                         SDB_DOUBLE_QUOTED);
1661                         type1 = golden_data[i].d1.type;
1662                         type2 = golden_data[i].d2.type;
1663                         if (sdb_data_isnull(&golden_data[i].d1))
1664                                 type1 = SDB_TYPE_NULL;
1665                         if (sdb_data_isnull(&golden_data[i].d2))
1666                                 type2 = SDB_TYPE_NULL;
1667                         type = sdb_data_expr_type(tests[j].op, type1, type2);
1669                         check = sdb_data_expr_eval(tests[j].op,
1670                                         &golden_data[i].d1, &golden_data[i].d2, &res);
1671                         fail_unless((check == 0) == (tests[j].expected.type != -1),
1672                                         "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
1673                                         SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
1674                                         tests[j].expected.type == -1 ? -1 : 0);
1676                         fail_unless(tests[j].expected.type == type,
1677                                         "sdb_data_expr_eval(%s, %s, %s) expected to evaluate "
1678                                         "to type %d while sdb_data_expr_type(%d, %d, %d) "
1679                                         "predicted type %d", SDB_DATA_OP_TO_STRING(tests[j].op),
1680                                         d1_str, d2_str, tests[j].expected.type,
1681                                         tests[j].op, golden_data[i].d1.type,
1682                                         golden_data[i].d2.type, type);
1684                         if (tests[j].expected.type == -1)
1685                                 continue;
1687                         if (tests[j].expected.type == SDB_TYPE_NULL) {
1688                                 fail_unless(res.type == SDB_TYPE_NULL,
1689                                                 "sdb_data_expr_eval(%s, %s, %s) evaluated to "
1690                                                 "type %d; expected: SDB_TYPE_NULL",
1691                                                 SDB_DATA_OP_TO_STRING(tests[j].op),
1692                                                 d1_str, d2_str, res.type);
1693                                 continue;
1694                         }
1696                         check = sdb_data_cmp(&res, &tests[j].expected);
1697                         if (check != 0) {
1698                                 char res_str[64] = "", expected_str[64] = "";
1699                                 sdb_data_format(&res, res_str, sizeof(res_str),
1700                                                 SDB_DOUBLE_QUOTED);
1701                                 sdb_data_format(&tests[j].expected, expected_str,
1702                                                 sizeof(expected_str), SDB_DOUBLE_QUOTED);
1703                                 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s "
1704                                                 "(type %d); expected: %s (type %d)",
1705                                                 SDB_DATA_OP_TO_STRING(tests[j].op),
1706                                                 d1_str, d2_str, res_str, res.type,
1707                                                 expected_str, tests[j].expected.type);
1708                         }
1710                         sdb_data_free_datum(&res);
1711                 }
1712         }
1714 END_TEST
1716 START_TEST(test_format)
1718         int64_t int_values[] = { 47, 11, 23 };
1719         char *string_values[] = { "foo", "bar", "qux", "baz" };
1721         struct {
1722                 sdb_data_t datum;
1723                 const char *expected;
1724         } golden_data[] = {
1725                 {
1726                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
1727                         "4711",
1728                 },
1729                 {
1730                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
1731                         "65536",
1732                 },
1733                 {
1734                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
1735                         "12.3",
1736                 },
1737                 {
1738                         { SDB_TYPE_STRING, { .string = NULL } },
1739                         "NULL",
1740                 },
1741                 {
1742                         { SDB_TYPE_STRING, { .string = "this is a test" } },
1743                         "\"this is a test\"",
1744                 },
1745                 {
1746                         { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
1747                         "\"special \\\\ \\\" characters\"",
1748                 },
1749                 {
1750                         { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
1751                         "\"1984-12-06 02:11:54 +0000\"",
1752                 },
1753                 {
1754                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1755                         "NULL",
1756                 },
1757                 {
1758                         {
1759                                 SDB_TYPE_BINARY,
1760                                 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
1761                         },
1762                         "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
1763                 },
1764                 {
1765                         { SDB_TYPE_REGEX, { .re = { "some regex", empty_re } } },
1766                         "\"/some regex/\"",
1767                 },
1768                 {
1769                         {
1770                                 SDB_TYPE_INTEGER | SDB_TYPE_ARRAY,
1771                                 { .array = { SDB_STATIC_ARRAY_LEN(int_values), int_values } },
1772                         },
1773                         "[47, 11, 23]",
1774                 },
1775                 {
1776                         {
1777                                 SDB_TYPE_STRING | SDB_TYPE_ARRAY,
1778                                 { .array = { SDB_STATIC_ARRAY_LEN(string_values), string_values } },
1779                         },
1780                         "[\"foo\", \"bar\", \"qux\", \"baz\"]",
1781                 },
1782         };
1784         size_t i;
1786         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1787                 sdb_data_t *datum = &golden_data[i].datum;
1788                 char buf[sdb_data_strlen(datum) + 2];
1789                 int check;
1791                 memset(buf, (int)'A', sizeof(buf));
1793                 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
1794                                 SDB_DOUBLE_QUOTED);
1795                 fail_unless(check > 0,
1796                                 "sdb_data_format(type=%s) = %d; expected: >0",
1797                                 SDB_TYPE_TO_STRING(datum->type), check);
1798                 fail_unless(! strcmp(buf, golden_data[i].expected),
1799                                 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
1800                                 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
1802                 fail_unless((size_t)check <= sizeof(buf) - 2,
1803                                 "sdb_data_format(type=%s) wrote %d bytes; "
1804                                 "expected <= %zu based on sdb_data_strlen()",
1805                                 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
1807                 fail_unless(buf[sizeof(buf) - 2] == '\0',
1808                                 "sdb_data_format(type=%s) did not nul-terminate the buffer",
1809                                 SDB_TYPE_TO_STRING(datum->type));
1810                 fail_unless(buf[sizeof(buf) - 1] == 'A',
1811                                 "sdb_data_format(type=%s) wrote past the end of the buffer",
1812                                 SDB_TYPE_TO_STRING(datum->type));
1813         }
1815 END_TEST
1817 START_TEST(test_parse)
1819         struct {
1820                 char *input;
1821                 sdb_data_t result;
1822                 int expected;
1823         } golden_data[] = {
1824                 { "4711",    { SDB_TYPE_INTEGER,  { .integer  = 4711 } },          0 },
1825                 { "0x10",    { SDB_TYPE_INTEGER,  { .integer  = 16 } },            0 },
1826                 { "010",     { SDB_TYPE_INTEGER,  { .integer  = 8 } },             0 },
1827                 { "abc",     { SDB_TYPE_INTEGER,  { .integer  = 0 } },            -1 },
1828                 { "1.2",     { SDB_TYPE_DECIMAL,  { .decimal  = 1.2 } },           0 },
1829                 { "0x1p+16", { SDB_TYPE_DECIMAL,  { .decimal  = 65536.0 } },       0 },
1830                 { "abc",     { SDB_TYPE_DECIMAL,  { .decimal  = 0.0 } },          -1 },
1831                 { "abc",     { SDB_TYPE_STRING,   { .string   = "abc" } },         0 },
1832                 { ".4",      { SDB_TYPE_DATETIME, { .datetime = 400000000 } },     0 },
1833                 { "abc",     { SDB_TYPE_DATETIME, { .datetime = 0 } },            -1 },
1834                 { "abc",     { SDB_TYPE_BINARY,
1835                                          { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
1836                 { "abc",     { SDB_TYPE_REGEX,    { .re = { "abc", empty_re } } }, 0 },
1837                 { "(|",      { SDB_TYPE_REGEX,    { .re = { "", empty_re } } },   -1 },
1838         };
1840         size_t i;
1842         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1843                 sdb_data_t result;
1844                 int type, check;
1846                 memset(&result, 0, sizeof(result));
1847                 type = golden_data[i].result.type;
1848                 check = sdb_data_parse(golden_data[i].input, type, &result);
1849                 fail_unless(check == golden_data[i].expected,
1850                                 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
1851                                 golden_data[i].input, type, check, golden_data[i].expected);
1853                 if (check)
1854                         continue;
1856                 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
1857                                 "sdb_data_parse(%s, %d, <d>) did not create expected result",
1858                                 golden_data[i].input, type);
1860                 if (type == SDB_TYPE_STRING)
1861                         fail_unless(golden_data[i].input == result.data.string,
1862                                         "sdb_data_parse(%s, %d, <d>) modified input string",
1863                                         golden_data[i].input, type);
1864                 if (type == SDB_TYPE_BINARY)
1865                         fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
1866                                         "sdb_data_parse(%s, %d, <d>) modified input string",
1867                                         golden_data[i].input, type);
1868                 if (type == SDB_TYPE_REGEX) {
1869                         fail_unless(golden_data[i].input != result.data.re.raw,
1870                                         "sdb_data_parse(%s, %d, <d>) copied input string",
1871                                         golden_data[i].input, type);
1872                         sdb_data_free_datum(&result);
1873                 }
1874         }
1876 END_TEST
1878 Suite *
1879 core_data_suite(void)
1881         Suite *s = suite_create("core::data");
1882         TCase *tc;
1884         tc = tcase_create("core");
1885         tcase_add_test(tc, test_data);
1886         tcase_add_test(tc, test_cmp);
1887         tcase_add_test(tc, test_strcmp);
1888         tcase_add_test(tc, test_inarray);
1889         tcase_add_test(tc, test_array_get);
1890         tcase_add_test(tc, test_parse_op);
1891         tcase_add_test(tc, test_expr_eval);
1892         tcase_add_test(tc, test_format);
1893         tcase_add_test(tc, test_parse);
1894         suite_add_tcase(s, tc);
1896         return s;
1897 } /* core_data_suite */
1899 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */