Code

data: Added sdb_data_parse_op().
[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_parse_op)
622         struct {
623                 const char *op;
624                 int id;
625         } golden_data[] = {
626                 { "+",  SDB_DATA_ADD },
627                 { "-",  SDB_DATA_SUB },
628                 { "*",  SDB_DATA_MUL },
629                 { "/",  SDB_DATA_DIV },
630                 { "%",  SDB_DATA_MOD },
631                 { "||", SDB_DATA_CONCAT },
632                 { "&&", -1 },
633         };
635         size_t i;
637         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
638                 const char *op;
639                 int id;
641                 id = sdb_data_parse_op(golden_data[i].op);
642                 fail_unless(id == golden_data[i].id,
643                                 "sdb_data_parse_op(%s) = %d; expected: %d",
644                                 golden_data[i].op, id, golden_data[i].id);
646                 if (id <= 0)
647                         continue;
649                 op = SDB_DATA_OP_TO_STRING(id);
650                 fail_unless(!strcmp(op, golden_data[i].op),
651                                 "SDB_DATA_OP_TO_STRING(%d) = '%s'; expected: '%s'",
652                                 id, op, golden_data[i].op);
653         }
655 END_TEST
657 START_TEST(test_expr_eval)
659         struct {
660                 sdb_data_t d1;
661                 sdb_data_t d2;
662                 sdb_data_t expected_add;
663                 sdb_data_t expected_sub;
664                 sdb_data_t expected_mul;
665                 sdb_data_t expected_div;
666                 sdb_data_t expected_mod;
667                 sdb_data_t expected_concat;
668         } golden_data[] = {
669                 {
670                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
671                         { SDB_TYPE_INTEGER, { .integer = 47 } },
672                         { SDB_TYPE_INTEGER, { .integer = 4758 } },
673                         { SDB_TYPE_INTEGER, { .integer = 4664 } },
674                         { SDB_TYPE_INTEGER, { .integer = 221417 } },
675                         { SDB_TYPE_INTEGER, { .integer = 100 } },
676                         { SDB_TYPE_INTEGER, { .integer = 11 } },
677                         SDB_DATA_INIT,
678                 },
679                 {
680                         { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
681                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
682                         { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
683                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
684                         { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
685                         { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
686                         { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
687                         SDB_DATA_INIT,
688                 },
689                 {
690                         { SDB_TYPE_STRING, { .string = NULL } },
691                         { SDB_TYPE_STRING, { .string = "" } },
692                         SDB_DATA_INIT,
693                         SDB_DATA_INIT,
694                         SDB_DATA_INIT,
695                         SDB_DATA_INIT,
696                         SDB_DATA_INIT,
697                         { SDB_TYPE_STRING, { .string = "" } },
698                 },
699                 {
700                         { SDB_TYPE_STRING, { .string = NULL } },
701                         { SDB_TYPE_STRING, { .string = NULL } },
702                         SDB_DATA_INIT,
703                         SDB_DATA_INIT,
704                         SDB_DATA_INIT,
705                         SDB_DATA_INIT,
706                         SDB_DATA_INIT,
707                         { SDB_TYPE_STRING, { .string = NULL } },
708                 },
709                 {
710                         { SDB_TYPE_STRING, { .string = "" } },
711                         { SDB_TYPE_STRING, { .string = NULL } },
712                         SDB_DATA_INIT,
713                         SDB_DATA_INIT,
714                         SDB_DATA_INIT,
715                         SDB_DATA_INIT,
716                         SDB_DATA_INIT,
717                         { SDB_TYPE_STRING, { .string = "" } },
718                 },
719                 {
720                         { SDB_TYPE_STRING, { .string = "a" } },
721                         { SDB_TYPE_STRING, { .string = "b" } },
722                         SDB_DATA_INIT,
723                         SDB_DATA_INIT,
724                         SDB_DATA_INIT,
725                         SDB_DATA_INIT,
726                         SDB_DATA_INIT,
727                         { SDB_TYPE_STRING, { .string = "ab" } },
728                 },
729                 {
730                         { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
731                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
732                         { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
733                         { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
734                         { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
735                         { SDB_TYPE_DATETIME, { .datetime = 10001 } },
736                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
737                         SDB_DATA_INIT,
738                 },
739                 {
740                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
741                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
742                         SDB_DATA_INIT,
743                         SDB_DATA_INIT,
744                         SDB_DATA_INIT,
745                         SDB_DATA_INIT,
746                         SDB_DATA_INIT,
747                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
748                 },
749                 {
750                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
751                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
752                         SDB_DATA_INIT,
753                         SDB_DATA_INIT,
754                         SDB_DATA_INIT,
755                         SDB_DATA_INIT,
756                         SDB_DATA_INIT,
757                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
758                 },
759                 {
760                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
761                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
762                         SDB_DATA_INIT,
763                         SDB_DATA_INIT,
764                         SDB_DATA_INIT,
765                         SDB_DATA_INIT,
766                         SDB_DATA_INIT,
767                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
768                 },
769                 {
770                         {
771                                 SDB_TYPE_BINARY,
772                                 { .binary = { 3, (unsigned char *)"a\0a" } },
773                         },
774                         {
775                                 SDB_TYPE_BINARY,
776                                 { .binary = { 3, (unsigned char *)"b\0b" } },
777                         },
778                         SDB_DATA_INIT,
779                         SDB_DATA_INIT,
780                         SDB_DATA_INIT,
781                         SDB_DATA_INIT,
782                         SDB_DATA_INIT,
783                         {
784                                 SDB_TYPE_BINARY,
785                                 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
786                         },
787                 },
788                 {
789                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
790                         { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
791                         SDB_DATA_INIT,
792                         SDB_DATA_INIT,
793                         SDB_DATA_INIT,
794                         SDB_DATA_INIT,
795                         SDB_DATA_INIT,
796                         SDB_DATA_INIT,
797                 },
798                 /* supported type-mismatches */
799                 {
800                         /* int * datetime */
801                         { SDB_TYPE_INTEGER,  { .integer  = 20 } },
802                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
803                         SDB_DATA_INIT,
804                         SDB_DATA_INIT,
805                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
806                         SDB_DATA_INIT,
807                         SDB_DATA_INIT,
808                         SDB_DATA_INIT,
809                 },
810                 {
811                         /* datetime * int, datetime / int, datetime % int */
812                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
813                         { SDB_TYPE_INTEGER,  { .integer  = 2 } },
814                         SDB_DATA_INIT,
815                         SDB_DATA_INIT,
816                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
817                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
818                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
819                         SDB_DATA_INIT,
820                 },
821                 {
822                         /* float * datetime */
823                         { SDB_TYPE_DECIMAL,  { .decimal  = 20.0 } },
824                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
825                         SDB_DATA_INIT,
826                         SDB_DATA_INIT,
827                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
828                         SDB_DATA_INIT,
829                         SDB_DATA_INIT,
830                         SDB_DATA_INIT,
831                 },
832                 {
833                         /* datetime * float, datetime / float, datetime % float */
834                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
835                         { SDB_TYPE_DECIMAL,  { .decimal  = 2.0 } },
836                         SDB_DATA_INIT,
837                         SDB_DATA_INIT,
838                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
839                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
840                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
841                         SDB_DATA_INIT,
842                 },
843         };
845         size_t i;
847         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
848                 struct {
849                         int op;
850                         sdb_data_t expected;
851                 } tests[] = {
852                         { SDB_DATA_ADD, golden_data[i].expected_add },
853                         { SDB_DATA_SUB, golden_data[i].expected_sub },
854                         { SDB_DATA_MUL, golden_data[i].expected_mul },
855                         { SDB_DATA_DIV, golden_data[i].expected_div },
856                         { SDB_DATA_MOD, golden_data[i].expected_mod },
857                         { SDB_DATA_CONCAT, golden_data[i].expected_concat },
858                 };
860                 size_t j;
861                 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
862                         sdb_data_t res;
863                         int check;
865                         char d1_str[64] = "", d2_str[64] = "";
866                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
867                                         SDB_DOUBLE_QUOTED);
868                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
869                                         SDB_DOUBLE_QUOTED);
871                         check = sdb_data_expr_eval(tests[j].op,
872                                         &golden_data[i].d1, &golden_data[i].d2, &res);
873                         fail_unless((check == 0) == (tests[j].expected.type != 0),
874                                         "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
875                                         SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
876                                         tests[j].expected.type == 0 ? -1 : 0);
877                         if (tests[j].expected.type == 0)
878                                 continue;
880                         check = sdb_data_cmp(&res, &tests[j].expected);
881                         if (check != 0) {
882                                 char res_str[64] = "", expected_str[64] = "";
883                                 sdb_data_format(&res, res_str, sizeof(res_str),
884                                                 SDB_DOUBLE_QUOTED);
885                                 sdb_data_format(&tests[j].expected, expected_str,
886                                                 sizeof(expected_str), SDB_DOUBLE_QUOTED);
887                                 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s; "
888                                                 "expected: %s", SDB_DATA_OP_TO_STRING(tests[j].op),
889                                                 d1_str, d2_str, res_str, expected_str);
890                         }
892                         sdb_data_free_datum(&res);
893                 }
894         }
896 END_TEST
898 START_TEST(test_format)
900         struct {
901                 sdb_data_t datum;
902                 const char *expected;
903         } golden_data[] = {
904                 {
905                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
906                         "4711",
907                 },
908                 {
909                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
910                         "65536",
911                 },
912                 {
913                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
914                         "12.3",
915                 },
916                 {
917                         { SDB_TYPE_STRING, { .string = NULL } },
918                         "\"<NULL>\"",
919                 },
920                 {
921                         { SDB_TYPE_STRING, { .string = "this is a test" } },
922                         "\"this is a test\"",
923                 },
924                 {
925                         { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
926                         "\"special \\\\ \\\" characters\"",
927                 },
928                 {
929                         { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
930                         "\"1984-12-06 02:11:54 +0000\"",
931                 },
932                 {
933                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
934                         "\"<NULL>\"",
935                 },
936                 {
937                         {
938                                 SDB_TYPE_BINARY,
939                                 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
940                         },
941                         "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
942                 },
943                 {
944                         { SDB_TYPE_REGEX, { .re = { "some regex", empty_re } } },
945                         "\"/some regex/\"",
946                 },
947         };
949         size_t i;
951         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
952                 sdb_data_t *datum = &golden_data[i].datum;
953                 char buf[sdb_data_strlen(datum) + 2];
954                 int check;
956                 memset(buf, (int)'A', sizeof(buf));
958                 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
959                                 SDB_DOUBLE_QUOTED);
960                 fail_unless(check > 0,
961                                 "sdb_data_format(type=%s) = %d; expected: >0",
962                                 SDB_TYPE_TO_STRING(datum->type), check);
963                 fail_unless(! strcmp(buf, golden_data[i].expected),
964                                 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
965                                 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
967                 fail_unless((size_t)check <= sizeof(buf) - 2,
968                                 "sdb_data_format(type=%s) wrote %d bytes; "
969                                 "expected <= %zu based on sdb_data_strlen()",
970                                 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
972                 fail_unless(buf[sizeof(buf) - 2] == '\0',
973                                 "sdb_data_format(type=%s) did not nul-terminate the buffer",
974                                 SDB_TYPE_TO_STRING(datum->type));
975                 fail_unless(buf[sizeof(buf) - 1] == 'A',
976                                 "sdb_data_format(type=%s) wrote past the end of the buffer",
977                                 SDB_TYPE_TO_STRING(datum->type));
978         }
980 END_TEST
982 START_TEST(test_parse)
984         struct {
985                 char *input;
986                 sdb_data_t result;
987                 int expected;
988         } golden_data[] = {
989                 { "4711",    { SDB_TYPE_INTEGER,  { .integer  = 4711 } },          0 },
990                 { "0x10",    { SDB_TYPE_INTEGER,  { .integer  = 16 } },            0 },
991                 { "010",     { SDB_TYPE_INTEGER,  { .integer  = 8 } },             0 },
992                 { "abc",     { SDB_TYPE_INTEGER,  { .integer  = 0 } },            -1 },
993                 { "1.2",     { SDB_TYPE_DECIMAL,  { .decimal  = 1.2 } },           0 },
994                 { "0x1p+16", { SDB_TYPE_DECIMAL,  { .decimal  = 65536.0 } },       0 },
995                 { "abc",     { SDB_TYPE_DECIMAL,  { .decimal  = 0.0 } },          -1 },
996                 { "abc",     { SDB_TYPE_STRING,   { .string   = "abc" } },         0 },
997                 { ".4",      { SDB_TYPE_DATETIME, { .datetime = 400000000 } },     0 },
998                 { "abc",     { SDB_TYPE_DATETIME, { .datetime = 0 } },            -1 },
999                 { "abc",     { SDB_TYPE_BINARY,
1000                                          { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
1001                 { "abc",     { SDB_TYPE_REGEX,    { .re = { "abc", empty_re } } }, 0 },
1002                 { "(|",      { SDB_TYPE_REGEX,    { .re = { "", empty_re } } },   -1 },
1003         };
1005         size_t i;
1007         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1008                 sdb_data_t result;
1009                 int type, check;
1011                 memset(&result, 0, sizeof(result));
1012                 type = golden_data[i].result.type;
1013                 check = sdb_data_parse(golden_data[i].input, type, &result);
1014                 fail_unless(check == golden_data[i].expected,
1015                                 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
1016                                 golden_data[i].input, type, check, golden_data[i].expected);
1018                 if (check)
1019                         continue;
1021                 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
1022                                 "sdb_data_parse(%s, %d, <d>) did not create expected result",
1023                                 golden_data[i].input, type);
1025                 if (type == SDB_TYPE_STRING)
1026                         fail_unless(golden_data[i].input == result.data.string,
1027                                         "sdb_data_parse(%s, %d, <d>) modified input string",
1028                                         golden_data[i].input, type);
1029                 if (type == SDB_TYPE_BINARY)
1030                         fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
1031                                         "sdb_data_parse(%s, %d, <d>) modified input string",
1032                                         golden_data[i].input, type);
1033                 if (type == SDB_TYPE_REGEX) {
1034                         fail_unless(golden_data[i].input != result.data.re.raw,
1035                                         "sdb_data_parse(%s, %d, <d>) copied input string",
1036                                         golden_data[i].input, type);
1037                         sdb_data_free_datum(&result);
1038                 }
1039         }
1041 END_TEST
1043 Suite *
1044 core_data_suite(void)
1046         Suite *s = suite_create("core::data");
1047         TCase *tc;
1049         tc = tcase_create("core");
1050         tcase_add_test(tc, test_data);
1051         tcase_add_test(tc, test_cmp);
1052         tcase_add_test(tc, test_strcmp);
1053         tcase_add_test(tc, test_parse_op);
1054         tcase_add_test(tc, test_expr_eval);
1055         tcase_add_test(tc, test_format);
1056         tcase_add_test(tc, test_parse);
1057         suite_add_tcase(s, tc);
1059         return s;
1060 } /* core_data_suite */
1062 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */