Code

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