Code

data: Fixed copying of NULL data.
[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 <check.h>
33 START_TEST(test_data)
34 {
35         sdb_data_t d1, d2;
36         int check;
38         d2.type = SDB_TYPE_INTEGER;
39         d2.data.integer = 4711;
40         memset(&d1, 0, sizeof(d1));
41         check = sdb_data_copy(&d1, &d2);
42         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
43         fail_unless(d1.type == d2.type,
44                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
45                         d1.type, d2.type);
46         fail_unless(d1.data.integer == d2.data.integer,
47                         "sdb_data_copy() didn't copy integer data: got: %d; expected: %d",
48                         d1.data.integer, d2.data.integer);
50         d2.type = SDB_TYPE_DECIMAL;
51         d2.data.decimal = 47.11;
52         check = sdb_data_copy(&d1, &d2);
53         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
54         fail_unless(d1.type == d2.type,
55                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
56                         d1.type, d2.type);
57         fail_unless(d1.data.decimal == d2.data.decimal,
58                         "sdb_data_copy() didn't copy decimal data: got: %f; expected: %f",
59                         d1.data.decimal, d2.data.decimal);
61         d2.type = SDB_TYPE_STRING;
62         d2.data.string = "some string";
63         check = sdb_data_copy(&d1, &d2);
64         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
65         fail_unless(d1.type == d2.type,
66                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
67                         d1.type, d2.type);
68         fail_unless(!strcmp(d1.data.string, d2.data.string),
69                         "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
70                         d1.data.string, d2.data.string);
72         sdb_data_free_datum(&d1);
73         fail_unless(d1.data.string == NULL,
74                         "sdb_data_free_datum() didn't free string data");
76         d1.type = 0;
77         d2.type = SDB_TYPE_STRING;
78         d2.data.string = NULL;
79         check = sdb_data_copy(&d1, &d2);
80         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
81         fail_unless(d1.type == d2.type,
82                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
83                         d1.type, d2.type);
84         fail_unless(d1.data.string == d2.data.string,
85                         "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
86                         d1.data.string, d2.data.string);
88         sdb_data_free_datum(&d1);
89         fail_unless(d1.data.string == NULL,
90                         "sdb_data_free_datum() didn't free string data");
92         d2.type = SDB_TYPE_DATETIME;
93         d2.data.datetime = 4711;
94         check = sdb_data_copy(&d1, &d2);
95         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
96         fail_unless(d1.type == d2.type,
97                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
98                         d1.type, d2.type);
99         fail_unless(d1.data.datetime == d2.data.datetime,
100                         "sdb_data_copy() didn't copy datetime data: got: %d; expected: %d",
101                         d1.data.datetime, d2.data.datetime);
103         d2.type = SDB_TYPE_BINARY;
104         d2.data.binary.datum = (unsigned char *)"some string";
105         d2.data.binary.length = strlen((const char *)d2.data.binary.datum);
106         check = sdb_data_copy(&d1, &d2);
107         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
108         fail_unless(d1.type == d2.type,
109                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
110                         d1.type, d2.type);
111         fail_unless(d1.data.binary.length == d2.data.binary.length,
112                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
113                         d1.data.binary.length, d2.data.binary.length);
114         fail_unless(!memcmp(d1.data.binary.datum, d2.data.binary.datum,
115                                 d2.data.binary.length),
116                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
117                         d1.data.string, d2.data.string);
119         sdb_data_free_datum(&d1);
120         fail_unless(d1.data.binary.length == 0,
121                         "sdb_data_free_datum() didn't reset binary datum length");
122         fail_unless(d1.data.binary.datum == NULL,
123                         "sdb_data_free_datum() didn't free binary datum");
125         d1.type = 0;
126         d2.type = SDB_TYPE_BINARY;
127         d2.data.binary.datum = NULL;
128         d2.data.binary.length = 0;
129         check = sdb_data_copy(&d1, &d2);
130         fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
131         fail_unless(d1.type == d2.type,
132                         "sdb_data_copy() didn't copy type; got: %i; expected: %i",
133                         d1.type, d2.type);
134         fail_unless(d1.data.binary.length == d2.data.binary.length,
135                         "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
136                         d1.data.binary.length, d2.data.binary.length);
137         fail_unless(d1.data.binary.datum == d2.data.binary.datum,
138                         "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
139                         d1.data.string, d2.data.string);
141         sdb_data_free_datum(&d1);
142         fail_unless(d1.data.binary.length == 0,
143                         "sdb_data_free_datum() didn't reset binary datum length");
144         fail_unless(d1.data.binary.datum == NULL,
145                         "sdb_data_free_datum() didn't free binary datum");
147 END_TEST
149 START_TEST(test_cmp)
151         struct {
152                 sdb_data_t d1;
153                 sdb_data_t d2;
154                 int expected;
155         } golden_data[] = {
156                 /* same data as for the sdb_data_cmp test; in case the types match,
157                  * both functions should behave the same (except for some loss in
158                  * precision, e.g. when formatting datetime values) */
159                 {
160                         { SDB_TYPE_INTEGER, { .integer = 47 } },
161                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
162                         -1,
163                 },
164                 {
165                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
166                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
167                         0,
168                 },
169                 {
170                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
171                         { SDB_TYPE_INTEGER, { .integer = 47 } },
172                         1,
173                 },
174                 {
175                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
176                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
177                         -1,
178                 },
179                 {
180                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
181                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
182                         0,
183                 },
184                 {
185                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
186                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
187                         1,
188                 },
189                 {
190                         { SDB_TYPE_STRING, { .string = NULL } },
191                         { SDB_TYPE_STRING, { .string = "" } },
192                         -1,
193                 },
194                 {
195                         { SDB_TYPE_STRING, { .string = NULL } },
196                         { SDB_TYPE_STRING, { .string = NULL } },
197                         0,
198                 },
199                 {
200                         { SDB_TYPE_STRING, { .string = "" } },
201                         { SDB_TYPE_STRING, { .string = NULL } },
202                         1,
203                 },
204                 {
205                         { SDB_TYPE_STRING, { .string = "a" } },
206                         { SDB_TYPE_STRING, { .string = "b" } },
207                         -1,
208                 },
209                 {
210                         { SDB_TYPE_STRING, { .string = "a" } },
211                         { SDB_TYPE_STRING, { .string = "ab" } },
212                         -1,
213                 },
214                 {
215                         { SDB_TYPE_STRING, { .string = "a" } },
216                         { SDB_TYPE_STRING, { .string = "a" } },
217                         0,
218                 },
219                 {
220                         { SDB_TYPE_STRING, { .string = "b" } },
221                         { SDB_TYPE_STRING, { .string = "a" } },
222                         1,
223                 },
224                 {
225                         { SDB_TYPE_STRING, { .string = "ab" } },
226                         { SDB_TYPE_STRING, { .string = "a" } },
227                         1,
228                 },
229                 {
230                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
231                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
232                         -1,
233                 },
234                 {
235                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
236                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
237                         0,
238                 },
239                 {
240                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
241                         { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
242                         1,
243                 },
244                 {
245                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
246                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
247                         -1,
248                 },
249                 {
250                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
251                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
252                         0,
253                 },
254                 {
255                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
256                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
257                         1,
258                 },
259                 {
260                         {
261                                 SDB_TYPE_BINARY,
262                                 { .binary = { 3, (unsigned char *)"a\0a" } },
263                         },
264                         {
265                                 SDB_TYPE_BINARY,
266                                 { .binary = { 3, (unsigned char *)"a\0b" } },
267                         },
268                         -1,
269                 },
270                 {
271                         {
272                                 SDB_TYPE_BINARY,
273                                 { .binary = { 1, (unsigned char *)"a" } },
274                         },
275                         {
276                                 SDB_TYPE_BINARY,
277                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
278                         },
279                         -1,
280                 },
281                 {
282                         {
283                                 SDB_TYPE_BINARY,
284                                 { .binary = { 3, (unsigned char *)"a\0a" } },
285                         },
286                         {
287                                 SDB_TYPE_BINARY,
288                                 { .binary = { 3, (unsigned char *)"a\0a" } },
289                         },
290                         0,
291                 },
292                 {
293                         {
294                                 SDB_TYPE_BINARY,
295                                 { .binary = { 3, (unsigned char *)"a\0b" } },
296                         },
297                         {
298                                 SDB_TYPE_BINARY,
299                                 { .binary = { 3, (unsigned char *)"a\0a" } },
300                         },
301                         1,
302                 },
303                 {
304                         {
305                                 SDB_TYPE_BINARY,
306                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
307                         },
308                         {
309                                 SDB_TYPE_BINARY,
310                                 { .binary = { 1, (unsigned char *)"a" } },
311                         },
312                         1,
313                 },
314                 /* type mismatches */
315                 {
316                         { SDB_TYPE_INTEGER, { .integer = 123 } },
317                         { SDB_TYPE_STRING, { .string = "123" } },
318                         0,
319                 },
320                 {
321                         { SDB_TYPE_INTEGER, { .integer = 120 } },
322                         { SDB_TYPE_STRING, { .string = "123" } },
323                         -1,
324                 },
325                 {
326                         { SDB_TYPE_STRING, { .string = "123" } },
327                         { SDB_TYPE_INTEGER, { .integer = 120 } },
328                         1,
329                 },
330                 {
331                         { SDB_TYPE_STRING, { .string = "12.3" } },
332                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
333                         0,
334                 },
335                 {
336                         { SDB_TYPE_STRING, { .string = "12.0" } },
337                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
338                         -1,
339                 },
340                 {
341                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
342                         { SDB_TYPE_STRING, { .string = "12.0" } },
343                         1,
344                 },
345         };
347         size_t i;
349         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
350                 int check = sdb_data_strcmp(&golden_data[i].d1, &golden_data[i].d2);
351                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
352                 if (check != golden_data[i].expected) {
353                         char d1_str[64] = "", d2_str[64] = "";
354                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
355                                         SDB_DOUBLE_QUOTED);
356                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
357                                         SDB_DOUBLE_QUOTED);
358                         fail("sdb_data_strcmp(%s, %s) = %d; expected: %d",
359                                         d1_str, d2_str, check, golden_data[i].expected);
360                 }
361         }
363 END_TEST
365 START_TEST(test_strcmp)
367         struct {
368                 sdb_data_t d1;
369                 sdb_data_t d2;
370                 int expected;
371         } golden_data[] = {
372                 {
373                         { SDB_TYPE_INTEGER, { .integer = 47 } },
374                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
375                         -1,
376                 },
377                 {
378                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
379                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
380                         0,
381                 },
382                 {
383                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
384                         { SDB_TYPE_INTEGER, { .integer = 47 } },
385                         1,
386                 },
387                 {
388                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
389                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
390                         -1,
391                 },
392                 {
393                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
394                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
395                         0,
396                 },
397                 {
398                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
399                         { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
400                         1,
401                 },
402                 {
403                         { SDB_TYPE_STRING, { .string = NULL } },
404                         { SDB_TYPE_STRING, { .string = "" } },
405                         -1,
406                 },
407                 {
408                         { SDB_TYPE_STRING, { .string = NULL } },
409                         { SDB_TYPE_STRING, { .string = NULL } },
410                         0,
411                 },
412                 {
413                         { SDB_TYPE_STRING, { .string = "" } },
414                         { SDB_TYPE_STRING, { .string = NULL } },
415                         1,
416                 },
417                 {
418                         { SDB_TYPE_STRING, { .string = "a" } },
419                         { SDB_TYPE_STRING, { .string = "b" } },
420                         -1,
421                 },
422                 {
423                         { SDB_TYPE_STRING, { .string = "a" } },
424                         { SDB_TYPE_STRING, { .string = "ab" } },
425                         -1,
426                 },
427                 {
428                         { SDB_TYPE_STRING, { .string = "a" } },
429                         { SDB_TYPE_STRING, { .string = "a" } },
430                         0,
431                 },
432                 {
433                         { SDB_TYPE_STRING, { .string = "b" } },
434                         { SDB_TYPE_STRING, { .string = "a" } },
435                         1,
436                 },
437                 {
438                         { SDB_TYPE_STRING, { .string = "ab" } },
439                         { SDB_TYPE_STRING, { .string = "a" } },
440                         1,
441                 },
442                 {
443                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
444                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
445                         -1,
446                 },
447                 {
448                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
449                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
450                         0,
451                 },
452                 {
453                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
454                         { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
455                         1,
456                 },
457                 {
458                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
459                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
460                         -1,
461                 },
462                 {
463                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
464                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
465                         0,
466                 },
467                 {
468                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
469                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
470                         1,
471                 },
472                 {
473                         {
474                                 SDB_TYPE_BINARY,
475                                 { .binary = { 3, (unsigned char *)"a\0a" } },
476                         },
477                         {
478                                 SDB_TYPE_BINARY,
479                                 { .binary = { 3, (unsigned char *)"a\0b" } },
480                         },
481                         -1,
482                 },
483                 {
484                         {
485                                 SDB_TYPE_BINARY,
486                                 { .binary = { 1, (unsigned char *)"a" } },
487                         },
488                         {
489                                 SDB_TYPE_BINARY,
490                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
491                         },
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\0a" } },
502                         },
503                         0,
504                 },
505                 {
506                         {
507                                 SDB_TYPE_BINARY,
508                                 { .binary = { 3, (unsigned char *)"a\0b" } },
509                         },
510                         {
511                                 SDB_TYPE_BINARY,
512                                 { .binary = { 3, (unsigned char *)"a\0a" } },
513                         },
514                         1,
515                 },
516                 {
517                         {
518                                 SDB_TYPE_BINARY,
519                                 { .binary = { 3, (unsigned char *)"a\0\0" } },
520                         },
521                         {
522                                 SDB_TYPE_BINARY,
523                                 { .binary = { 1, (unsigned char *)"a" } },
524                         },
525                         1,
526                 },
527         };
529         size_t i;
531         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
532                 int check = sdb_data_cmp(&golden_data[i].d1, &golden_data[i].d2);
533                 check = check < 0 ? -1 : check > 0 ? 1 : 0;
534                 if (check != golden_data[i].expected) {
535                         char d1_str[64] = "", d2_str[64] = "";
536                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
537                                         SDB_DOUBLE_QUOTED);
538                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
539                                         SDB_DOUBLE_QUOTED);
540                         fail("sdb_data_cmp(%s, %s) = %d; expected: %d",
541                                         d1_str, d2_str, check, golden_data[i].expected);
542                 }
543         }
545 END_TEST
547 START_TEST(test_expr_eval)
549         struct {
550                 sdb_data_t d1;
551                 sdb_data_t d2;
552                 sdb_data_t expected_add;
553                 sdb_data_t expected_sub;
554                 sdb_data_t expected_mul;
555                 sdb_data_t expected_div;
556                 sdb_data_t expected_mod;
557                 sdb_data_t expected_concat;
558         } golden_data[] = {
559                 {
560                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
561                         { SDB_TYPE_INTEGER, { .integer = 47 } },
562                         { SDB_TYPE_INTEGER, { .integer = 4758 } },
563                         { SDB_TYPE_INTEGER, { .integer = 4664 } },
564                         { SDB_TYPE_INTEGER, { .integer = 221417 } },
565                         { SDB_TYPE_INTEGER, { .integer = 100 } },
566                         { SDB_TYPE_INTEGER, { .integer = 11 } },
567                         SDB_DATA_INIT,
568                 },
569                 {
570                         { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
571                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
572                         { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
573                         { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
574                         { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
575                         { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
576                         { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
577                         SDB_DATA_INIT,
578                 },
579                 {
580                         { SDB_TYPE_STRING, { .string = NULL } },
581                         { SDB_TYPE_STRING, { .string = "" } },
582                         SDB_DATA_INIT,
583                         SDB_DATA_INIT,
584                         SDB_DATA_INIT,
585                         SDB_DATA_INIT,
586                         SDB_DATA_INIT,
587                         { SDB_TYPE_STRING, { .string = "" } },
588                 },
589                 {
590                         { SDB_TYPE_STRING, { .string = NULL } },
591                         { SDB_TYPE_STRING, { .string = NULL } },
592                         SDB_DATA_INIT,
593                         SDB_DATA_INIT,
594                         SDB_DATA_INIT,
595                         SDB_DATA_INIT,
596                         SDB_DATA_INIT,
597                         { SDB_TYPE_STRING, { .string = NULL } },
598                 },
599                 {
600                         { SDB_TYPE_STRING, { .string = "" } },
601                         { SDB_TYPE_STRING, { .string = NULL } },
602                         SDB_DATA_INIT,
603                         SDB_DATA_INIT,
604                         SDB_DATA_INIT,
605                         SDB_DATA_INIT,
606                         SDB_DATA_INIT,
607                         { SDB_TYPE_STRING, { .string = "" } },
608                 },
609                 {
610                         { SDB_TYPE_STRING, { .string = "a" } },
611                         { SDB_TYPE_STRING, { .string = "b" } },
612                         SDB_DATA_INIT,
613                         SDB_DATA_INIT,
614                         SDB_DATA_INIT,
615                         SDB_DATA_INIT,
616                         SDB_DATA_INIT,
617                         { SDB_TYPE_STRING, { .string = "ab" } },
618                 },
619                 {
620                         { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
621                         { SDB_TYPE_DATETIME, { .datetime = 4711 } },
622                         { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
623                         { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
624                         { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
625                         { SDB_TYPE_DATETIME, { .datetime = 10001 } },
626                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
627                         SDB_DATA_INIT,
628                 },
629                 {
630                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
631                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
632                         SDB_DATA_INIT,
633                         SDB_DATA_INIT,
634                         SDB_DATA_INIT,
635                         SDB_DATA_INIT,
636                         SDB_DATA_INIT,
637                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
638                 },
639                 {
640                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
641                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
642                         SDB_DATA_INIT,
643                         SDB_DATA_INIT,
644                         SDB_DATA_INIT,
645                         SDB_DATA_INIT,
646                         SDB_DATA_INIT,
647                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
648                 },
649                 {
650                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
651                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
652                         SDB_DATA_INIT,
653                         SDB_DATA_INIT,
654                         SDB_DATA_INIT,
655                         SDB_DATA_INIT,
656                         SDB_DATA_INIT,
657                         { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
658                 },
659                 {
660                         {
661                                 SDB_TYPE_BINARY,
662                                 { .binary = { 3, (unsigned char *)"a\0a" } },
663                         },
664                         {
665                                 SDB_TYPE_BINARY,
666                                 { .binary = { 3, (unsigned char *)"b\0b" } },
667                         },
668                         SDB_DATA_INIT,
669                         SDB_DATA_INIT,
670                         SDB_DATA_INIT,
671                         SDB_DATA_INIT,
672                         SDB_DATA_INIT,
673                         {
674                                 SDB_TYPE_BINARY,
675                                 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
676                         },
677                 },
678                 /* supported type-mismatches */
679                 {
680                         /* int * datetime */
681                         { SDB_TYPE_INTEGER,  { .integer  = 20 } },
682                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
683                         SDB_DATA_INIT,
684                         SDB_DATA_INIT,
685                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
686                         SDB_DATA_INIT,
687                         SDB_DATA_INIT,
688                         SDB_DATA_INIT,
689                 },
690                 {
691                         /* datetime * int, datetime / int, datetime % int */
692                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
693                         { SDB_TYPE_INTEGER,  { .integer  = 2 } },
694                         SDB_DATA_INIT,
695                         SDB_DATA_INIT,
696                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
697                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
698                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
699                         SDB_DATA_INIT,
700                 },
701                 {
702                         /* float * datetime */
703                         { SDB_TYPE_DECIMAL,  { .decimal  = 20.0 } },
704                         { SDB_TYPE_DATETIME, { .datetime = 2 } },
705                         SDB_DATA_INIT,
706                         SDB_DATA_INIT,
707                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
708                         SDB_DATA_INIT,
709                         SDB_DATA_INIT,
710                         SDB_DATA_INIT,
711                 },
712                 {
713                         /* datetime * float, datetime / float, datetime % float */
714                         { SDB_TYPE_DATETIME, { .datetime = 20 } },
715                         { SDB_TYPE_DECIMAL,  { .decimal  = 2.0 } },
716                         SDB_DATA_INIT,
717                         SDB_DATA_INIT,
718                         { SDB_TYPE_DATETIME, { .datetime = 40 } },
719                         { SDB_TYPE_DATETIME, { .datetime = 10 } },
720                         { SDB_TYPE_DATETIME, { .datetime = 0 } },
721                         SDB_DATA_INIT,
722                 },
723         };
725         size_t i;
727         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
728                 struct {
729                         int op;
730                         sdb_data_t expected;
731                 } tests[] = {
732                         { SDB_DATA_ADD, golden_data[i].expected_add },
733                         { SDB_DATA_SUB, golden_data[i].expected_sub },
734                         { SDB_DATA_MUL, golden_data[i].expected_mul },
735                         { SDB_DATA_DIV, golden_data[i].expected_div },
736                         { SDB_DATA_MOD, golden_data[i].expected_mod },
737                         { SDB_DATA_CONCAT, golden_data[i].expected_concat },
738                 };
740                 size_t j;
741                 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
742                         sdb_data_t res;
743                         int check;
745                         char d1_str[64] = "", d2_str[64] = "";
746                         sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
747                                         SDB_DOUBLE_QUOTED);
748                         sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
749                                         SDB_DOUBLE_QUOTED);
751                         check = sdb_data_expr_eval(tests[j].op,
752                                         &golden_data[i].d1, &golden_data[i].d2, &res);
753                         fail_unless((check == 0) == (tests[j].expected.type != 0),
754                                         "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
755                                         SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
756                                         tests[j].expected.type == 0 ? -1 : 0);
757                         if (tests[j].expected.type == 0)
758                                 continue;
760                         check = sdb_data_cmp(&res, &tests[j].expected);
761                         if (check != 0) {
762                                 char res_str[64] = "", expected_str[64] = "";
763                                 sdb_data_format(&res, res_str, sizeof(res_str),
764                                                 SDB_DOUBLE_QUOTED);
765                                 sdb_data_format(&tests[j].expected, expected_str,
766                                                 sizeof(expected_str), SDB_DOUBLE_QUOTED);
767                                 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s; "
768                                                 "expected: %s", SDB_DATA_OP_TO_STRING(tests[j].op),
769                                                 d1_str, d2_str, res_str, expected_str);
770                         }
772                         sdb_data_free_datum(&res);
773                 }
774         }
776 END_TEST
778 START_TEST(test_format)
780         struct {
781                 sdb_data_t datum;
782                 const char *expected;
783         } golden_data[] = {
784                 {
785                         { SDB_TYPE_INTEGER, { .integer = 4711 } },
786                         "4711",
787                 },
788                 {
789                         { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
790                         "65536",
791                 },
792                 {
793                         { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
794                         "12.3",
795                 },
796                 {
797                         { SDB_TYPE_STRING, { .string = NULL } },
798                         "\"<NULL>\"",
799                 },
800                 {
801                         { SDB_TYPE_STRING, { .string = "this is a test" } },
802                         "\"this is a test\"",
803                 },
804                 {
805                         { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
806                         "\"special \\\\ \\\" characters\"",
807                 },
808                 {
809                         { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
810                         "\"1984-12-06 02:11:54 +0000\"",
811                 },
812                 {
813                         { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
814                         "\"<NULL>\"",
815                 },
816                 {
817                         {
818                                 SDB_TYPE_BINARY,
819                                 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
820                         },
821                         "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
822                 },
823         };
825         size_t i;
827         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
828                 sdb_data_t *datum = &golden_data[i].datum;
829                 char buf[sdb_data_strlen(datum) + 2];
830                 int check;
832                 memset(buf, (int)'A', sizeof(buf));
834                 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
835                                 SDB_DOUBLE_QUOTED);
836                 fail_unless(check > 0,
837                                 "sdb_data_format(type=%s) = %d; expected: >0",
838                                 SDB_TYPE_TO_STRING(datum->type), check);
839                 fail_unless(! strcmp(buf, golden_data[i].expected),
840                                 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
841                                 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
843                 fail_unless((size_t)check <= sizeof(buf) - 2,
844                                 "sdb_data_format(type=%s) wrote %d bytes; "
845                                 "expected <= %zu based on sdb_data_strlen()",
846                                 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
848                 fail_unless(buf[sizeof(buf) - 2] == '\0',
849                                 "sdb_data_format(type=%s) did not nul-terminate the buffer",
850                                 SDB_TYPE_TO_STRING(datum->type));
851                 fail_unless(buf[sizeof(buf) - 1] == 'A',
852                                 "sdb_data_format(type=%s) wrote past the end of the buffer",
853                                 SDB_TYPE_TO_STRING(datum->type));
854         }
856 END_TEST
858 START_TEST(test_parse)
860         struct {
861                 char *input;
862                 sdb_data_t result;
863                 int expected;
864         } golden_data[] = {
865                 { "4711",    { SDB_TYPE_INTEGER,  { .integer  = 4711 } },       0 },
866                 { "0x10",    { SDB_TYPE_INTEGER,  { .integer  = 16 } },         0 },
867                 { "010",     { SDB_TYPE_INTEGER,  { .integer  = 8 } },          0 },
868                 { "abc",     { SDB_TYPE_INTEGER,  { .integer  = 0 } },         -1 },
869                 { "1.2",     { SDB_TYPE_DECIMAL,  { .decimal  = 1.2 } },        0 },
870                 { "0x1p+16", { SDB_TYPE_DECIMAL,  { .decimal  = 65536.0 } },    0 },
871                 { "abc",     { SDB_TYPE_DECIMAL,  { .decimal  = 0.0 } },       -1 },
872                 { "abc",     { SDB_TYPE_STRING,   { .string   = "abc" } },      0 },
873                 { ".4",      { SDB_TYPE_DATETIME, { .datetime = 400000000 } },  0 },
874                 { "abc",     { SDB_TYPE_DATETIME, { .datetime = 0 } },         -1 },
875                 { "abc",     { SDB_TYPE_BINARY,
876                                          { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
877         };
879         size_t i;
881         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
882                 sdb_data_t result;
883                 int type, check;
885                 memset(&result, 0, sizeof(result));
886                 type = golden_data[i].result.type;
887                 check = sdb_data_parse(golden_data[i].input, type, &result);
888                 fail_unless(check == golden_data[i].expected,
889                                 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
890                                 golden_data[i].input, type, check, golden_data[i].expected);
892                 if (check)
893                         continue;
895                 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
896                                 "sdb_data_parse(%s, %d, <d>) did not create expected result",
897                                 golden_data[i].input, type);
899                 if (type == SDB_TYPE_STRING)
900                         fail_unless(golden_data[i].input == result.data.string,
901                                         "sdb_data_parse(%s, %d, <d>) modified input string",
902                                         golden_data[i].input, type);
903                 if (type == SDB_TYPE_BINARY)
904                         fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
905                                         "sdb_data_parse(%s, %d, <d>) modified input string",
906                                         golden_data[i].input, type);
907         }
909 END_TEST
911 Suite *
912 core_data_suite(void)
914         Suite *s = suite_create("core::data");
915         TCase *tc;
917         tc = tcase_create("core");
918         tcase_add_test(tc, test_data);
919         tcase_add_test(tc, test_cmp);
920         tcase_add_test(tc, test_strcmp);
921         tcase_add_test(tc, test_expr_eval);
922         tcase_add_test(tc, test_format);
923         tcase_add_test(tc, test_parse);
924         suite_add_tcase(s, tc);
926         return s;
927 } /* core_data_suite */
929 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */