9c736d399e291d12eb61c80ae0c3a83772393d2e
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");
184 }
185 END_TEST
187 START_TEST(test_cmp)
188 {
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 }
381 }
382 END_TEST
384 START_TEST(test_strcmp)
385 {
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 }
617 }
618 END_TEST
620 START_TEST(test_parse_op)
621 {
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 }
654 }
655 END_TEST
657 START_TEST(test_expr_eval)
658 {
659 sdb_data_t err = { -1, { .integer = 0 } };
661 struct {
662 sdb_data_t d1;
663 sdb_data_t d2;
664 sdb_data_t expected_add;
665 sdb_data_t expected_sub;
666 sdb_data_t expected_mul;
667 sdb_data_t expected_div;
668 sdb_data_t expected_mod;
669 sdb_data_t expected_concat;
670 } golden_data[] = {
671 {
672 { SDB_TYPE_INTEGER, { .integer = 4711 } },
673 { SDB_TYPE_INTEGER, { .integer = 47 } },
674 { SDB_TYPE_INTEGER, { .integer = 4758 } },
675 { SDB_TYPE_INTEGER, { .integer = 4664 } },
676 { SDB_TYPE_INTEGER, { .integer = 221417 } },
677 { SDB_TYPE_INTEGER, { .integer = 100 } },
678 { SDB_TYPE_INTEGER, { .integer = 11 } },
679 err,
680 },
681 {
682 { SDB_TYPE_DECIMAL, { .decimal = 35.0 } },
683 { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
684 { SDB_TYPE_DECIMAL, { .decimal = 52.5 } },
685 { SDB_TYPE_DECIMAL, { .decimal = 17.5 } },
686 { SDB_TYPE_DECIMAL, { .decimal = 612.5 } },
687 { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
688 { SDB_TYPE_DECIMAL, { .decimal = 0.0 } },
689 err,
690 },
691 {
692 { SDB_TYPE_STRING, { .string = NULL } },
693 { SDB_TYPE_STRING, { .string = "" } },
694 SDB_DATA_NULL,
695 SDB_DATA_NULL,
696 SDB_DATA_NULL,
697 SDB_DATA_NULL,
698 SDB_DATA_NULL,
699 SDB_DATA_NULL,
700 },
701 {
702 { SDB_TYPE_STRING, { .string = NULL } },
703 { SDB_TYPE_STRING, { .string = NULL } },
704 SDB_DATA_NULL,
705 SDB_DATA_NULL,
706 SDB_DATA_NULL,
707 SDB_DATA_NULL,
708 SDB_DATA_NULL,
709 SDB_DATA_NULL,
710 },
711 {
712 { SDB_TYPE_STRING, { .string = "" } },
713 { SDB_TYPE_STRING, { .string = NULL } },
714 SDB_DATA_NULL,
715 SDB_DATA_NULL,
716 SDB_DATA_NULL,
717 SDB_DATA_NULL,
718 SDB_DATA_NULL,
719 SDB_DATA_NULL,
720 },
721 {
722 { SDB_TYPE_STRING, { .string = "a" } },
723 { SDB_TYPE_STRING, { .string = "b" } },
724 err,
725 err,
726 err,
727 err,
728 err,
729 { SDB_TYPE_STRING, { .string = "ab" } },
730 },
731 {
732 { SDB_TYPE_DATETIME, { .datetime = 47114711 } },
733 { SDB_TYPE_DATETIME, { .datetime = 4711 } },
734 { SDB_TYPE_DATETIME, { .datetime = 47119422 } },
735 { SDB_TYPE_DATETIME, { .datetime = 47110000 } },
736 { SDB_TYPE_DATETIME, { .datetime = 221957403521 } },
737 { SDB_TYPE_DATETIME, { .datetime = 10001 } },
738 { SDB_TYPE_DATETIME, { .datetime = 0 } },
739 err,
740 },
741 {
742 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
743 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
744 SDB_DATA_NULL,
745 SDB_DATA_NULL,
746 SDB_DATA_NULL,
747 SDB_DATA_NULL,
748 SDB_DATA_NULL,
749 SDB_DATA_NULL,
750 },
751 {
752 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
753 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
754 SDB_DATA_NULL,
755 SDB_DATA_NULL,
756 SDB_DATA_NULL,
757 SDB_DATA_NULL,
758 SDB_DATA_NULL,
759 SDB_DATA_NULL,
760 },
761 {
762 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
763 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
764 SDB_DATA_NULL,
765 SDB_DATA_NULL,
766 SDB_DATA_NULL,
767 SDB_DATA_NULL,
768 SDB_DATA_NULL,
769 SDB_DATA_NULL,
770 },
771 {
772 {
773 SDB_TYPE_BINARY,
774 { .binary = { 3, (unsigned char *)"a\0a" } },
775 },
776 {
777 SDB_TYPE_BINARY,
778 { .binary = { 3, (unsigned char *)"b\0b" } },
779 },
780 err,
781 err,
782 err,
783 err,
784 err,
785 {
786 SDB_TYPE_BINARY,
787 { .binary = { 6, (unsigned char *)"a\0ab\0b" } },
788 },
789 },
790 {
791 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
792 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
793 err,
794 err,
795 err,
796 err,
797 err,
798 err,
799 },
800 {
801 { SDB_TYPE_NULL, { .integer = 0 } },
802 { SDB_TYPE_NULL, { .integer = 0 } },
803 SDB_DATA_NULL,
804 SDB_DATA_NULL,
805 SDB_DATA_NULL,
806 SDB_DATA_NULL,
807 SDB_DATA_NULL,
808 SDB_DATA_NULL,
809 },
810 {
811 { SDB_TYPE_NULL, { .integer = 0 } },
812 { SDB_TYPE_INTEGER, { .integer = 42 } },
813 SDB_DATA_NULL,
814 SDB_DATA_NULL,
815 SDB_DATA_NULL,
816 SDB_DATA_NULL,
817 SDB_DATA_NULL,
818 SDB_DATA_NULL,
819 },
820 {
821 { SDB_TYPE_INTEGER, { .integer = 42 } },
822 { SDB_TYPE_NULL, { .integer = 0 } },
823 SDB_DATA_NULL,
824 SDB_DATA_NULL,
825 SDB_DATA_NULL,
826 SDB_DATA_NULL,
827 SDB_DATA_NULL,
828 SDB_DATA_NULL,
829 },
830 {
831 { SDB_TYPE_NULL, { .integer = 0 } },
832 { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
833 SDB_DATA_NULL,
834 SDB_DATA_NULL,
835 SDB_DATA_NULL,
836 SDB_DATA_NULL,
837 SDB_DATA_NULL,
838 SDB_DATA_NULL,
839 },
840 {
841 { SDB_TYPE_DECIMAL, { .decimal = 47.11 } },
842 { SDB_TYPE_NULL, { .integer = 0 } },
843 SDB_DATA_NULL,
844 SDB_DATA_NULL,
845 SDB_DATA_NULL,
846 SDB_DATA_NULL,
847 SDB_DATA_NULL,
848 SDB_DATA_NULL,
849 },
850 {
851 { SDB_TYPE_NULL, { .integer = 0 } },
852 { SDB_TYPE_STRING, { .string = "47.11" } },
853 SDB_DATA_NULL,
854 SDB_DATA_NULL,
855 SDB_DATA_NULL,
856 SDB_DATA_NULL,
857 SDB_DATA_NULL,
858 SDB_DATA_NULL,
859 },
860 {
861 { SDB_TYPE_STRING, { .string = "47.11" } },
862 { SDB_TYPE_NULL, { .integer = 0 } },
863 SDB_DATA_NULL,
864 SDB_DATA_NULL,
865 SDB_DATA_NULL,
866 SDB_DATA_NULL,
867 SDB_DATA_NULL,
868 SDB_DATA_NULL,
869 },
870 {
871 { SDB_TYPE_NULL, { .integer = 0 } },
872 { SDB_TYPE_DATETIME, { .datetime = 4711 } },
873 SDB_DATA_NULL,
874 SDB_DATA_NULL,
875 SDB_DATA_NULL,
876 SDB_DATA_NULL,
877 SDB_DATA_NULL,
878 SDB_DATA_NULL,
879 },
880 {
881 { SDB_TYPE_DATETIME, { .datetime = 4711 } },
882 { SDB_TYPE_NULL, { .integer = 0 } },
883 SDB_DATA_NULL,
884 SDB_DATA_NULL,
885 SDB_DATA_NULL,
886 SDB_DATA_NULL,
887 SDB_DATA_NULL,
888 SDB_DATA_NULL,
889 },
890 {
891 { SDB_TYPE_NULL, { .integer = 0 } },
892 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
893 SDB_DATA_NULL,
894 SDB_DATA_NULL,
895 SDB_DATA_NULL,
896 SDB_DATA_NULL,
897 SDB_DATA_NULL,
898 SDB_DATA_NULL,
899 },
900 {
901 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
902 { SDB_TYPE_NULL, { .integer = 0 } },
903 SDB_DATA_NULL,
904 SDB_DATA_NULL,
905 SDB_DATA_NULL,
906 SDB_DATA_NULL,
907 SDB_DATA_NULL,
908 SDB_DATA_NULL,
909 },
910 {
911 { SDB_TYPE_NULL, { .integer = 0 } },
912 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
913 SDB_DATA_NULL,
914 SDB_DATA_NULL,
915 SDB_DATA_NULL,
916 SDB_DATA_NULL,
917 SDB_DATA_NULL,
918 SDB_DATA_NULL,
919 },
920 {
921 { SDB_TYPE_REGEX, { .re = { ".", empty_re } } },
922 { SDB_TYPE_NULL, { .integer = 0 } },
923 SDB_DATA_NULL,
924 SDB_DATA_NULL,
925 SDB_DATA_NULL,
926 SDB_DATA_NULL,
927 SDB_DATA_NULL,
928 SDB_DATA_NULL,
929 },
930 /* supported type-mismatches */
931 {
932 /* int * datetime */
933 { SDB_TYPE_INTEGER, { .integer = 20 } },
934 { SDB_TYPE_DATETIME, { .datetime = 2 } },
935 err,
936 err,
937 { SDB_TYPE_DATETIME, { .datetime = 40 } },
938 err,
939 err,
940 err,
941 },
942 {
943 /* datetime * int, datetime / int, datetime % int */
944 { SDB_TYPE_DATETIME, { .datetime = 20 } },
945 { SDB_TYPE_INTEGER, { .integer = 2 } },
946 err,
947 err,
948 { SDB_TYPE_DATETIME, { .datetime = 40 } },
949 { SDB_TYPE_DATETIME, { .datetime = 10 } },
950 { SDB_TYPE_DATETIME, { .datetime = 0 } },
951 err,
952 },
953 {
954 /* float * datetime */
955 { SDB_TYPE_DECIMAL, { .decimal = 20.0 } },
956 { SDB_TYPE_DATETIME, { .datetime = 2 } },
957 err,
958 err,
959 { SDB_TYPE_DATETIME, { .datetime = 40 } },
960 err,
961 err,
962 err,
963 },
964 {
965 /* datetime * float, datetime / float, datetime % float */
966 { SDB_TYPE_DATETIME, { .datetime = 20 } },
967 { SDB_TYPE_DECIMAL, { .decimal = 2.0 } },
968 err,
969 err,
970 { SDB_TYPE_DATETIME, { .datetime = 40 } },
971 { SDB_TYPE_DATETIME, { .datetime = 10 } },
972 { SDB_TYPE_DATETIME, { .datetime = 0 } },
973 err,
974 },
975 };
977 size_t i;
979 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
980 struct {
981 int op;
982 sdb_data_t expected;
983 } tests[] = {
984 { SDB_DATA_ADD, golden_data[i].expected_add },
985 { SDB_DATA_SUB, golden_data[i].expected_sub },
986 { SDB_DATA_MUL, golden_data[i].expected_mul },
987 { SDB_DATA_DIV, golden_data[i].expected_div },
988 { SDB_DATA_MOD, golden_data[i].expected_mod },
989 { SDB_DATA_CONCAT, golden_data[i].expected_concat },
990 };
992 size_t j;
993 for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) {
994 sdb_data_t res;
995 int check;
997 char d1_str[64] = "", d2_str[64] = "";
998 sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
999 SDB_DOUBLE_QUOTED);
1000 sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
1001 SDB_DOUBLE_QUOTED);
1003 check = sdb_data_expr_eval(tests[j].op,
1004 &golden_data[i].d1, &golden_data[i].d2, &res);
1005 fail_unless((check == 0) == (tests[j].expected.type != -1),
1006 "sdb_data_expr_eval(%s, %s, %s) = %d; expected: %d",
1007 SDB_DATA_OP_TO_STRING(tests[j].op), d1_str, d2_str, check,
1008 tests[j].expected.type == -1 ? -1 : 0);
1009 if (tests[j].expected.type == -1)
1010 continue;
1012 if (tests[j].expected.type == SDB_TYPE_NULL) {
1013 fail_unless(res.type == SDB_TYPE_NULL,
1014 "sdb_data_expr_eval(%s, %s, %s) evaluated to "
1015 "type %d; expected: SDB_TYPE_NULL",
1016 SDB_DATA_OP_TO_STRING(tests[j].op),
1017 d1_str, d2_str, res.type);
1018 continue;
1019 }
1021 check = sdb_data_cmp(&res, &tests[j].expected);
1022 if (check != 0) {
1023 char res_str[64] = "", expected_str[64] = "";
1024 sdb_data_format(&res, res_str, sizeof(res_str),
1025 SDB_DOUBLE_QUOTED);
1026 sdb_data_format(&tests[j].expected, expected_str,
1027 sizeof(expected_str), SDB_DOUBLE_QUOTED);
1028 fail("sdb_data_expr_eval(%s, %s, %s) evaluated to %s "
1029 "(type %d); expected: %s (type %d)",
1030 SDB_DATA_OP_TO_STRING(tests[j].op),
1031 d1_str, d2_str, res_str, res.type,
1032 expected_str, tests[j].expected.type);
1033 }
1035 sdb_data_free_datum(&res);
1036 }
1037 }
1038 }
1039 END_TEST
1041 START_TEST(test_format)
1042 {
1043 struct {
1044 sdb_data_t datum;
1045 const char *expected;
1046 } golden_data[] = {
1047 {
1048 { SDB_TYPE_INTEGER, { .integer = 4711 } },
1049 "4711",
1050 },
1051 {
1052 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
1053 "65536",
1054 },
1055 {
1056 { SDB_TYPE_DECIMAL, { .decimal = 12.3 } },
1057 "12.3",
1058 },
1059 {
1060 { SDB_TYPE_STRING, { .string = NULL } },
1061 "\"<NULL>\"",
1062 },
1063 {
1064 { SDB_TYPE_STRING, { .string = "this is a test" } },
1065 "\"this is a test\"",
1066 },
1067 {
1068 { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
1069 "\"special \\\\ \\\" characters\"",
1070 },
1071 {
1072 { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
1073 "\"1984-12-06 02:11:54 +0000\"",
1074 },
1075 {
1076 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
1077 "\"<NULL>\"",
1078 },
1079 {
1080 {
1081 SDB_TYPE_BINARY,
1082 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
1083 },
1084 "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
1085 },
1086 {
1087 { SDB_TYPE_REGEX, { .re = { "some regex", empty_re } } },
1088 "\"/some regex/\"",
1089 },
1090 };
1092 size_t i;
1094 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1095 sdb_data_t *datum = &golden_data[i].datum;
1096 char buf[sdb_data_strlen(datum) + 2];
1097 int check;
1099 memset(buf, (int)'A', sizeof(buf));
1101 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
1102 SDB_DOUBLE_QUOTED);
1103 fail_unless(check > 0,
1104 "sdb_data_format(type=%s) = %d; expected: >0",
1105 SDB_TYPE_TO_STRING(datum->type), check);
1106 fail_unless(! strcmp(buf, golden_data[i].expected),
1107 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
1108 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
1110 fail_unless((size_t)check <= sizeof(buf) - 2,
1111 "sdb_data_format(type=%s) wrote %d bytes; "
1112 "expected <= %zu based on sdb_data_strlen()",
1113 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
1115 fail_unless(buf[sizeof(buf) - 2] == '\0',
1116 "sdb_data_format(type=%s) did not nul-terminate the buffer",
1117 SDB_TYPE_TO_STRING(datum->type));
1118 fail_unless(buf[sizeof(buf) - 1] == 'A',
1119 "sdb_data_format(type=%s) wrote past the end of the buffer",
1120 SDB_TYPE_TO_STRING(datum->type));
1121 }
1122 }
1123 END_TEST
1125 START_TEST(test_parse)
1126 {
1127 struct {
1128 char *input;
1129 sdb_data_t result;
1130 int expected;
1131 } golden_data[] = {
1132 { "4711", { SDB_TYPE_INTEGER, { .integer = 4711 } }, 0 },
1133 { "0x10", { SDB_TYPE_INTEGER, { .integer = 16 } }, 0 },
1134 { "010", { SDB_TYPE_INTEGER, { .integer = 8 } }, 0 },
1135 { "abc", { SDB_TYPE_INTEGER, { .integer = 0 } }, -1 },
1136 { "1.2", { SDB_TYPE_DECIMAL, { .decimal = 1.2 } }, 0 },
1137 { "0x1p+16", { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } }, 0 },
1138 { "abc", { SDB_TYPE_DECIMAL, { .decimal = 0.0 } }, -1 },
1139 { "abc", { SDB_TYPE_STRING, { .string = "abc" } }, 0 },
1140 { ".4", { SDB_TYPE_DATETIME, { .datetime = 400000000 } }, 0 },
1141 { "abc", { SDB_TYPE_DATETIME, { .datetime = 0 } }, -1 },
1142 { "abc", { SDB_TYPE_BINARY,
1143 { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
1144 { "abc", { SDB_TYPE_REGEX, { .re = { "abc", empty_re } } }, 0 },
1145 { "(|", { SDB_TYPE_REGEX, { .re = { "", empty_re } } }, -1 },
1146 };
1148 size_t i;
1150 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
1151 sdb_data_t result;
1152 int type, check;
1154 memset(&result, 0, sizeof(result));
1155 type = golden_data[i].result.type;
1156 check = sdb_data_parse(golden_data[i].input, type, &result);
1157 fail_unless(check == golden_data[i].expected,
1158 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
1159 golden_data[i].input, type, check, golden_data[i].expected);
1161 if (check)
1162 continue;
1164 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
1165 "sdb_data_parse(%s, %d, <d>) did not create expected result",
1166 golden_data[i].input, type);
1168 if (type == SDB_TYPE_STRING)
1169 fail_unless(golden_data[i].input == result.data.string,
1170 "sdb_data_parse(%s, %d, <d>) modified input string",
1171 golden_data[i].input, type);
1172 if (type == SDB_TYPE_BINARY)
1173 fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
1174 "sdb_data_parse(%s, %d, <d>) modified input string",
1175 golden_data[i].input, type);
1176 if (type == SDB_TYPE_REGEX) {
1177 fail_unless(golden_data[i].input != result.data.re.raw,
1178 "sdb_data_parse(%s, %d, <d>) copied input string",
1179 golden_data[i].input, type);
1180 sdb_data_free_datum(&result);
1181 }
1182 }
1183 }
1184 END_TEST
1186 Suite *
1187 core_data_suite(void)
1188 {
1189 Suite *s = suite_create("core::data");
1190 TCase *tc;
1192 tc = tcase_create("core");
1193 tcase_add_test(tc, test_data);
1194 tcase_add_test(tc, test_cmp);
1195 tcase_add_test(tc, test_strcmp);
1196 tcase_add_test(tc, test_parse_op);
1197 tcase_add_test(tc, test_expr_eval);
1198 tcase_add_test(tc, test_format);
1199 tcase_add_test(tc, test_parse);
1200 suite_add_tcase(s, tc);
1202 return s;
1203 } /* core_data_suite */
1205 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */