Code

data: Added support for a "regex" data-type.
[sysdb.git] / t / unit / core / data_test.c
1 /*
2  * SysDB - t/unit/core/data_test.c
3  * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #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         d2.type = SDB_TYPE_INTEGER;
42         d2.data.integer = 4711;
43         memset(&d1, 0, sizeof(d1));
44         check = sdb_data_copy(&d1, &d2);
45         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
46         fail_unless(d1.type == d2.type,
47                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
48                         d1.type, d2.type);
49         fail_unless(d1.data.integer == d2.data.integer,
50                         "sdb_data_copy() didn't copy integer data: got: %d; expected: %d",
51                         d1.data.integer, d2.data.integer);
53         d2.type = SDB_TYPE_DECIMAL;
54         d2.data.decimal = 47.11;
55         check = sdb_data_copy(&d1, &d2);
56         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
57         fail_unless(d1.type == d2.type,
58                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
59                         d1.type, d2.type);
60         fail_unless(d1.data.decimal == d2.data.decimal,
61                         "sdb_data_copy() didn't copy decimal data: got: %f; expected: %f",
62                         d1.data.decimal, d2.data.decimal);
64         d2.type = SDB_TYPE_STRING;
65         d2.data.string = "some string";
66         check = sdb_data_copy(&d1, &d2);
67         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
68         fail_unless(d1.type == d2.type,
69                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
70                         d1.type, d2.type);
71         fail_unless(!strcmp(d1.data.string, d2.data.string),
72                         "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
73                         d1.data.string, d2.data.string);
75         sdb_data_free_datum(&d1);
76         fail_unless(d1.data.string == NULL,
77                         "sdb_data_free_datum() didn't free string data");
79         d1.type = 0;
80         d2.type = SDB_TYPE_STRING;
81         d2.data.string = NULL;
82         check = sdb_data_copy(&d1, &d2);
83         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
84         fail_unless(d1.type == d2.type,
85                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
86                         d1.type, d2.type);
87         fail_unless(d1.data.string == d2.data.string,
88                         "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
89                         d1.data.string, d2.data.string);
91         sdb_data_free_datum(&d1);
92         fail_unless(d1.data.string == NULL,
93                         "sdb_data_free_datum() didn't free string data");
95         d2.type = SDB_TYPE_DATETIME;
96         d2.data.datetime = 4711;
97         check = sdb_data_copy(&d1, &d2);
98         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
99         fail_unless(d1.type == d2.type,
100                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
101                         d1.type, d2.type);
102         fail_unless(d1.data.datetime == d2.data.datetime,
103                         "sdb_data_copy() didn't copy datetime data: got: %d; expected: %d",
104                         d1.data.datetime, d2.data.datetime);
106         d2.type = SDB_TYPE_BINARY;
107         d2.data.binary.datum = (unsigned char *)"some string";
108         d2.data.binary.length = strlen((const char *)d2.data.binary.datum);
109         check = sdb_data_copy(&d1, &d2);
110         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
111         fail_unless(d1.type == d2.type,
112                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
113                         d1.type, d2.type);
114         fail_unless(d1.data.binary.length == d2.data.binary.length,
115                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
116                         d1.data.binary.length, d2.data.binary.length);
117         fail_unless(!memcmp(d1.data.binary.datum, d2.data.binary.datum,
118                                 d2.data.binary.length),
119                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
120                         d1.data.binary.datum, d2.data.binary.datum);
122         sdb_data_free_datum(&d1);
123         fail_unless(d1.data.binary.length == 0,
124                         "sdb_data_free_datum() didn't reset binary datum length");
125         fail_unless(d1.data.binary.datum == NULL,
126                         "sdb_data_free_datum() didn't free binary datum");
128         d1.type = 0;
129         d2.type = SDB_TYPE_BINARY;
130         d2.data.binary.datum = NULL;
131         d2.data.binary.length = 0;
132         check = sdb_data_copy(&d1, &d2);
133         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
134         fail_unless(d1.type == d2.type,
135                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
136                         d1.type, d2.type);
137         fail_unless(d1.data.binary.length == d2.data.binary.length,
138                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
139                         d1.data.binary.length, d2.data.binary.length);
140         fail_unless(d1.data.binary.datum == d2.data.binary.datum,
141                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
142                         d1.data.binary.datum, d2.data.binary.datum);
144         sdb_data_free_datum(&d1);
145         fail_unless(d1.data.binary.length == 0,
146                         "sdb_data_free_datum() didn't reset binary datum length");
147         fail_unless(d1.data.binary.datum == NULL,
148                         "sdb_data_free_datum() didn't free binary datum");
150         check = sdb_data_parse(".", SDB_TYPE_REGEX, &d2);
151         fail_unless(check == 0,
152                         "INTERNAL ERROR: Failed to parse regex '.'");
153         assert(d2.type == SDB_TYPE_REGEX);
154         check = sdb_data_copy(&d1, &d2);
155         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
156         fail_unless(d1.type == d2.type,
157                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
158                         d1.type, d2.type);
159         fail_unless(d1.data.re.raw != d2.data.re.raw,
160                         "sdb_data_copy() copy string pointer");
161         fail_unless(!strcmp(d1.data.re.raw, d2.data.re.raw),
162                         "sdb_data_copy() didn't copy raw regex: got: %s; expected: %s",
163                         d1.data.re.raw, d2.data.re.raw);
164         sdb_data_free_datum(&d2);
166         sdb_data_free_datum(&d1);
167         fail_unless(d1.data.re.raw == NULL,
168                         "sdb_data_free_datum() didn't reset raw regex");
170         d2.type = SDB_TYPE_REGEX;
171         d2.data.re.raw = NULL;
172         check = sdb_data_copy(&d1, &d2);
173         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
174         fail_unless(d1.type == d2.type,
175                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
176                         d1.type, d2.type);
177         fail_unless(d1.data.re.raw == d2.data.re.raw,
178                         "sdb_data_copy() didn't copy raw regex: got: %s; expected: %s",
179                         d1.data.re.raw, d2.data.re.raw);
181         sdb_data_free_datum(&d1);
182         fail_unless(d1.data.re.raw == NULL,
183                         "sdb_data_free_datum() didn't reset raw regex");
185 END_TEST
187 START_TEST(test_cmp)
189         struct {
190                 sdb_data_t d1;
191                 sdb_data_t d2;
192                 int expected;
193         } golden_data[] = {
194                 {
195                         { SDB_TYPE_INTEGER, { .integer = 47 } },
196                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
197                         -1,
198                 },
199                 {
200                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
201                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
202                         0,
203                 },
204                 {
205                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
206                         { SDB_TYPE_INTEGER, { .integer = 47 } },
207                         1,
208                 },
209                 {
210                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
211                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
212                         -1,
213                 },
214                 {
215                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
216                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
217                         0,
218                 },
219                 {
220                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
221                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
222                         1,
223                 },
224                 {
225                         { SDB_TYPE_STRING, { .string = NULL } },
226                         { SDB_TYPE_STRING, { .string = "" } },
227                         -1,
228                 },
229                 {
230                         { SDB_TYPE_STRING, { .string = NULL } },
231                         { SDB_TYPE_STRING, { .string = NULL } },
232                         0,
233                 },
234                 {
235                         { SDB_TYPE_STRING, { .string = "" } },
236                         { SDB_TYPE_STRING, { .string = NULL } },
237                         1,
238                 },
239                 {
240                         { SDB_TYPE_STRING, { .string = "a" } },
241                         { SDB_TYPE_STRING, { .string = "b" } },
242                         -1,
243                 },
244                 {
245                         { SDB_TYPE_STRING, { .string = "a" } },
246                         { SDB_TYPE_STRING, { .string = "ab" } },
247                         -1,
248                 },
249                 {
250                         { SDB_TYPE_STRING, { .string = "a" } },
251                         { SDB_TYPE_STRING, { .string = "a" } },
252                         0,
253                 },
254                 {
255                         { SDB_TYPE_STRING, { .string = "b" } },
256                         { SDB_TYPE_STRING, { .string = "a" } },
257                         1,
258                 },
259                 {
260                         { SDB_TYPE_STRING, { .string = "ab" } },
261                         { SDB_TYPE_STRING, { .string = "a" } },
262                         1,
263                 },
264                 {
265                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
266                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
267                         -1,
268                 },
269                 {
270                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
271                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
272                         0,
273                 },
274                 {
275                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
276                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
277                         1,
278                 },
279                 {
280                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
281                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
282                         -1,
283                 },
284                 {
285                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
286                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
287                         0,
288                 },
289                 {
290                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
291                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
292                         1,
293                 },
294                 {
295                         {
296                                 SDB_TYPE_BINARY,
297                                 { .binary = { 3, (unsigned char *)"a\0a" } },
298                         },
299                         {
300                                 SDB_TYPE_BINARY,
301                                 { .binary = { 3, (unsigned char *)"a\0b" } },
302                         },
303                         -1,
304                 },
305                 {
306                         {
307                                 SDB_TYPE_BINARY,
308                                 { .binary = { 1, (unsigned char *)"a" } },
309                         },
310                         {
311                                 SDB_TYPE_BINARY,
312                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
313                         },
314                         -1,
315                 },
316                 {
317                         {
318                                 SDB_TYPE_BINARY,
319                                 { .binary = { 3, (unsigned char *)"a\0a" } },
320                         },
321                         {
322                                 SDB_TYPE_BINARY,
323                                 { .binary = { 3, (unsigned char *)"a\0a" } },
324                         },
325                         0,
326                 },
327                 {
328                         {
329                                 SDB_TYPE_BINARY,
330                                 { .binary = { 3, (unsigned char *)"a\0b" } },
331                         },
332                         {
333                                 SDB_TYPE_BINARY,
334                                 { .binary = { 3, (unsigned char *)"a\0a" } },
335                         },
336                         1,
337                 },
338                 {
339                         {
340                                 SDB_TYPE_BINARY,
341                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
342                         },
343                         {
344                                 SDB_TYPE_BINARY,
345                                 { .binary = { 1, (unsigned char *)"a" } },
346                         },
347                         1,
348                 },
349                 {
350                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
351                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
352                         0,
353                 },
354                 {
355                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
356                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
357                         -1,
358                 },
359                 {
360                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
361                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
362                         1,
363                 },
364         };
366         size_t i;
368         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
369                 int check = sdb_data_cmp(&golden_data[i].d1, &golden_data[i].d2);
370                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
371                 if (check != golden_data[i].expected) {
372                         char d1_str[64] = "", d2_str[64] = "";
373                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
374                                         SDB_DOUBLE_QUOTED);
375                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
376                                         SDB_DOUBLE_QUOTED);
377                         fail("sdb_data_cmp(%s, %s) = %d; expected: %d",
378                                         d1_str, d2_str, check, golden_data[i].expected);
379                 }
380         }
382 END_TEST
384 START_TEST(test_strcmp)
386         struct {
387                 sdb_data_t d1;
388                 sdb_data_t d2;
389                 int expected;
390         } golden_data[] = {
391                 /* same data as for the sdb_data_cmp test; in case the types match,
392                  * both functions should behave the same (except for some loss in
393                  * precision, e.g. when formatting datetime values) */
394                 {
395                         { SDB_TYPE_INTEGER, { .integer = 47 } },
396                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
397                         -1,
398                 },
399                 {
400                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
401                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
402                         0,
403                 },
404                 {
405                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
406                         { SDB_TYPE_INTEGER, { .integer = 47 } },
407                         1,
408                 },
409                 {
410                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
411                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
412                         -1,
413                 },
414                 {
415                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
416                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
417                         0,
418                 },
419                 {
420                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
421                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
422                         1,
423                 },
424                 {
425                         { SDB_TYPE_STRING, { .string = NULL } },
426                         { SDB_TYPE_STRING, { .string = "" } },
427                         -1,
428                 },
429                 {
430                         { SDB_TYPE_STRING, { .string = NULL } },
431                         { SDB_TYPE_STRING, { .string = NULL } },
432                         0,
433                 },
434                 {
435                         { SDB_TYPE_STRING, { .string = "" } },
436                         { SDB_TYPE_STRING, { .string = NULL } },
437                         1,
438                 },
439                 {
440                         { SDB_TYPE_STRING, { .string = "a" } },
441                         { SDB_TYPE_STRING, { .string = "b" } },
442                         -1,
443                 },
444                 {
445                         { SDB_TYPE_STRING, { .string = "a" } },
446                         { SDB_TYPE_STRING, { .string = "ab" } },
447                         -1,
448                 },
449                 {
450                         { SDB_TYPE_STRING, { .string = "a" } },
451                         { SDB_TYPE_STRING, { .string = "a" } },
452                         0,
453                 },
454                 {
455                         { SDB_TYPE_STRING, { .string = "b" } },
456                         { SDB_TYPE_STRING, { .string = "a" } },
457                         1,
458                 },
459                 {
460                         { SDB_TYPE_STRING, { .string = "ab" } },
461                         { SDB_TYPE_STRING, { .string = "a" } },
462                         1,
463                 },
464                 {
465                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
466                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
467                         -1,
468                 },
469                 {
470                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
471                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
472                         0,
473                 },
474                 {
475                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
476                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
477                         1,
478                 },
479                 {
480                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
481                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
482                         -1,
483                 },
484                 {
485                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
486                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
487                         0,
488                 },
489                 {
490                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
491                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
492                         1,
493                 },
494                 {
495                         {
496                                 SDB_TYPE_BINARY,
497                                 { .binary = { 3, (unsigned char *)"a\0a" } },
498                         },
499                         {
500                                 SDB_TYPE_BINARY,
501                                 { .binary = { 3, (unsigned char *)"a\0b" } },
502                         },
503                         -1,
504                 },
505                 {
506                         {
507                                 SDB_TYPE_BINARY,
508                                 { .binary = { 1, (unsigned char *)"a" } },
509                         },
510                         {
511                                 SDB_TYPE_BINARY,
512                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
513                         },
514                         -1,
515                 },
516                 {
517                         {
518                                 SDB_TYPE_BINARY,
519                                 { .binary = { 3, (unsigned char *)"a\0a" } },
520                         },
521                         {
522                                 SDB_TYPE_BINARY,
523                                 { .binary = { 3, (unsigned char *)"a\0a" } },
524                         },
525                         0,
526                 },
527                 {
528                         {
529                                 SDB_TYPE_BINARY,
530                                 { .binary = { 3, (unsigned char *)"a\0b" } },
531                         },
532                         {
533                                 SDB_TYPE_BINARY,
534                                 { .binary = { 3, (unsigned char *)"a\0a" } },
535                         },
536                         1,
537                 },
538                 {
539                         {
540                                 SDB_TYPE_BINARY,
541                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
542                         },
543                         {
544                                 SDB_TYPE_BINARY,
545                                 { .binary = { 1, (unsigned char *)"a" } },
546                         },
547                         1,
548                 },
549                 {
550                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
551                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
552                         0,
553                 },
554                 {
555                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
556                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
557                         -1,
558                 },
559                 {
560                         { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
561                         { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
562                         1,
563                 },
564                 /* type mismatches */
565                 {
566                         { SDB_TYPE_INTEGER, { .integer = 123 } },
567                         { SDB_TYPE_STRING, { .string = "123" } },
568                         0,
569                 },
570                 {
571                         { SDB_TYPE_INTEGER, { .integer = 120 } },
572                         { SDB_TYPE_STRING, { .string = "123" } },
573                         -1,
574                 },
575                 {
576                         { SDB_TYPE_STRING, { .string = "123" } },
577                         { SDB_TYPE_INTEGER, { .integer = 120 } },
578                         1,
579                 },
580                 {
581                         { SDB_TYPE_STRING, { .string = "12.3" } },
582                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
583                         0,
584                 },
585                 {
586                         { SDB_TYPE_STRING, { .string = "12.0" } },
587                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
588                         -1,
589                 },
590                 {
591                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
592                         { SDB_TYPE_STRING, { .string = "12.0" } },
593                         1,
594                 },
595                 {
596                         { SDB_TYPE_REGEX, { .re = { "regex", empty_re } } },
597                         { SDB_TYPE_STRING, { .string = "/regex/" } },
598                         0,
599                 },
600         };
602         size_t i;
604         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
605                 int check = sdb_data_strcmp(&golden_data[i].d1, &golden_data[i].d2);
606                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
607                 if (check != golden_data[i].expected) {
608                         char d1_str[64] = "", d2_str[64] = "";
609                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
610                                         SDB_DOUBLE_QUOTED);
611                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
612                                         SDB_DOUBLE_QUOTED);
613                         fail("sdb_data_strcmp(%s, %s) = %d; expected: %d",
614                                         d1_str, d2_str, check, golden_data[i].expected);
615                 }
616         }
618 END_TEST
620 START_TEST(test_expr_eval)
622         struct {
623                 sdb_data_t d1;
624                 sdb_data_t d2;
625                 sdb_data_t expected_add;
626                 sdb_data_t expected_sub;
627                 sdb_data_t expected_mul;
628                 sdb_data_t expected_div;
629                 sdb_data_t expected_mod;
630                 sdb_data_t expected_concat;
631         } golden_data[] = {
632                 {
633                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
634                         { SDB_TYPE_INTEGER, { .integer = 47 } },
635                         { SDB_TYPE_INTEGER, { .integer = 4758 } },
636                         { SDB_TYPE_INTEGER, { .integer = 4664 } },
637                         { SDB_TYPE_INTEGER, { .integer = 221417 } },
638                         { SDB_TYPE_INTEGER, { .integer = 100 } },
639                         { SDB_TYPE_INTEGER, { .integer = 11 } },
640                         SDB_DATA_INIT,
641                 },
642                 {
643                         { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
644                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
645                         { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
646                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
647                         { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
648                         { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
649                         { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
650                         SDB_DATA_INIT,
651                 },
652                 {
653                         { SDB_TYPE_STRING, { .string = NULL } },
654                         { SDB_TYPE_STRING, { .string = "" } },
655                         SDB_DATA_INIT,
656                         SDB_DATA_INIT,
657                         SDB_DATA_INIT,
658                         SDB_DATA_INIT,
659                         SDB_DATA_INIT,
660                         { SDB_TYPE_STRING, { .string = "" } },
661                 },
662                 {
663                         { SDB_TYPE_STRING, { .string = NULL } },
664                         { SDB_TYPE_STRING, { .string = NULL } },
665                         SDB_DATA_INIT,
666                         SDB_DATA_INIT,
667                         SDB_DATA_INIT,
668                         SDB_DATA_INIT,
669                         SDB_DATA_INIT,
670                         { SDB_TYPE_STRING, { .string = NULL } },
671                 },
672                 {
673                         { SDB_TYPE_STRING, { .string = "" } },
674                         { SDB_TYPE_STRING, { .string = NULL } },
675                         SDB_DATA_INIT,
676                         SDB_DATA_INIT,
677                         SDB_DATA_INIT,
678                         SDB_DATA_INIT,
679                         SDB_DATA_INIT,
680                         { SDB_TYPE_STRING, { .string = "" } },
681                 },
682                 {
683                         { SDB_TYPE_STRING, { .string = "a" } },
684                         { SDB_TYPE_STRING, { .string = "b" } },
685                         SDB_DATA_INIT,
686                         SDB_DATA_INIT,
687                         SDB_DATA_INIT,
688                         SDB_DATA_INIT,
689                         SDB_DATA_INIT,
690                         { SDB_TYPE_STRING, { .string = "ab" } },
691                 },
692                 {
693                         { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
694                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
695                         { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
696                         { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
697                         { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
698                         { SDB_TYPE_DATETIME, { .datetime = 10001 } },
699                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
700                         SDB_DATA_INIT,
701                 },
702                 {
703                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
704                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
705                         SDB_DATA_INIT,
706                         SDB_DATA_INIT,
707                         SDB_DATA_INIT,
708                         SDB_DATA_INIT,
709                         SDB_DATA_INIT,
710                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
711                 },
712                 {
713                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
714                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
715                         SDB_DATA_INIT,
716                         SDB_DATA_INIT,
717                         SDB_DATA_INIT,
718                         SDB_DATA_INIT,
719                         SDB_DATA_INIT,
720                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
721                 },
722                 {
723                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
724                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
725                         SDB_DATA_INIT,
726                         SDB_DATA_INIT,
727                         SDB_DATA_INIT,
728                         SDB_DATA_INIT,
729                         SDB_DATA_INIT,
730                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
731                 },
732                 {
733                         {
734                                 SDB_TYPE_BINARY,
735                                 { .binary = { 3, (unsigned char *)"a\0a" } },
736                         },
737                         {
738                                 SDB_TYPE_BINARY,
739                                 { .binary = { 3, (unsigned char *)"b\0b" } },
740                         },
741                         SDB_DATA_INIT,
742                         SDB_DATA_INIT,
743                         SDB_DATA_INIT,
744                         SDB_DATA_INIT,
745                         SDB_DATA_INIT,
746                         {
747                                 SDB_TYPE_BINARY,
748                                 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
749                         },
750                 },
751                 {
752                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
753                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
754                         SDB_DATA_INIT,
755                         SDB_DATA_INIT,
756                         SDB_DATA_INIT,
757                         SDB_DATA_INIT,
758                         SDB_DATA_INIT,
759                         SDB_DATA_INIT,
760                 },
761                 /* supported type-mismatches */
762                 {
763                         /* int * datetime */
764                         { SDB_TYPE_INTEGER,  { .integer  = 20 } },
765                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
766                         SDB_DATA_INIT,
767                         SDB_DATA_INIT,
768                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
769                         SDB_DATA_INIT,
770                         SDB_DATA_INIT,
771                         SDB_DATA_INIT,
772                 },
773                 {
774                         /* datetime * int, datetime / int, datetime % int */
775                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
776                         { SDB_TYPE_INTEGER,  { .integer  = 2 } },
777                         SDB_DATA_INIT,
778                         SDB_DATA_INIT,
779                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
780                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
781                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
782                         SDB_DATA_INIT,
783                 },
784                 {
785                         /* float * datetime */
786                         { SDB_TYPE_DECIMAL,  { .decimal  = 20.0 } },
787                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
788                         SDB_DATA_INIT,
789                         SDB_DATA_INIT,
790                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
791                         SDB_DATA_INIT,
792                         SDB_DATA_INIT,
793                         SDB_DATA_INIT,
794                 },
795                 {
796                         /* datetime * float, datetime / float, datetime % float */
797                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
798                         { SDB_TYPE_DECIMAL,  { .decimal  = 2.0 } },
799                         SDB_DATA_INIT,
800                         SDB_DATA_INIT,
801                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
802                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
803                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
804                         SDB_DATA_INIT,
805                 },
806         };
808         size_t i;
810         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
811                 struct {
812                         int op;
813                         sdb_data_t expected;
814                 } tests[] = {
815                         { SDB_DATA_ADD, golden_data[i].expected_add },
816                         { SDB_DATA_SUB, golden_data[i].expected_sub },
817                         { SDB_DATA_MUL, golden_data[i].expected_mul },
818                         { SDB_DATA_DIV, golden_data[i].expected_div },
819                         { SDB_DATA_MOD, golden_data[i].expected_mod },
820                         { SDB_DATA_CONCAT, golden_data[i].expected_concat },
821                 };
823                 size_t j;
824                 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
825                         sdb_data_t res;
826                         int check;
828                         char d1_str[64] = "", d2_str[64] = "";
829                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
830                                         SDB_DOUBLE_QUOTED);
831                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
832                                         SDB_DOUBLE_QUOTED);
834                         check = sdb_data_expr_eval(tests[j].op,
835                                         &golden_data[i].d1, &golden_data[i].d2, &res);
836                         fail_unless((check == 0) == (tests[j].expected.type != 0),
837                                         "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
838                                         SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
839                                         tests[j].expected.type == 0 ? -1 : 0);
840                         if (tests[j].expected.type == 0)
841                                 continue;
843                         check = sdb_data_cmp(&res, &tests[j].expected);
844                         if (check != 0) {
845                                 char res_str[64] = "", expected_str[64] = "";
846                                 sdb_data_format(&res, res_str, sizeof(res_str),
847                                                 SDB_DOUBLE_QUOTED);
848                                 sdb_data_format(&tests[j].expected, expected_str,
849                                                 sizeof(expected_str), SDB_DOUBLE_QUOTED);
850                                 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s; "
851                                                 "expected: %s", SDB_DATA_OP_TO_STRING(tests[j].op),
852                                                 d1_str, d2_str, res_str, expected_str);
853                         }
855                         sdb_data_free_datum(&res);
856                 }
857         }
859 END_TEST
861 START_TEST(test_format)
863         struct {
864                 sdb_data_t datum;
865                 const char *expected;
866         } golden_data[] = {
867                 {
868                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
869                         "4711",
870                 },
871                 {
872                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
873                         "65536",
874                 },
875                 {
876                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
877                         "12.3",
878                 },
879                 {
880                         { SDB_TYPE_STRING, { .string = NULL } },
881                         "\"<NULL>\"",
882                 },
883                 {
884                         { SDB_TYPE_STRING, { .string = "this is a test" } },
885                         "\"this is a test\"",
886                 },
887                 {
888                         { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
889                         "\"special \\\\ \\\" characters\"",
890                 },
891                 {
892                         { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
893                         "\"1984-12-06 02:11:54 +0000\"",
894                 },
895                 {
896                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
897                         "\"<NULL>\"",
898                 },
899                 {
900                         {
901                                 SDB_TYPE_BINARY,
902                                 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
903                         },
904                         "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
905                 },
906                 {
907                         { SDB_TYPE_REGEX, { .re = { "some regex", empty_re } } },
908                         "\"/some regex/\"",
909                 },
910         };
912         size_t i;
914         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
915                 sdb_data_t *datum = &golden_data[i].datum;
916                 char buf[sdb_data_strlen(datum) + 2];
917                 int check;
919                 memset(buf, (int)'A', sizeof(buf));
921                 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
922                                 SDB_DOUBLE_QUOTED);
923                 fail_unless(check > 0,
924                                 "sdb_data_format(type=%s) = %d; expected: >0",
925                                 SDB_TYPE_TO_STRING(datum->type), check);
926                 fail_unless(! strcmp(buf, golden_data[i].expected),
927                                 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
928                                 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
930                 fail_unless((size_t)check <= sizeof(buf) - 2,
931                                 "sdb_data_format(type=%s) wrote %d bytes; "
932                                 "expected <= %zu based on sdb_data_strlen()",
933                                 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
935                 fail_unless(buf[sizeof(buf) - 2] == '\0',
936                                 "sdb_data_format(type=%s) did not nul-terminate the buffer",
937                                 SDB_TYPE_TO_STRING(datum->type));
938                 fail_unless(buf[sizeof(buf) - 1] == 'A',
939                                 "sdb_data_format(type=%s) wrote past the end of the buffer",
940                                 SDB_TYPE_TO_STRING(datum->type));
941         }
943 END_TEST
945 START_TEST(test_parse)
947         struct {
948                 char *input;
949                 sdb_data_t result;
950                 int expected;
951         } golden_data[] = {
952                 { "4711",    { SDB_TYPE_INTEGER,  { .integer  = 4711 } },          0 },
953                 { "0x10",    { SDB_TYPE_INTEGER,  { .integer  = 16 } },            0 },
954                 { "010",     { SDB_TYPE_INTEGER,  { .integer  = 8 } },             0 },
955                 { "abc",     { SDB_TYPE_INTEGER,  { .integer  = 0 } },            -1 },
956                 { "1.2",     { SDB_TYPE_DECIMAL,  { .decimal  = 1.2 } },           0 },
957                 { "0x1p+16", { SDB_TYPE_DECIMAL,  { .decimal  = 65536.0 } },       0 },
958                 { "abc",     { SDB_TYPE_DECIMAL,  { .decimal  = 0.0 } },          -1 },
959                 { "abc",     { SDB_TYPE_STRING,   { .string   = "abc" } },         0 },
960                 { ".4",      { SDB_TYPE_DATETIME, { .datetime = 400000000 } },     0 },
961                 { "abc",     { SDB_TYPE_DATETIME, { .datetime = 0 } },            -1 },
962                 { "abc",     { SDB_TYPE_BINARY,
963                                          { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
964                 { "abc",     { SDB_TYPE_REGEX,    { .re = { "abc", empty_re } } }, 0 },
965                 { "(|",      { SDB_TYPE_REGEX,    { .re = { "", empty_re } } },   -1 },
966         };
968         size_t i;
970         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
971                 sdb_data_t result;
972                 int type, check;
974                 memset(&result, 0, sizeof(result));
975                 type = golden_data[i].result.type;
976                 check = sdb_data_parse(golden_data[i].input, type, &result);
977                 fail_unless(check == golden_data[i].expected,
978                                 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
979                                 golden_data[i].input, type, check, golden_data[i].expected);
981                 if (check)
982                         continue;
984                 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
985                                 "sdb_data_parse(%s, %d, <d>) did not create expected result",
986                                 golden_data[i].input, type);
988                 if (type == SDB_TYPE_STRING)
989                         fail_unless(golden_data[i].input == result.data.string,
990                                         "sdb_data_parse(%s, %d, <d>) modified input string",
991                                         golden_data[i].input, type);
992                 if (type == SDB_TYPE_BINARY)
993                         fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
994                                         "sdb_data_parse(%s, %d, <d>) modified input string",
995                                         golden_data[i].input, type);
996                 if (type == SDB_TYPE_REGEX) {
997                         fail_unless(golden_data[i].input != result.data.re.raw,
998                                         "sdb_data_parse(%s, %d, <d>) copied input string",
999                                         golden_data[i].input, type);
1000                         sdb_data_free_datum(&result);
1001                 }
1002         }
1004 END_TEST
1006 Suite *
1007 core_data_suite(void)
1009         Suite *s = suite_create("core::data");
1010         TCase *tc;
1012         tc = tcase_create("core");
1013         tcase_add_test(tc, test_data);
1014         tcase_add_test(tc, test_cmp);
1015         tcase_add_test(tc, test_strcmp);
1016         tcase_add_test(tc, test_expr_eval);
1017         tcase_add_test(tc, test_format);
1018         tcase_add_test(tc, test_parse);
1019         suite_add_tcase(s, tc);
1021         return s;
1022 } /* core_data_suite */
1024 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */