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