Code

data: Added helper functions to copy and free data.
[sysdb.git] / t / utils / strbuf_test.c
1 /*
2  * SysDB - t/utils/strbuf_test.c
3  * Copyright (C) 2013 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 "utils/strbuf.h"
29 #include "libsysdb_test.h"
31 #include <check.h>
33 /*
34  * private data types
35  */
37 static sdb_strbuf_t *buf;
39 static void
40 setup(void)
41 {
42         buf = sdb_strbuf_create(0);
43         fail_unless(buf != NULL,
44                         "sdb_strbuf_create() = NULL; expected strbuf object");
45 } /* setup */
47 static void
48 teardown(void)
49 {
50         sdb_strbuf_destroy(buf);
51         buf = NULL;
52 } /* teardown */
54 /*
55  * tests
56  */
58 START_TEST(test_null)
59 {
60         sdb_strbuf_t *b = NULL;
61         va_list ap;
63         /* check that methods don't crash */
64         sdb_strbuf_destroy(b);
65         sdb_strbuf_skip(b, 0, 0);
66         sdb_strbuf_skip(b, 0, 10);
67         sdb_strbuf_skip(b, 10, 10);
68         sdb_strbuf_clear(b);
70         /* check that methods return an error */
71         fail_unless(sdb_strbuf_vappend(b, "test", ap) < 0,
72                         "sdb_strbuf_vappend(NULL) didn't report failure");
73         fail_unless(sdb_strbuf_append(b, "test") < 0,
74                         "sdb_strbuf_append(NULL) didn't report failure");
75         fail_unless(sdb_strbuf_vsprintf(b, "test", ap) < 0,
76                         "sdb_strbuf_vsprintf(NULL) didn't report failure");
77         fail_unless(sdb_strbuf_sprintf(b, "test") < 0,
78                         "sdb_strbuf_sprintf(NULL) didn't report failure");
79         fail_unless(sdb_strbuf_memcpy(b, "test", 4) < 0,
80                         "sdb_strbuf_memcpy(NULL) didn't report failure");
81         fail_unless(sdb_strbuf_memappend(b, "test", 4) < 0,
82                         "sdb_strbuf_memappend(NULL) didn't report failure");
83         fail_unless(sdb_strbuf_read(b, 0, 32) < 0,
84                         "sdb_strbuf_read(NULL) didn't report failure");
85         fail_unless(sdb_strbuf_chomp(b) < 0,
86                         "sdb_strbuf_chomp(NULL) didn't report failure");
87 }
88 END_TEST
90 START_TEST(test_empty)
91 {
92         sdb_strbuf_t *b = sdb_strbuf_create(0);
93         const char *data;
94         size_t len;
96         /* check that methods don't crash */
97         sdb_strbuf_skip(b, 1, 1);
98         sdb_strbuf_clear(b);
99         sdb_strbuf_chomp(b);
101         data = sdb_strbuf_string(b);
102         fail_unless(data && (*data == '\0'),
103                         "sdb_strbuf_string(<empty>) = '%s'; expected: ''", data);
104         len = sdb_strbuf_len(b);
105         fail_unless(len == 0,
106                         "sdb_strbuf_len(<empty>) = %zu; expected: 0", len);
108         sdb_strbuf_destroy(b);
110 END_TEST
112 START_TEST(test_sdb_strbuf_create)
114         sdb_strbuf_t *s;
115         size_t len;
117         s = sdb_strbuf_create(0);
118         fail_unless(s != NULL,
119                         "sdb_strbuf_create() = NULL; expected strbuf object");
120         len = sdb_strbuf_len(s);
121         fail_unless(len == 0,
122                         "sdb_strbuf_create() created buffer with len = %zu; "
123                         "expected: 0", len);
124         sdb_strbuf_destroy(s);
126         s = sdb_strbuf_create(128);
127         fail_unless(s != NULL,
128                         "sdb_strbuf_create() = NULL; expected strbuf object");
129         len = sdb_strbuf_len(s);
130         /* len still has to be 0 -- there's no content */
131         fail_unless(len == 0,
132                         "sdb_strbuf_create() created buffer with len = %zu; "
133                         "expected: 0", len);
134         sdb_strbuf_destroy(s);
136 END_TEST
138 START_TEST(test_sdb_strbuf_append)
140         ssize_t n, expected;
141         size_t len;
142         const char *test;
144         n = sdb_strbuf_append(buf, "1234567890");
145         fail_unless(n == 10,
146                         "sdb_strbuf_append() appended %zi bytes; expected: 10", n);
147         len = sdb_strbuf_len(buf);
148         fail_unless(len == 10,
149                         "sdb_strbuf_append() left behind buffer with len = %zu; "
150                         "expected: 10", len);
152         n = sdb_strbuf_append(buf, "ABCDE");
153         fail_unless(n == 5,
154                         "sdb_strbuf_append() appended %zi bytes; expected: 5", n);
155         len = sdb_strbuf_len(buf);
156         fail_unless(len == 15,
157                         "sdb_strbuf_append() left behind buffer with len = %zu; "
158                         "expected: 15", len);
160         test = sdb_strbuf_string(buf);
161         fail_unless(test[len] == '\0',
162                         "sdb_strbuf_append() did not nil-terminate the string");
163         fail_unless(!strcmp(test, "1234567890ABCDE"),
164                         "sdb_strbuf_append() did not correctly concatenate two string; "
165                         "got: %s; expected: 1234567890ABCDE", test);
167         n = sdb_strbuf_append(buf, "%zu; %5.4f", len, (double)len / 10.0);
168         expected = /* len */ 2 + /* "; " */ 2 + /* decimal len/10 */ 6;
169         fail_unless(n == expected,
170                         "sdb_strbuf_append() appended %zi bytes; expected: %zi",
171                         n, expected);
172         len = sdb_strbuf_len(buf);
173         fail_unless(len == 15 + (size_t)expected,
174                         "sdb_strbuf_append() left behind buffer with len = %zu; "
175                         "expected: %zu", len, 15 + (size_t)expected);
177         test = sdb_strbuf_string(buf);
178         fail_unless(test[len] == '\0',
179                         "sdb_strbuf_append() did not nil-terminate the string");
180         fail_unless(!strcmp(test, "1234567890ABCDE15; 1.5000"),
181                         "sdb_strbuf_append() did not correctly concatenate two string; "
182                         "got: %s; expected: 1234567890ABCDE15; 1.5000", test);
184 END_TEST
186 START_TEST(test_sdb_strbuf_sprintf)
188         ssize_t n, expected;
189         size_t len;
190         const char *test;
192         n = sdb_strbuf_sprintf(buf, "1234567890");
193         fail_unless(n == 10,
194                         "sdb_strbuf_sprintf() wrote %zi bytes; expected: 10", n);
195         len = sdb_strbuf_len(buf);
196         fail_unless(len == 10,
197                         "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
198                         "expected: 10", len);
200         n = sdb_strbuf_sprintf(buf, "ABCDE");
201         fail_unless(n == 5,
202                         "sdb_strbuf_sprintf() wrote %zi bytes; expected: 5", n);
203         len = sdb_strbuf_len(buf);
204         fail_unless(len == 5,
205                         "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
206                         "expected: 5", len);
208         test = sdb_strbuf_string(buf);
209         fail_unless(test[len] == '\0',
210                         "sdb_strbuf_sprintf() did not nil-terminate the string");
211         fail_unless(!strcmp(test, "ABCDE"),
212                         "sdb_strbuf_sprintf() did not format string correctly; "
213                         "got: %s; expected: ABCDE", test);
215         n = sdb_strbuf_sprintf(buf, "%zu; %5.4f", len, (double)len / 10.0);
216         expected = /* len */ 1 + /* "; " */ 2 + /* decimal len/10 */ 6;
217         fail_unless(n == expected,
218                         "sdb_strbuf_sprintf() wrote %zi bytes; expected: %zi",
219                         n, expected);
220         len = sdb_strbuf_len(buf);
221         fail_unless(len == (size_t)expected,
222                         "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
223                         "expected: %zu", len, (size_t)expected);
225         test = sdb_strbuf_string(buf);
226         fail_unless(test[len] == '\0',
227                         "sdb_strbuf_sprintf() did not nil-terminate the string");
228         fail_unless(!strcmp(test, "5; 0.5000"),
229                         "sdb_strbuf_sprintf() did not format string correctly; "
230                         "got: %s; expected: 5; 0.5000", test);
232 END_TEST
234 START_TEST(test_incremental)
236         ssize_t n;
237         size_t i;
239         sdb_strbuf_destroy(buf);
240         buf = sdb_strbuf_create(1024);
242         /* fill buffer one by one; leave room for nul-byte */
243         for (i = 0; i < 1023; ++i) {
244                 n = sdb_strbuf_append(buf, ".");
245                 fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
246         }
248         /* write another byte; this has to trigger a resize */
249         n = sdb_strbuf_append(buf, ".");
250         fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
252         /* write more bytes; this should trigger at least one more resize but
253          * that's an implementation detail */
254         for (i = 0; i < 1024; ++i) {
255                 n = sdb_strbuf_append(buf, ".");
256                 fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
257         }
259         n = (ssize_t)sdb_strbuf_len(buf);
260         fail_unless(n == 2048, "sdb_strbuf_len() = %zi; expectd: 2048", n);
262 END_TEST
264 static struct {
265         const char *input;
266         size_t size;
267 } mem_golden_data[] = {
268         { "abc\0\x10\x42", 6 },
269         { "\0\1\2\3\4", 5 },
270         { "\n\n\0\n\n", 5 },
271         { "", 0 },
272 };
274 START_TEST(test_sdb_strbuf_memcpy)
276         size_t i;
278         for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
279                 ssize_t n;
280                 const char *check;
282                 n = sdb_strbuf_memcpy(buf, mem_golden_data[i].input,
283                                 mem_golden_data[i].size);
284                 fail_unless(n >= 0,
285                                 "sdb_strbuf_memcpy() = %zi; expected: >=0", n);
286                 fail_unless((size_t)n == mem_golden_data[i].size,
287                                 "sdb_strbuf_memcpy() = %zi; expected: %zu",
288                                 n, mem_golden_data[i].size);
290                 n = (ssize_t)sdb_strbuf_len(buf);
291                 fail_unless((size_t)n == mem_golden_data[i].size,
292                                 "sdb_strbuf_len() = %zu (after memcpy); expected: %zu",
293                                 n, mem_golden_data[i].size);
295                 check = sdb_strbuf_string(buf);
296                 fail_unless(check != NULL,
297                                 "sdb_strbuf_string() = NULL (after memcpy); expected: data");
298                 fail_unless(check[mem_golden_data[i].size] == '\0',
299                                 "sdb_strbuf_memcpy() did not nil-terminate the data");
300                 fail_unless(!memcmp(check, mem_golden_data[i].input,
301                                         mem_golden_data[i].size),
302                                 "sdb_strbuf_memcpy() did not set the buffer correctly");
303         }
305 END_TEST
307 START_TEST(test_sdb_strbuf_memappend)
309         size_t i;
311         for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
312                 ssize_t n;
313                 const char *check;
315                 size_t total, j;
317                 n = sdb_strbuf_memappend(buf, mem_golden_data[i].input,
318                                 mem_golden_data[i].size);
319                 fail_unless(n >= 0,
320                                 "sdb_strbuf_memappend() = %zi; expected: >=0", n);
321                 fail_unless((size_t)n == mem_golden_data[i].size,
322                                 "sdb_strbuf_memappend() = %zi; expected: %zu",
323                                 n, mem_golden_data[i].size);
325                 check = sdb_strbuf_string(buf);
326                 fail_unless(check != NULL,
327                                 "sdb_strbuf_string() = NULL (after memappend); "
328                                 "expected: data");
330                 n = (ssize_t)sdb_strbuf_len(buf);
331                 total = 0;
332                 for (j = 0; j <= i; ++j) {
333                         fail_unless(total + mem_golden_data[j].size <= (size_t)n,
334                                         "sdb_strbuf_len() = %zu (after memappend); "
335                                         "expected: >=%zu", n, total + mem_golden_data[j].size);
337                         fail_unless(!memcmp(check + total, mem_golden_data[j].input,
338                                                 mem_golden_data[j].size),
339                                         "sdb_strbuf_memappend() did not "
340                                         "set the buffer correctly");
341                         total += mem_golden_data[j].size;
342                 }
343                 fail_unless((size_t)n == total,
344                                 "sdb_strbuf_len() = %zu (after memappend); expected: %zu",
345                                 n, total);
347                 fail_unless(check[total] == '\0',
348                                 "sdb_strbuf_memappend() did not nil-terminate the data");
349         }
351 END_TEST
353 static struct {
354         const char *input;
355         ssize_t expected;
356         const char *expected_string;
357 } chomp_golden_data[] = {
358         { NULL, 0, "" },
359         { "\n", 1, "" },
360         { "\n\n", 2, "" },
361         { "12345\n\n\n", 3, "12345" },
362         { "abcd", 0, "abcd" },
363 };
365 START_TEST(test_sdb_strbuf_chomp)
367         size_t i;
369         for (i = 0; i < SDB_STATIC_ARRAY_LEN(chomp_golden_data); ++i) {
370                 ssize_t n;
371                 const char *check;
373                 if (chomp_golden_data[i].input)
374                         sdb_strbuf_sprintf(buf, chomp_golden_data[i].input);
376                 /* empty buffer */
377                 n = sdb_strbuf_chomp(buf);
378                 fail_unless(n == chomp_golden_data[i].expected,
379                                 "sdb_strbuf_chomp() = %zi; expected: %zi", n,
380                                 chomp_golden_data[i].expected);
382                 check = sdb_strbuf_string(buf);
383                 fail_unless(!strcmp(check, chomp_golden_data[i].expected_string),
384                                 "sdb_strbuf_chomp() did not correctly remove newlines; "
385                                 "got string '%s'; expected: '%s'", check,
386                                 chomp_golden_data[i].expected_string);
387         }
389 END_TEST
391 /* input is "1234567890" */
392 static struct {
393         size_t offset;
394         size_t n;
395         const char *expected;
396         size_t expected_len;
397 } skip_golden_data[] = {
398         { 0, 0, "1234567890", 10 },
399         { 0, 1, "234567890", 9 },
400         { 0, 2, "34567890", 8 },
401         { 0, 9, "0", 1 },
402         { 0, 10, "", 0 },
403         { 0, 11, "", 0 },
404         { 0, 100, "", 0 },
405         { 1, 0, "1234567890", 10 },
406         { 1, 1, "134567890", 9 },
407         { 1, 2, "14567890", 8 },
408         { 8, 1, "123456780", 9 },
409         { 8, 2, "12345678", 8 },
410         { 8, 3, "12345678", 8 },
411         { 9, 1, "123456789", 9 },
412         { 9, 2, "123456789", 9 },
413         { 10, 1, "1234567890", 10 },
414         { 10, 2, "1234567890", 10 },
415 };
417 START_TEST(test_sdb_strbuf_skip)
419         const char *input = "1234567890";
420         size_t i;
422         for (i = 0; i < SDB_STATIC_ARRAY_LEN(skip_golden_data); ++i) {
423                 const char *check;
424                 size_t n;
426                 sdb_strbuf_sprintf(buf, input);
427                 sdb_strbuf_skip(buf, skip_golden_data[i].offset,
428                                 skip_golden_data[i].n);
430                 n = sdb_strbuf_len(buf);
431                 fail_unless(n == skip_golden_data[i].expected_len,
432                                 "sdb_strbuf_len() = %zu (after skip); expected: %zu",
433                                 n, skip_golden_data[i].expected_len);
435                 check = sdb_strbuf_string(buf);
436                 fail_unless(!!check,
437                                 "sdb_strbuf_string() = NULL (after skip); expected: string");
439                 fail_unless(check[n] == '\0',
440                                 "sdb_strbuf_skip() did not nil-terminate the string");
442                 fail_unless(! strcmp(skip_golden_data[i].expected, check),
443                                 "sdb_strbuf_skip('%s', %zu) did not skip correctly; "
444                                 "got string '%s'; expected: '%s'", input,
445                                 skip_golden_data[i].n, check, skip_golden_data[i].expected);
446         }
448 END_TEST
450 START_TEST(test_sdb_strbuf_clear)
452         const char *data;
453         size_t len;
455         sdb_strbuf_append(buf, "abc");
456         len = sdb_strbuf_len(buf);
457         fail_unless(len != 0,
458                         "sdb_strbuf_len() = %zu; expected: != 0", len);
460         sdb_strbuf_clear(buf);
461         len = sdb_strbuf_len(buf);
462         fail_unless(len == 0,
463                         "sdb_strbuf_len() = %zu (after clear); expected: 0", len);
465         data = sdb_strbuf_string(buf);
466         fail_unless(*data == '\0',
467                         "sdb_strbuf_string() = '%s' (after clear); expected: ''", data);
469 END_TEST
471 static struct {
472         const char *input;
473         const char *expected;
474 } string_golden_data[] = {
475         { NULL, "" },
476         { "a", "a" },
477         { "abcdef", "abcdef" },
478 };
480 START_TEST(test_sdb_strbuf_string)
482         size_t i;
484         for (i = 0; i < SDB_STATIC_ARRAY_LEN(string_golden_data); ++i) {
485                 const char *check;
487                 if (string_golden_data[i].input)
488                         sdb_strbuf_sprintf(buf, string_golden_data[i].input);
489                 check = sdb_strbuf_string(buf);
490                 fail_unless(!strcmp(check, string_golden_data[i].expected),
491                                 "sdb_strbuf_string() = '%s'; expected: '%s'",
492                                 check, string_golden_data[i].expected);
493         }
495 END_TEST
497 static struct {
498         const char *input;
499         size_t expected;
500 } len_golden_data[] = {
501         { NULL, 0 },
502         { "a", 1 },
503         { "12345", 5 },
504 };
506 START_TEST(test_sdb_strbuf_len)
508         size_t i;
510         for (i = 0; i < SDB_STATIC_ARRAY_LEN(len_golden_data); ++i) {
511                 size_t check;
513                 if (len_golden_data[i].input)
514                         sdb_strbuf_sprintf(buf, len_golden_data[i].input);
515                 check = sdb_strbuf_len(buf);
516                 fail_unless(check == len_golden_data[i].expected,
517                                 "sdb_strbuf_len() = %zu; expected: %zu",
518                                 check, len_golden_data[i].expected);
519         }
521 END_TEST
523 Suite *
524 util_strbuf_suite(void)
526         Suite *s = suite_create("utils::strbuf");
527         TCase *tc;
529         tc = tcase_create("empty");
530         tcase_add_test(tc, test_null);
531         tcase_add_test(tc, test_empty);
532         suite_add_tcase(s, tc);
534         tc = tcase_create("core");
535         tcase_add_checked_fixture(tc, setup, teardown);
536         tcase_add_test(tc, test_sdb_strbuf_create);
537         tcase_add_test(tc, test_sdb_strbuf_append);
538         tcase_add_test(tc, test_sdb_strbuf_sprintf);
539         tcase_add_test(tc, test_incremental);
540         tcase_add_test(tc, test_sdb_strbuf_memcpy);
541         tcase_add_test(tc, test_sdb_strbuf_memappend);
542         tcase_add_test(tc, test_sdb_strbuf_chomp);
543         tcase_add_test(tc, test_sdb_strbuf_skip);
544         tcase_add_test(tc, test_sdb_strbuf_clear);
545         tcase_add_test(tc, test_sdb_strbuf_string);
546         tcase_add_test(tc, test_sdb_strbuf_len);
547         suite_add_tcase(s, tc);
549         return s;
550 } /* util_strbuf_suite */
552 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */