1 /*
2 * SysDB - t/unit/core/data_test.c
3 * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
28 #include "core/data.h"
29 #include "libsysdb_test.h"
31 #include <check.h>
33 START_TEST(test_data)
34 {
35 sdb_data_t d1, d2;
36 int check;
38 d2.type = SDB_TYPE_INTEGER;
39 d2.data.integer = 4711;
40 memset(&d1, 0, sizeof(d1));
41 check = sdb_data_copy(&d1, &d2);
42 fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
43 fail_unless(d1.type == d2.type,
44 "sdb_data_copy() didn't copy type; got: %i; expected: %i",
45 d1.type, d2.type);
46 fail_unless(d1.data.integer == d2.data.integer,
47 "sdb_data_copy() didn't copy integer data: got: %d; expected: %d",
48 d1.data.integer, d2.data.integer);
50 d2.type = SDB_TYPE_DECIMAL;
51 d2.data.decimal = 47.11;
52 check = sdb_data_copy(&d1, &d2);
53 fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
54 fail_unless(d1.type == d2.type,
55 "sdb_data_copy() didn't copy type; got: %i; expected: %i",
56 d1.type, d2.type);
57 fail_unless(d1.data.decimal == d2.data.decimal,
58 "sdb_data_copy() didn't copy decimal data: got: %f; expected: %f",
59 d1.data.decimal, d2.data.decimal);
61 d2.type = SDB_TYPE_STRING;
62 d2.data.string = "some string";
63 check = sdb_data_copy(&d1, &d2);
64 fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
65 fail_unless(d1.type == d2.type,
66 "sdb_data_copy() didn't copy type; got: %i; expected: %i",
67 d1.type, d2.type);
68 fail_unless(!strcmp(d1.data.string, d2.data.string),
69 "sdb_data_copy() didn't copy string data: got: %s; expected: %s",
70 d1.data.string, d2.data.string);
72 sdb_data_free_datum(&d1);
73 fail_unless(d1.data.string == NULL,
74 "sdb_data_free_datum() didn't free string data");
76 d2.type = SDB_TYPE_DATETIME;
77 d2.data.datetime = 4711;
78 check = sdb_data_copy(&d1, &d2);
79 fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
80 fail_unless(d1.type == d2.type,
81 "sdb_data_copy() didn't copy type; got: %i; expected: %i",
82 d1.type, d2.type);
83 fail_unless(d1.data.datetime == d2.data.datetime,
84 "sdb_data_copy() didn't copy datetime data: got: %d; expected: %d",
85 d1.data.datetime, d2.data.datetime);
87 d2.type = SDB_TYPE_BINARY;
88 d2.data.binary.datum = (unsigned char *)"some string";
89 d2.data.binary.length = strlen((const char *)d2.data.binary.datum);
90 check = sdb_data_copy(&d1, &d2);
91 fail_unless(!check, "sdb_data_copy() = %i; expected: 0", check);
92 fail_unless(d1.type == d2.type,
93 "sdb_data_copy() didn't copy type; got: %i; expected: %i",
94 d1.type, d2.type);
95 fail_unless(d1.data.binary.length == d2.data.binary.length,
96 "sdb_data_copy() didn't copy length; got: %d; expected: 5d",
97 d1.data.binary.length, d2.data.binary.length);
98 fail_unless(!memcmp(d1.data.binary.datum, d2.data.binary.datum,
99 d2.data.binary.length),
100 "sdb_data_copy() didn't copy binary data: got: %s; expected: %s",
101 d1.data.string, d2.data.string);
103 sdb_data_free_datum(&d1);
104 fail_unless(d1.data.binary.length == 0,
105 "sdb_data_free_datum() didn't reset binary datum length");
106 fail_unless(d1.data.binary.datum == NULL,
107 "sdb_data_free_datum() didn't free binary datum");
108 }
109 END_TEST
111 START_TEST(test_cmp)
112 {
113 struct {
114 sdb_data_t d1;
115 sdb_data_t d2;
116 int expected;
117 } golden_data[] = {
118 {
119 { SDB_TYPE_INTEGER, { .integer = 47 } },
120 { SDB_TYPE_INTEGER, { .integer = 4711 } },
121 -1,
122 },
123 {
124 { SDB_TYPE_INTEGER, { .integer = 4711 } },
125 { SDB_TYPE_INTEGER, { .integer = 4711 } },
126 0,
127 },
128 {
129 { SDB_TYPE_INTEGER, { .integer = 4711 } },
130 { SDB_TYPE_INTEGER, { .integer = 47 } },
131 1,
132 },
133 {
134 { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
135 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
136 -1,
137 },
138 {
139 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
140 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
141 0,
142 },
143 {
144 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
145 { SDB_TYPE_DECIMAL, { .decimal = 65535.9 } },
146 1,
147 },
148 {
149 { SDB_TYPE_STRING, { .string = NULL } },
150 { SDB_TYPE_STRING, { .string = "" } },
151 -1,
152 },
153 {
154 { SDB_TYPE_STRING, { .string = NULL } },
155 { SDB_TYPE_STRING, { .string = NULL } },
156 0,
157 },
158 {
159 { SDB_TYPE_STRING, { .string = "" } },
160 { SDB_TYPE_STRING, { .string = NULL } },
161 1,
162 },
163 {
164 { SDB_TYPE_STRING, { .string = "a" } },
165 { SDB_TYPE_STRING, { .string = "b" } },
166 -1,
167 },
168 {
169 { SDB_TYPE_STRING, { .string = "a" } },
170 { SDB_TYPE_STRING, { .string = "ab" } },
171 -1,
172 },
173 {
174 { SDB_TYPE_STRING, { .string = "a" } },
175 { SDB_TYPE_STRING, { .string = "a" } },
176 0,
177 },
178 {
179 { SDB_TYPE_STRING, { .string = "b" } },
180 { SDB_TYPE_STRING, { .string = "a" } },
181 1,
182 },
183 {
184 { SDB_TYPE_STRING, { .string = "ab" } },
185 { SDB_TYPE_STRING, { .string = "a" } },
186 1,
187 },
188 {
189 { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
190 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
191 -1,
192 },
193 {
194 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
195 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
196 0,
197 },
198 {
199 { SDB_TYPE_DATETIME, { .datetime = 471147114711471100 } },
200 { SDB_TYPE_DATETIME, { .datetime = 471147114711471000 } },
201 1,
202 },
203 {
204 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
205 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
206 -1,
207 },
208 {
209 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
210 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
211 0,
212 },
213 {
214 { SDB_TYPE_BINARY, { .binary = { 1, (unsigned char *)"a" } } },
215 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
216 1,
217 },
218 {
219 {
220 SDB_TYPE_BINARY,
221 { .binary = { 3, (unsigned char *)"a\0a" } },
222 },
223 {
224 SDB_TYPE_BINARY,
225 { .binary = { 3, (unsigned char *)"a\0b" } },
226 },
227 -1,
228 },
229 {
230 {
231 SDB_TYPE_BINARY,
232 { .binary = { 1, (unsigned char *)"a" } },
233 },
234 {
235 SDB_TYPE_BINARY,
236 { .binary = { 3, (unsigned char *)"a\0\0" } },
237 },
238 -1,
239 },
240 {
241 {
242 SDB_TYPE_BINARY,
243 { .binary = { 3, (unsigned char *)"a\0a" } },
244 },
245 {
246 SDB_TYPE_BINARY,
247 { .binary = { 3, (unsigned char *)"a\0a" } },
248 },
249 0,
250 },
251 {
252 {
253 SDB_TYPE_BINARY,
254 { .binary = { 3, (unsigned char *)"a\0b" } },
255 },
256 {
257 SDB_TYPE_BINARY,
258 { .binary = { 3, (unsigned char *)"a\0a" } },
259 },
260 1,
261 },
262 {
263 {
264 SDB_TYPE_BINARY,
265 { .binary = { 3, (unsigned char *)"a\0\0" } },
266 },
267 {
268 SDB_TYPE_BINARY,
269 { .binary = { 1, (unsigned char *)"a" } },
270 },
271 1,
272 },
273 };
275 size_t i;
277 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
278 int check = sdb_data_cmp(&golden_data[i].d1, &golden_data[i].d2);
279 check = check < 0 ? -1 : check > 0 ? 1 : 0;
280 if (check != golden_data[i].expected) {
281 char d1_str[64] = "", d2_str[64] = "";
282 sdb_data_format(&golden_data[i].d1, d1_str, sizeof(d1_str),
283 SDB_DOUBLE_QUOTED);
284 sdb_data_format(&golden_data[i].d2, d2_str, sizeof(d2_str),
285 SDB_DOUBLE_QUOTED);
286 fail("sdb_data_cmp(%s, %s) = %d; expected: %d",
287 d1_str, d2_str, check, golden_data[i].expected);
288 }
289 }
290 }
291 END_TEST
293 START_TEST(test_format)
294 {
295 struct {
296 sdb_data_t datum;
297 const char *expected;
298 } golden_data[] = {
299 {
300 { SDB_TYPE_INTEGER, { .integer = 4711 } },
301 "4711",
302 },
303 {
304 { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } },
305 "0x1p+16",
306 },
307 {
308 { SDB_TYPE_STRING, { .string = NULL } },
309 "\"NULL\"",
310 },
311 {
312 { SDB_TYPE_STRING, { .string = "this is a test" } },
313 "\"this is a test\"",
314 },
315 {
316 { SDB_TYPE_STRING, { .string = "special \\ \" characters" } },
317 "\"special \\\\ \\\" characters\"",
318 },
319 {
320 { SDB_TYPE_DATETIME, { .datetime= 471147114711471100 } },
321 "\"1984-12-06 02:11:54 +0000\"",
322 },
323 {
324 { SDB_TYPE_BINARY, { .binary = { 0, NULL } } },
325 "\"\"",
326 },
327 {
328 {
329 SDB_TYPE_BINARY,
330 { .binary = { 12, (unsigned char *)"binary\0crap\x42" } },
331 },
332 "\"\\x62\\x69\\x6e\\x61\\x72\\x79\\x0\\x63\\x72\\x61\\x70\\x42\"",
333 },
334 };
336 size_t i;
338 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
339 sdb_data_t *datum = &golden_data[i].datum;
340 char buf[sdb_data_strlen(datum) + 2];
341 int check;
343 memset(buf, (int)'A', sizeof(buf));
345 check = sdb_data_format(datum, buf, sizeof(buf) - 1,
346 SDB_DOUBLE_QUOTED);
347 fail_unless(check > 0,
348 "sdb_data_format(type=%s) = %d; expected: >0",
349 SDB_TYPE_TO_STRING(datum->type), check);
350 fail_unless(! strcmp(buf, golden_data[i].expected),
351 "sdb_data_format(type=%s) used wrong format: %s; expected: %s",
352 SDB_TYPE_TO_STRING(datum->type), buf, golden_data[i].expected);
354 fail_unless((size_t)check <= sizeof(buf) - 2,
355 "sdb_data_format(type=%s) wrote %d bytes; "
356 "expected <= %zu based on sdb_data_strlen()",
357 SDB_TYPE_TO_STRING(datum->type), check, sizeof(buf) - 2);
359 fail_unless(buf[sizeof(buf) - 2] == '\0',
360 "sdb_data_format(type=%s) did not nul-terminate the buffer",
361 SDB_TYPE_TO_STRING(datum->type));
362 fail_unless(buf[sizeof(buf) - 1] == 'A',
363 "sdb_data_format(type=%s) wrote past the end of the buffer",
364 SDB_TYPE_TO_STRING(datum->type));
365 }
366 }
367 END_TEST
369 START_TEST(test_parse)
370 {
371 struct {
372 char *input;
373 sdb_data_t result;
374 int expected;
375 } golden_data[] = {
376 { "4711", { SDB_TYPE_INTEGER, { .integer = 4711 } }, 0 },
377 { "0x10", { SDB_TYPE_INTEGER, { .integer = 16 } }, 0 },
378 { "010", { SDB_TYPE_INTEGER, { .integer = 8 } }, 0 },
379 { "abc", { SDB_TYPE_INTEGER, { .integer = 0 } }, -1 },
380 { "1.2", { SDB_TYPE_DECIMAL, { .decimal = 1.2 } }, 0 },
381 { "0x1p+16", { SDB_TYPE_DECIMAL, { .decimal = 65536.0 } }, 0 },
382 { "abc", { SDB_TYPE_DECIMAL, { .decimal = 0.0 } }, -1 },
383 { "abc", { SDB_TYPE_STRING, { .string = "abc" } }, 0 },
384 { ".4", { SDB_TYPE_DATETIME, { .datetime = 400000000 } }, 0 },
385 { "abc", { SDB_TYPE_DATETIME, { .datetime = 0 } }, -1 },
386 { "abc", { SDB_TYPE_BINARY,
387 { .binary = { 3, (unsigned char *)"abc" } } }, 0 },
388 };
390 size_t i;
392 for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
393 sdb_data_t result;
394 int type, check;
396 memset(&result, 0, sizeof(result));
397 type = golden_data[i].result.type;
398 check = sdb_data_parse(golden_data[i].input, type, &result);
399 fail_unless(check == golden_data[i].expected,
400 "sdb_data_parse(%s, %d, <d>) = %d; expected: %d",
401 golden_data[i].input, type, check, golden_data[i].expected);
403 if (check)
404 continue;
406 fail_unless(sdb_data_cmp(&result, &golden_data[i].result) == 0,
407 "sdb_data_parse(%s, %d, <d>) did not create expected result",
408 golden_data[i].input, type);
410 if (type == SDB_TYPE_STRING)
411 fail_unless(golden_data[i].input == result.data.string,
412 "sdb_data_parse(%s, %d, <d>) modified input string",
413 golden_data[i].input, type);
414 if (type == SDB_TYPE_BINARY)
415 fail_unless(golden_data[i].input == (char *)result.data.binary.datum,
416 "sdb_data_parse(%s, %d, <d>) modified input string",
417 golden_data[i].input, type);
418 }
419 }
420 END_TEST
422 Suite *
423 core_data_suite(void)
424 {
425 Suite *s = suite_create("core::data");
426 TCase *tc;
428 tc = tcase_create("core");
429 tcase_add_test(tc, test_data);
430 tcase_add_test(tc, test_cmp);
431 tcase_add_test(tc, test_format);
432 tcase_add_test(tc, test_parse);
433 suite_add_tcase(s, tc);
435 return s;
436 } /* core_data_suite */
438 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */