702afa487a0fa9aa7fbc31090f7d133f770ffe20
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 }
178 END_TEST
180 START_TEST(test_cmp)
181 {
182 struct {
183 sdb_data_t d1;
184 sdb_data_t d2;
185 int expected;
186 } golden_data[] = {
187 {
188 { SDB_TYPE_INTEGER, { .integer = 47 } },
189 { SDB_TYPE_INTEGER, { .integer = 4711 } },
190 -1,
191 },
192 {
193 { SDB_TYPE_INTEGER, { .integer = 4711 } },
194 { SDB_TYPE_INTEGER, { .integer = 4711 } },
195 0,
196 },
197 {
198 { SDB_TYPE_INTEGER, { .integer = 4711 } },
199 { SDB_TYPE_INTEGER, { .integer = 47 } },
200 1,
201 },
202 {
203 { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
204 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
205 -1,
206 },
207 {
208 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
209 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
210 0,
211 },
212 {
213 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
214 { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
215 1,
216 },
217 {
218 { SDB_TYPE_STRING, { .string = NULL } },
219 { SDB_TYPE_STRING, { .string = "" } },
220 -1,
221 },
222 {
223 { SDB_TYPE_STRING, { .string = NULL } },
224 { SDB_TYPE_STRING, { .string = NULL } },
225 0,
226 },
227 {
228 { SDB_TYPE_STRING, { .string = "" } },
229 { SDB_TYPE_STRING, { .string = NULL } },
230 1,
231 },
232 {
233 { SDB_TYPE_STRING, { .string = "a" } },
234 { SDB_TYPE_STRING, { .string = "b" } },
235 -1,
236 },
237 {
238 { SDB_TYPE_STRING, { .string = "a" } },
239 { SDB_TYPE_STRING, { .string = "ab" } },
240 -1,
241 },
242 {
243 { SDB_TYPE_STRING, { .string = "a" } },
244 { SDB_TYPE_STRING, { .string = "a" } },
245 0,
246 },
247 {
248 { SDB_TYPE_STRING, { .string = "b" } },
249 { SDB_TYPE_STRING, { .string = "a" } },
250 1,
251 },
252 {
253 { SDB_TYPE_STRING, { .string = "ab" } },
254 { SDB_TYPE_STRING, { .string = "a" } },
255 1,
256 },
257 {
258 { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
259 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
260 -1,
261 },
262 {
263 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
264 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
265 0,
266 },
267 {
268 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
269 { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
270 1,
271 },
272 {
273 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
274 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
275 -1,
276 },
277 {
278 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
279 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
280 0,
281 },
282 {
283 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
284 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
285 1,
286 },
287 {
288 {
289 SDB_TYPE_BINARY,
290 { .binary = { 3, (unsigned char *)"a\0a" } },
291 },
292 {
293 SDB_TYPE_BINARY,
294 { .binary = { 3, (unsigned char *)"a\0b" } },
295 },
296 -1,
297 },
298 {
299 {
300 SDB_TYPE_BINARY,
301 { .binary = { 1, (unsigned char *)"a" } },
302 },
303 {
304 SDB_TYPE_BINARY,
305 { .binary = { 3, (unsigned char *)"a\0\0" } },
306 },
307 -1,
308 },
309 {
310 {
311 SDB_TYPE_BINARY,
312 { .binary = { 3, (unsigned char *)"a\0a" } },
313 },
314 {
315 SDB_TYPE_BINARY,
316 { .binary = { 3, (unsigned char *)"a\0a" } },
317 },
318 0,
319 },
320 {
321 {
322 SDB_TYPE_BINARY,
323 { .binary = { 3, (unsigned char *)"a\0b" } },
324 },
325 {
326 SDB_TYPE_BINARY,
327 { .binary = { 3, (unsigned char *)"a\0a" } },
328 },
329 1,
330 },
331 {
332 {
333 SDB_TYPE_BINARY,
334 { .binary = { 3, (unsigned char *)"a\0\0" } },
335 },
336 {
337 SDB_TYPE_BINARY,
338 { .binary = { 1, (unsigned char *)"a" } },
339 },
340 1,
341 },
342 {
343 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
344 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
345 0,
346 },
347 {
348 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
349 { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
350 -1,
351 },
352 {
353 { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
354 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
355 1,
356 },
357 };
359 size_t i;
361 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
362 int check = sdb_data_cmp(&golden_data[i].d1, &golden_data[i].d2);
363 check = check < 0 ? -1 : check > 0 ? 1 : 0;
364 if (check != golden_data[i].expected) {
365 char d1_str[64] = "", d2_str[64] = "";
366 sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
367 SDB_DOUBLE_QUOTED);
368 sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
369 SDB_DOUBLE_QUOTED);
370 fail("sdb_data_cmp(%s, %s) = %d; expected: %d",
371 d1_str, d2_str, check, golden_data[i].expected);
372 }
373 }
374 }
375 END_TEST
377 START_TEST(test_strcmp)
378 {
379 struct {
380 sdb_data_t d1;
381 sdb_data_t d2;
382 int expected;
383 } golden_data[] = {
384 /* same data as for the sdb_data_cmp test; in case the types match,
385 * both functions should behave the same (except for some loss in
386 * precision, e.g. when formatting datetime values) */
387 {
388 { SDB_TYPE_INTEGER, { .integer = 47 } },
389 { SDB_TYPE_INTEGER, { .integer = 4711 } },
390 -1,
391 },
392 {
393 { SDB_TYPE_INTEGER, { .integer = 4711 } },
394 { SDB_TYPE_INTEGER, { .integer = 4711 } },
395 0,
396 },
397 {
398 { SDB_TYPE_INTEGER, { .integer = 4711 } },
399 { SDB_TYPE_INTEGER, { .integer = 47 } },
400 1,
401 },
402 {
403 { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
404 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
405 -1,
406 },
407 {
408 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
409 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
410 0,
411 },
412 {
413 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
414 { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
415 1,
416 },
417 {
418 { SDB_TYPE_STRING, { .string = NULL } },
419 { SDB_TYPE_STRING, { .string = "" } },
420 -1,
421 },
422 {
423 { SDB_TYPE_STRING, { .string = NULL } },
424 { SDB_TYPE_STRING, { .string = NULL } },
425 0,
426 },
427 {
428 { SDB_TYPE_STRING, { .string = "" } },
429 { SDB_TYPE_STRING, { .string = NULL } },
430 1,
431 },
432 {
433 { SDB_TYPE_STRING, { .string = "a" } },
434 { SDB_TYPE_STRING, { .string = "b" } },
435 -1,
436 },
437 {
438 { SDB_TYPE_STRING, { .string = "a" } },
439 { SDB_TYPE_STRING, { .string = "ab" } },
440 -1,
441 },
442 {
443 { SDB_TYPE_STRING, { .string = "a" } },
444 { SDB_TYPE_STRING, { .string = "a" } },
445 0,
446 },
447 {
448 { SDB_TYPE_STRING, { .string = "b" } },
449 { SDB_TYPE_STRING, { .string = "a" } },
450 1,
451 },
452 {
453 { SDB_TYPE_STRING, { .string = "ab" } },
454 { SDB_TYPE_STRING, { .string = "a" } },
455 1,
456 },
457 {
458 { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
459 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
460 -1,
461 },
462 {
463 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
464 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
465 0,
466 },
467 {
468 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
469 { SDB_TYPE_DATETIME, { .datetime = 471047114711471100 } },
470 1,
471 },
472 {
473 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
474 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
475 -1,
476 },
477 {
478 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
479 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
480 0,
481 },
482 {
483 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
484 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
485 1,
486 },
487 {
488 {
489 SDB_TYPE_BINARY,
490 { .binary = { 3, (unsigned char *)"a\0a" } },
491 },
492 {
493 SDB_TYPE_BINARY,
494 { .binary = { 3, (unsigned char *)"a\0b" } },
495 },
496 -1,
497 },
498 {
499 {
500 SDB_TYPE_BINARY,
501 { .binary = { 1, (unsigned char *)"a" } },
502 },
503 {
504 SDB_TYPE_BINARY,
505 { .binary = { 3, (unsigned char *)"a\0\0" } },
506 },
507 -1,
508 },
509 {
510 {
511 SDB_TYPE_BINARY,
512 { .binary = { 3, (unsigned char *)"a\0a" } },
513 },
514 {
515 SDB_TYPE_BINARY,
516 { .binary = { 3, (unsigned char *)"a\0a" } },
517 },
518 0,
519 },
520 {
521 {
522 SDB_TYPE_BINARY,
523 { .binary = { 3, (unsigned char *)"a\0b" } },
524 },
525 {
526 SDB_TYPE_BINARY,
527 { .binary = { 3, (unsigned char *)"a\0a" } },
528 },
529 1,
530 },
531 {
532 {
533 SDB_TYPE_BINARY,
534 { .binary = { 3, (unsigned char *)"a\0\0" } },
535 },
536 {
537 SDB_TYPE_BINARY,
538 { .binary = { 1, (unsigned char *)"a" } },
539 },
540 1,
541 },
542 {
543 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
544 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
545 0,
546 },
547 {
548 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
549 { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
550 -1,
551 },
552 {
553 { SDB_TYPE_REGEX, { .re = { "b", empty_re } } },
554 { SDB_TYPE_REGEX, { .re = { "a", empty_re } } },
555 1,
556 },
557 /* type mismatches */
558 {
559 { SDB_TYPE_INTEGER, { .integer = 123 } },
560 { SDB_TYPE_STRING, { .string = "123" } },
561 0,
562 },
563 {
564 { SDB_TYPE_INTEGER, { .integer = 120 } },
565 { SDB_TYPE_STRING, { .string = "123" } },
566 -1,
567 },
568 {
569 { SDB_TYPE_STRING, { .string = "123" } },
570 { SDB_TYPE_INTEGER, { .integer = 120 } },
571 1,
572 },
573 {
574 { SDB_TYPE_STRING, { .string = "12.3" } },
575 { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
576 0,
577 },
578 {
579 { SDB_TYPE_STRING, { .string = "12.0" } },
580 { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
581 -1,
582 },
583 {
584 { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
585 { SDB_TYPE_STRING, { .string = "12.0" } },
586 1,
587 },
588 {
589 { SDB_TYPE_REGEX, { .re = { "regex", empty_re } } },
590 { SDB_TYPE_STRING, { .string = "/regex/" } },
591 0,
592 },
593 };
595 size_t i;
597 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
598 int check = sdb_data_strcmp(&golden_data[i].d1, &golden_data[i].d2);
599 check = check < 0 ? -1 : check > 0 ? 1 : 0;
600 if (check != golden_data[i].expected) {
601 char d1_str[64] = "", d2_str[64] = "";
602 sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
603 SDB_DOUBLE_QUOTED);
604 sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
605 SDB_DOUBLE_QUOTED);
606 fail("sdb_data_strcmp(%s, %s) = %d; expected: %d",
607 d1_str, d2_str, check, golden_data[i].expected);
608 }
609 }
610 }
611 END_TEST
613 START_TEST(test_parse_op)
614 {
615 struct {
616 const char *op;
617 int id;
618 } golden_data[] = {
619 { "+", SDB_DATA_ADD },
620 { "-", SDB_DATA_SUB },
621 { "*", SDB_DATA_MUL },
622 { "/", SDB_DATA_DIV },
623 { "%", SDB_DATA_MOD },
624 { "||", SDB_DATA_CONCAT },
625 { "&&", -1 },
626 };
628 size_t i;
630 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
631 const char *op;
632 int id;
634 id = sdb_data_parse_op(golden_data[i].op);
635 fail_unless(id == golden_data[i].id,
636 "sdb_data_parse_op(%s) = %d; expected: %d",
637 golden_data[i].op, id, golden_data[i].id);
639 if (id <= 0)
640 continue;
642 op = SDB_DATA_OP_TO_STRING(id);
643 fail_unless(!strcmp(op, golden_data[i].op),
644 "SDB_DATA_OP_TO_STRING(%d) = '%s'; expected: '%s'",
645 id, op, golden_data[i].op);
646 }
647 }
648 END_TEST
650 START_TEST(test_expr_eval)
651 {
652 sdb_data_t err = { -1, { .integer = 0 } };
654 struct {
655 sdb_data_t d1;
656 sdb_data_t d2;
657 sdb_data_t expected_add;
658 sdb_data_t expected_sub;
659 sdb_data_t expected_mul;
660 sdb_data_t expected_div;
661 sdb_data_t expected_mod;
662 sdb_data_t expected_concat;
663 } golden_data[] = {
664 {
665 { SDB_TYPE_INTEGER, { .integer = 4711 } },
666 { SDB_TYPE_INTEGER, { .integer = 47 } },
667 { SDB_TYPE_INTEGER, { .integer = 4758 } },
668 { SDB_TYPE_INTEGER, { .integer = 4664 } },
669 { SDB_TYPE_INTEGER, { .integer = 221417 } },
670 { SDB_TYPE_INTEGER, { .integer = 100 } },
671 { SDB_TYPE_INTEGER, { .integer = 11 } },
672 err,
673 },
674 {
675 { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
676 { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
677 { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
678 { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
679 { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
680 { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
681 { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
682 err,
683 },
684 {
685 { SDB_TYPE_STRING, { .string = NULL } },
686 { SDB_TYPE_STRING, { .string = "" } },
687 SDB_DATA_NULL,
688 SDB_DATA_NULL,
689 SDB_DATA_NULL,
690 SDB_DATA_NULL,
691 SDB_DATA_NULL,
692 SDB_DATA_NULL,
693 },
694 {
695 { SDB_TYPE_STRING, { .string = NULL } },
696 { SDB_TYPE_STRING, { .string = NULL } },
697 SDB_DATA_NULL,
698 SDB_DATA_NULL,
699 SDB_DATA_NULL,
700 SDB_DATA_NULL,
701 SDB_DATA_NULL,
702 SDB_DATA_NULL,
703 },
704 {
705 { SDB_TYPE_STRING, { .string = "" } },
706 { SDB_TYPE_STRING, { .string = NULL } },
707 SDB_DATA_NULL,
708 SDB_DATA_NULL,
709 SDB_DATA_NULL,
710 SDB_DATA_NULL,
711 SDB_DATA_NULL,
712 SDB_DATA_NULL,
713 },
714 {
715 { SDB_TYPE_STRING, { .string = "a" } },
716 { SDB_TYPE_STRING, { .string = "b" } },
717 err,
718 err,
719 err,
720 err,
721 err,
722 { SDB_TYPE_STRING, { .string = "ab" } },
723 },
724 {
725 { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
726 { SDB_TYPE_DATETIME, { .datetime = 4711 } },
727 { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
728 { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
729 { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
730 { SDB_TYPE_DATETIME, { .datetime = 10001 } },
731 { SDB_TYPE_DATETIME, { .datetime = 0 } },
732 err,
733 },
734 {
735 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
736 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
737 SDB_DATA_NULL,
738 SDB_DATA_NULL,
739 SDB_DATA_NULL,
740 SDB_DATA_NULL,
741 SDB_DATA_NULL,
742 SDB_DATA_NULL,
743 },
744 {
745 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
746 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
747 SDB_DATA_NULL,
748 SDB_DATA_NULL,
749 SDB_DATA_NULL,
750 SDB_DATA_NULL,
751 SDB_DATA_NULL,
752 SDB_DATA_NULL,
753 },
754 {
755 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
756 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
757 SDB_DATA_NULL,
758 SDB_DATA_NULL,
759 SDB_DATA_NULL,
760 SDB_DATA_NULL,
761 SDB_DATA_NULL,
762 SDB_DATA_NULL,
763 },
764 {
765 {
766 SDB_TYPE_BINARY,
767 { .binary = { 3, (unsigned char *)"a\0a" } },
768 },
769 {
770 SDB_TYPE_BINARY,
771 { .binary = { 3, (unsigned char *)"b\0b" } },
772 },
773 err,
774 err,
775 err,
776 err,
777 err,
778 {
779 SDB_TYPE_BINARY,
780 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
781 },
782 },
783 {
784 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
785 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
786 err,
787 err,
788 err,
789 err,
790 err,
791 err,
792 },
793 {
794 { SDB_TYPE_NULL, { .integer = 0 } },
795 { SDB_TYPE_NULL, { .integer = 0 } },
796 SDB_DATA_NULL,
797 SDB_DATA_NULL,
798 SDB_DATA_NULL,
799 SDB_DATA_NULL,
800 SDB_DATA_NULL,
801 SDB_DATA_NULL,
802 },
803 {
804 { SDB_TYPE_NULL, { .integer = 0 } },
805 { SDB_TYPE_INTEGER, { .integer = 42 } },
806 SDB_DATA_NULL,
807 SDB_DATA_NULL,
808 SDB_DATA_NULL,
809 SDB_DATA_NULL,
810 SDB_DATA_NULL,
811 SDB_DATA_NULL,
812 },
813 {
814 { SDB_TYPE_INTEGER, { .integer = 42 } },
815 { SDB_TYPE_NULL, { .integer = 0 } },
816 SDB_DATA_NULL,
817 SDB_DATA_NULL,
818 SDB_DATA_NULL,
819 SDB_DATA_NULL,
820 SDB_DATA_NULL,
821 SDB_DATA_NULL,
822 },
823 {
824 { SDB_TYPE_NULL, { .integer = 0 } },
825 { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
826 SDB_DATA_NULL,
827 SDB_DATA_NULL,
828 SDB_DATA_NULL,
829 SDB_DATA_NULL,
830 SDB_DATA_NULL,
831 SDB_DATA_NULL,
832 },
833 {
834 { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
835 { SDB_TYPE_NULL, { .integer = 0 } },
836 SDB_DATA_NULL,
837 SDB_DATA_NULL,
838 SDB_DATA_NULL,
839 SDB_DATA_NULL,
840 SDB_DATA_NULL,
841 SDB_DATA_NULL,
842 },
843 {
844 { SDB_TYPE_NULL, { .integer = 0 } },
845 { SDB_TYPE_STRING, { .string = "47.11" } },
846 SDB_DATA_NULL,
847 SDB_DATA_NULL,
848 SDB_DATA_NULL,
849 SDB_DATA_NULL,
850 SDB_DATA_NULL,
851 SDB_DATA_NULL,
852 },
853 {
854 { SDB_TYPE_STRING, { .string = "47.11" } },
855 { SDB_TYPE_NULL, { .integer = 0 } },
856 SDB_DATA_NULL,
857 SDB_DATA_NULL,
858 SDB_DATA_NULL,
859 SDB_DATA_NULL,
860 SDB_DATA_NULL,
861 SDB_DATA_NULL,
862 },
863 {
864 { SDB_TYPE_NULL, { .integer = 0 } },
865 { SDB_TYPE_DATETIME, { .datetime = 4711 } },
866 SDB_DATA_NULL,
867 SDB_DATA_NULL,
868 SDB_DATA_NULL,
869 SDB_DATA_NULL,
870 SDB_DATA_NULL,
871 SDB_DATA_NULL,
872 },
873 {
874 { SDB_TYPE_DATETIME, { .datetime = 4711 } },
875 { SDB_TYPE_NULL, { .integer = 0 } },
876 SDB_DATA_NULL,
877 SDB_DATA_NULL,
878 SDB_DATA_NULL,
879 SDB_DATA_NULL,
880 SDB_DATA_NULL,
881 SDB_DATA_NULL,
882 },
883 {
884 { SDB_TYPE_NULL, { .integer = 0 } },
885 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
886 SDB_DATA_NULL,
887 SDB_DATA_NULL,
888 SDB_DATA_NULL,
889 SDB_DATA_NULL,
890 SDB_DATA_NULL,
891 SDB_DATA_NULL,
892 },
893 {
894 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
895 { SDB_TYPE_NULL, { .integer = 0 } },
896 SDB_DATA_NULL,
897 SDB_DATA_NULL,
898 SDB_DATA_NULL,
899 SDB_DATA_NULL,
900 SDB_DATA_NULL,
901 SDB_DATA_NULL,
902 },
903 {
904 { SDB_TYPE_NULL, { .integer = 0 } },
905 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
906 SDB_DATA_NULL,
907 SDB_DATA_NULL,
908 SDB_DATA_NULL,
909 SDB_DATA_NULL,
910 SDB_DATA_NULL,
911 SDB_DATA_NULL,
912 },
913 {
914 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
915 { SDB_TYPE_NULL, { .integer = 0 } },
916 SDB_DATA_NULL,
917 SDB_DATA_NULL,
918 SDB_DATA_NULL,
919 SDB_DATA_NULL,
920 SDB_DATA_NULL,
921 SDB_DATA_NULL,
922 },
923 /* supported type-mismatches */
924 {
925 /* int * datetime */
926 { SDB_TYPE_INTEGER, { .integer = 20 } },
927 { SDB_TYPE_DATETIME, { .datetime = 2 } },
928 err,
929 err,
930 { SDB_TYPE_DATETIME, { .datetime = 40 } },
931 err,
932 err,
933 err,
934 },
935 {
936 /* datetime * int, datetime / int, datetime % int */
937 { SDB_TYPE_DATETIME, { .datetime = 20 } },
938 { SDB_TYPE_INTEGER, { .integer = 2 } },
939 err,
940 err,
941 { SDB_TYPE_DATETIME, { .datetime = 40 } },
942 { SDB_TYPE_DATETIME, { .datetime = 10 } },
943 { SDB_TYPE_DATETIME, { .datetime = 0 } },
944 err,
945 },
946 {
947 /* float * datetime */
948 { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
949 { SDB_TYPE_DATETIME, { .datetime = 2 } },
950 err,
951 err,
952 { SDB_TYPE_DATETIME, { .datetime = 40 } },
953 err,
954 err,
955 err,
956 },
957 {
958 /* datetime * float, datetime / float, datetime % float */
959 { SDB_TYPE_DATETIME, { .datetime = 20 } },
960 { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
961 err,
962 err,
963 { SDB_TYPE_DATETIME, { .datetime = 40 } },
964 { SDB_TYPE_DATETIME, { .datetime = 10 } },
965 { SDB_TYPE_DATETIME, { .datetime = 0 } },
966 err,
967 },
968 };
970 size_t i;
972 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
973 struct {
974 int op;
975 sdb_data_t expected;
976 } tests[] = {
977 { SDB_DATA_ADD, golden_data[i].expected_add },
978 { SDB_DATA_SUB, golden_data[i].expected_sub },
979 { SDB_DATA_MUL, golden_data[i].expected_mul },
980 { SDB_DATA_DIV, golden_data[i].expected_div },
981 { SDB_DATA_MOD, golden_data[i].expected_mod },
982 { SDB_DATA_CONCAT, golden_data[i].expected_concat },
983 };
985 size_t j;
986 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
987 sdb_data_t res;
988 int check;
990 char d1_str[64] = "", d2_str[64] = "";
991 sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
992 SDB_DOUBLE_QUOTED);
993 sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
994 SDB_DOUBLE_QUOTED);
996 check = sdb_data_expr_eval(tests[j].op,
997 &golden_data[i].d1, &golden_data[i].d2, &res);
998 fail_unless((check == 0) == (tests[j].expected.type != -1),
999 "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
1000 SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
1001 tests[j].expected.type == -1 ? -1 : 0);
1002 if (tests[j].expected.type == -1)
1003 continue;
1005 if (tests[j].expected.type == SDB_TYPE_NULL) {
1006 fail_unless(res.type == SDB_TYPE_NULL,
1007 "sdb_data_expr_eval(%s, %s, %s) evaluated to "
1008 "type %d; expected: SDB_TYPE_NULL",
1009 SDB_DATA_OP_TO_STRING(tests[j].op),
1010 d1_str, d2_str, res.type);
1011 continue;
1012 }
1014 check = sdb_data_cmp(&res, &tests[j].expected);
1015 if (check != 0) {
1016 char res_str[64] = "", expected_str[64] = "";
1017 sdb_data_format(&res, res_str, sizeof(res_str),
1018 SDB_DOUBLE_QUOTED);
1019 sdb_data_format(&tests[j].expected, expected_str,
1020 sizeof(expected_str), SDB_DOUBLE_QUOTED);
1021 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s "
1022 "(type %d); expected: %s (type %d)",
1023 SDB_DATA_OP_TO_STRING(tests[j].op),
1024 d1_str, d2_str, res_str, res.type,
1025 expected_str, tests[j].expected.type);
1026 }
1028 sdb_data_free_datum(&res);
1029 }
1030 }
1031 }
1032 END_TEST
1034 START_TEST(test_format)
1035 {
1036 struct {
1037 sdb_data_t datum;
1038 const char *expected;
1039 } golden_data[] = {
1040 {
1041 { SDB_TYPE_INTEGER, { .integer = 4711 } },
1042 "4711",
1043 },
1044 {
1045 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
1046 "65536",
1047 },
1048 {
1049 { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
1050 "12.3",
1051 },
1052 {
1053 { SDB_TYPE_STRING, { .string = NULL } },
1054 "\"<NULL>\"",
1055 },
1056 {
1057 { SDB_TYPE_STRING, { .string = "this is a test" } },
1058 "\"this is a test\"",
1059 },
1060 {
1061 { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
1062 "\"special \\\\ \\\" characters\"",
1063 },
1064 {
1065 { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
1066 "\"1984-12-06 02:11:54 +0000\"",
1067 },
1068 {
1069 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1070 "\"<NULL>\"",
1071 },
1072 {
1073 {
1074 SDB_TYPE_BINARY,
1075 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
1076 },
1077 "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
1078 },
1079 {
1080 { SDB_TYPE_REGEX, { .re = { "some regex", empty_re } } },
1081 "\"/some regex/\"",
1082 },
1083 };
1085 size_t i;
1087 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1088 sdb_data_t *datum = &golden_data[i].datum;
1089 char buf[sdb_data_strlen(datum) + 2];
1090 int check;
1092 memset(buf, (int)'A', sizeof(buf));
1094 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
1095 SDB_DOUBLE_QUOTED);
1096 fail_unless(check > 0,
1097 "sdb_data_format(type=%s) = %d; expected: >0",
1098 SDB_TYPE_TO_STRING(datum->type), check);
1099 fail_unless(! strcmp(buf, golden_data[i].expected),
1100 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
1101 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
1103 fail_unless((size_t)check <= sizeof(buf) - 2,
1104 "sdb_data_format(type=%s) wrote %d bytes; "
1105 "expected <= %zu based on sdb_data_strlen()",
1106 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
1108 fail_unless(buf[sizeof(buf) - 2] == '\0',
1109 "sdb_data_format(type=%s) did not nul-terminate the buffer",
1110 SDB_TYPE_TO_STRING(datum->type));
1111 fail_unless(buf[sizeof(buf) - 1] == 'A',
1112 "sdb_data_format(type=%s) wrote past the end of the buffer",
1113 SDB_TYPE_TO_STRING(datum->type));
1114 }
1115 }
1116 END_TEST
1118 START_TEST(test_parse)
1119 {
1120 struct {
1121 char *input;
1122 sdb_data_t result;
1123 int expected;
1124 } golden_data[] = {
1125 { "4711", { SDB_TYPE_INTEGER, { .integer = 4711 } }, 0 },
1126 { "0x10", { SDB_TYPE_INTEGER, { .integer = 16 } }, 0 },
1127 { "010", { SDB_TYPE_INTEGER, { .integer = 8 } }, 0 },
1128 { "abc", { SDB_TYPE_INTEGER, { .integer = 0 } }, -1 },
1129 { "1.2", { SDB_TYPE_DECIMAL, { .decimal = 1.2 } }, 0 },
1130 { "0x1p+16", { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } }, 0 },
1131 { "abc", { SDB_TYPE_DECIMAL, { .decimal = 0.0 } }, -1 },
1132 { "abc", { SDB_TYPE_STRING, { .string = "abc" } }, 0 },
1133 { ".4", { SDB_TYPE_DATETIME, { .datetime = 400000000 } }, 0 },
1134 { "abc", { SDB_TYPE_DATETIME, { .datetime = 0 } }, -1 },
1135 { "abc", { SDB_TYPE_BINARY,
1136 { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
1137 { "abc", { SDB_TYPE_REGEX, { .re = { "abc", empty_re } } }, 0 },
1138 { "(|", { SDB_TYPE_REGEX, { .re = { "", empty_re } } }, -1 },
1139 };
1141 size_t i;
1143 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1144 sdb_data_t result;
1145 int type, check;
1147 memset(&result, 0, sizeof(result));
1148 type = golden_data[i].result.type;
1149 check = sdb_data_parse(golden_data[i].input, type, &result);
1150 fail_unless(check == golden_data[i].expected,
1151 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
1152 golden_data[i].input, type, check, golden_data[i].expected);
1154 if (check)
1155 continue;
1157 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
1158 "sdb_data_parse(%s, %d, <d>) did not create expected result",
1159 golden_data[i].input, type);
1161 if (type == SDB_TYPE_STRING)
1162 fail_unless(golden_data[i].input == result.data.string,
1163 "sdb_data_parse(%s, %d, <d>) modified input string",
1164 golden_data[i].input, type);
1165 if (type == SDB_TYPE_BINARY)
1166 fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
1167 "sdb_data_parse(%s, %d, <d>) modified input string",
1168 golden_data[i].input, type);
1169 if (type == SDB_TYPE_REGEX) {
1170 fail_unless(golden_data[i].input != result.data.re.raw,
1171 "sdb_data_parse(%s, %d, <d>) copied input string",
1172 golden_data[i].input, type);
1173 sdb_data_free_datum(&result);
1174 }
1175 }
1176 }
1177 END_TEST
1179 Suite *
1180 core_data_suite(void)
1181 {
1182 Suite *s = suite_create("core::data");
1183 TCase *tc;
1185 tc = tcase_create("core");
1186 tcase_add_test(tc, test_data);
1187 tcase_add_test(tc, test_cmp);
1188 tcase_add_test(tc, test_strcmp);
1189 tcase_add_test(tc, test_parse_op);
1190 tcase_add_test(tc, test_expr_eval);
1191 tcase_add_test(tc, test_format);
1192 tcase_add_test(tc, test_parse);
1193 suite_add_tcase(s, tc);
1195 return s;
1196 } /* core_data_suite */
1198 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */