Code

strbuf_test: Added some more tests.
[sysdb.git] / t / unit / utils / strbuf_test.c
1 /*
2  * SysDB - t/unit/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_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_append)
140         ssize_t n;
141         size_t len, total = 0;
142         const char *test;
144         struct {
145                 const char *input;
146                 const char *result;
147         } golden_data[] = {
148                 { "1234567890", "1234567890" },
149                 { "ABCDE",      "1234567890ABCDE" },
150                 { "",           "1234567890ABCDE" },
151                 { "-",          "1234567890ABCDE-" },
152                 /* when adding anything to this array, the last check has to be
153                  * updated accordingly */
154         };
156         size_t i;
158         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
159                 n = sdb_strbuf_append(buf, golden_data[i].input);
160                 fail_unless((size_t)n == strlen(golden_data[i].input),
161                                 "sdb_strbuf_append() appended %zi bytes; expected: %zu",
162                                 n, strlen(golden_data[i].input));
163                 total += n;
164                 len = sdb_strbuf_len(buf);
165                 fail_unless(len == total,
166                                 "sdb_strbuf_append() left behind buffer with len = %zu; "
167                                 "expected: %zu", len, total);
169                 test = sdb_strbuf_string(buf);
170                 fail_unless(test[len] == '\0',
171                                 "sdb_strbuf_append() did not nil-terminate the string");
173                 test = sdb_strbuf_string(buf);
174                 fail_unless(!strcmp(test, golden_data[i].result),
175                                 "sdb_strbuf_append() did not correctly concatenate "
176                                 "the input; got: %s; expected: %s",
177                                 test, golden_data[i].result);
178         }
180         n = sdb_strbuf_append(buf, "%zu; %5.4f", 42, 4.2);
181         fail_unless(n == 10,
182                         "sdb_strbuf_append() appended %zi bytes; expected: 10", n);
183         total += n;
184         len = sdb_strbuf_len(buf);
185         fail_unless(len == total,
186                         "sdb_strbuf_append() left behind buffer with len = %zu; "
187                         "expected: %zu", len, total);
189         test = sdb_strbuf_string(buf);
190         fail_unless(test[len] == '\0',
191                         "sdb_strbuf_append() did not nil-terminate the string");
192         fail_unless(!strcmp(test, "1234567890ABCDE-42; 4.2000"),
193                         "sdb_strbuf_append() did not correctly concatenate the input; "
194                         "got: %s; expected: 1234567890ABCDE-42; 4.2000", test);
196 END_TEST
198 START_TEST(test_sprintf)
200         ssize_t n;
201         size_t len;
202         const char *test;
204         const char *golden_data[] = {
205                 "1234567890",
206                 "ABCDE",
207                 "",
208                 "-",
209         };
211         size_t i;
213         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
214                 n = sdb_strbuf_sprintf(buf, golden_data[i]);
215                 fail_unless((size_t)n == strlen(golden_data[i]),
216                                 "sdb_strbuf_sprintf() wrote %zi bytes; expected: %zu",
217                                 n, strlen(golden_data[i]));
218                 len = sdb_strbuf_len(buf);
219                 fail_unless(len == (size_t)n,
220                                 "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
221                                 "expected: %zi", len, n);
223                 test = sdb_strbuf_string(buf);
224                 fail_unless(test[len] == '\0',
225                                 "sdb_strbuf_sprintf() did not nil-terminate the string");
226                 fail_unless(!strcmp(test, golden_data[i]),
227                                 "sdb_strbuf_sprintf() did not format string correctly; "
228                                 "got: %s; expected: %s", test, golden_data[i]);
229         }
231         n = sdb_strbuf_sprintf(buf, "%zu; %5.4f", 42, 4.2);
232         fail_unless(n == 10,
233                         "sdb_strbuf_sprintf() wrote %zi bytes; expected: 10", n);
234         len = sdb_strbuf_len(buf);
235         fail_unless(len == 10,
236                         "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
237                         "expected: 10", len);
239         test = sdb_strbuf_string(buf);
240         fail_unless(test[len] == '\0',
241                         "sdb_strbuf_sprintf() did not nil-terminate the string");
242         fail_unless(!strcmp(test, "42; 4.2000"),
243                         "sdb_strbuf_sprintf() did not format string correctly; "
244                         "got: %s; expected: 42; 4.2000", test);
246 END_TEST
248 START_TEST(test_incremental)
250         const char *data;
252         ssize_t n;
253         size_t i;
255         sdb_strbuf_destroy(buf);
256         buf = sdb_strbuf_create(1024);
258         /* fill buffer one by one; leave room for nul-byte */
259         for (i = 0; i < 1023; ++i) {
260                 n = sdb_strbuf_append(buf, ".");
261                 fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
262         }
264         /* write another byte; this has to trigger a resize */
265         n = sdb_strbuf_append(buf, ".");
266         fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
268         /* write more bytes; this should trigger at least one more resize but
269          * that's an implementation detail */
270         for (i = 0; i < 1024; ++i) {
271                 n = sdb_strbuf_append(buf, ".");
272                 fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
273         }
275         n = (ssize_t)sdb_strbuf_len(buf);
276         fail_unless(n == 2048, "sdb_strbuf_len() = %zi; expectd: 2048", n);
278         data = sdb_strbuf_string(buf);
279         for (i = 0; i < 2048; ++i)
280                 fail_unless(data[i] == '.',
281                                 "After sdb_strbuf_append(), found character %x "
282                                 "at position %zi; expected %x (.)",
283                                 (int)data[i], i, '.');
284         fail_unless(data[i] == '\0',
285                         "After sdb_strbuf_append(), found character %x at end of string; "
286                         "expected '\\0'", (int)data[i]);
288 END_TEST
290 /* used by test_memcpy and test_memappend */
291 static struct {
292         const char *input;
293         size_t size;
294 } mem_golden_data[] = {
295         { "abc\0\x10\x42", 6 },
296         { "\0\1\2\3\4", 5 },
297         { "\n\n\0\n\n", 5 },
298         { "", 0 },
299 };
301 START_TEST(test_memcpy)
303         size_t i;
305         for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
306                 ssize_t n;
307                 const char *check;
309                 n = sdb_strbuf_memcpy(buf, mem_golden_data[i].input,
310                                 mem_golden_data[i].size);
311                 fail_unless(n >= 0,
312                                 "sdb_strbuf_memcpy() = %zi; expected: >=0", n);
313                 fail_unless((size_t)n == mem_golden_data[i].size,
314                                 "sdb_strbuf_memcpy() = %zi; expected: %zu",
315                                 n, mem_golden_data[i].size);
317                 n = (ssize_t)sdb_strbuf_len(buf);
318                 fail_unless((size_t)n == mem_golden_data[i].size,
319                                 "sdb_strbuf_len() = %zu (after memcpy); expected: %zu",
320                                 n, mem_golden_data[i].size);
322                 check = sdb_strbuf_string(buf);
323                 fail_unless(check != NULL,
324                                 "sdb_strbuf_string() = NULL (after memcpy); expected: data");
325                 fail_unless(check[mem_golden_data[i].size] == '\0',
326                                 "sdb_strbuf_memcpy() did not nil-terminate the data");
327                 fail_unless(!memcmp(check, mem_golden_data[i].input,
328                                         mem_golden_data[i].size),
329                                 "sdb_strbuf_memcpy() did not set the buffer correctly");
330         }
332 END_TEST
334 START_TEST(test_memappend)
336         size_t i;
338         for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
339                 ssize_t n;
340                 const char *check;
342                 size_t total, j;
344                 n = sdb_strbuf_memappend(buf, mem_golden_data[i].input,
345                                 mem_golden_data[i].size);
346                 fail_unless(n >= 0,
347                                 "sdb_strbuf_memappend() = %zi; expected: >=0", n);
348                 fail_unless((size_t)n == mem_golden_data[i].size,
349                                 "sdb_strbuf_memappend() = %zi; expected: %zu",
350                                 n, mem_golden_data[i].size);
352                 check = sdb_strbuf_string(buf);
353                 fail_unless(check != NULL,
354                                 "sdb_strbuf_string() = NULL (after memappend); "
355                                 "expected: data");
357                 n = (ssize_t)sdb_strbuf_len(buf);
358                 total = 0;
359                 for (j = 0; j <= i; ++j) {
360                         fail_unless(total + mem_golden_data[j].size <= (size_t)n,
361                                         "sdb_strbuf_len() = %zu (after memappend); "
362                                         "expected: >=%zu", n, total + mem_golden_data[j].size);
364                         fail_unless(!memcmp(check + total, mem_golden_data[j].input,
365                                                 mem_golden_data[j].size),
366                                         "sdb_strbuf_memappend() did not "
367                                         "set the buffer correctly");
368                         total += mem_golden_data[j].size;
369                 }
370                 fail_unless((size_t)n == total,
371                                 "sdb_strbuf_len() = %zu (after memappend); expected: %zu",
372                                 n, total);
374                 fail_unless(check[total] == '\0',
375                                 "sdb_strbuf_memappend() did not nil-terminate the data");
376         }
378 END_TEST
380 START_TEST(test_chomp)
382         struct {
383                 const char *input;
384                 ssize_t expected;
385                 const char *expected_string;
386         } golden_data[] = {
387                 { NULL, 0, "" },
388                 { "\n", 1, "" },
389                 { "\n\n", 2, "" },
390                 { "12345\n\n\n", 3, "12345" },
391                 { "abcd", 0, "abcd" },
392         };
394         size_t i;
396         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
397                 ssize_t n;
398                 const char *check;
400                 if (golden_data[i].input)
401                         sdb_strbuf_sprintf(buf, golden_data[i].input);
403                 /* empty buffer */
404                 n = sdb_strbuf_chomp(buf);
405                 fail_unless(n == golden_data[i].expected,
406                                 "sdb_strbuf_chomp() = %zi; expected: %zi", n,
407                                 golden_data[i].expected);
409                 check = sdb_strbuf_string(buf);
410                 fail_unless(!strcmp(check, golden_data[i].expected_string),
411                                 "sdb_strbuf_chomp() did not correctly remove newlines; "
412                                 "got string '%s'; expected: '%s'", check,
413                                 golden_data[i].expected_string);
414         }
416 END_TEST
418 START_TEST(test_skip)
420         const char *input = "1234567890";
421         struct {
422                 size_t offset;
423                 size_t n;
424                 const char *expected;
425                 size_t expected_len;
426         } golden_data[] = {
427                 { 0, 0, "1234567890", 10 },
428                 { 0, 1, "234567890", 9 },
429                 { 0, 2, "34567890", 8 },
430                 { 0, 9, "0", 1 },
431                 { 0, 10, "", 0 },
432                 { 0, 11, "", 0 },
433                 { 0, 100, "", 0 },
434                 { 1, 0, "1234567890", 10 },
435                 { 1, 1, "134567890", 9 },
436                 { 1, 2, "14567890", 8 },
437                 { 2, 0, "1234567890", 10 },
438                 { 2, 1, "124567890", 9 },
439                 { 2, 2, "12567890", 8 },
440                 { 2, 3, "1267890", 7 },
441                 { 2, 4, "127890", 6 },
442                 { 2, 5, "12890", 5 },
443                 { 2, 6, "1290", 4 },
444                 { 2, 7, "120", 3 },
445                 { 2, 8, "12", 2 },
446                 { 2, 9, "12", 2 },
447                 { 2, 10, "12", 2 },
448                 { 8, 1, "123456780", 9 },
449                 { 8, 2, "12345678", 8 },
450                 { 8, 3, "12345678", 8 },
451                 { 9, 1, "123456789", 9 },
452                 { 9, 2, "123456789", 9 },
453                 { 10, 1, "1234567890", 10 },
454                 { 10, 2, "1234567890", 10 },
455         };
457         size_t i;
459         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
460                 const char *check;
461                 size_t n;
463                 sdb_strbuf_sprintf(buf, input);
464                 sdb_strbuf_skip(buf, golden_data[i].offset,
465                                 golden_data[i].n);
467                 n = sdb_strbuf_len(buf);
468                 fail_unless(n == golden_data[i].expected_len,
469                                 "sdb_strbuf_len() = %zu (after skip); expected: %zu",
470                                 n, golden_data[i].expected_len);
472                 check = sdb_strbuf_string(buf);
473                 fail_unless(!!check,
474                                 "sdb_strbuf_string() = NULL (after skip); expected: string");
476                 fail_unless(check[n] == '\0',
477                                 "sdb_strbuf_skip() did not nil-terminate the string");
479                 fail_unless(! strcmp(golden_data[i].expected, check),
480                                 "sdb_strbuf_skip('%s', %zu) did not skip correctly; "
481                                 "got string '%s'; expected: '%s'", input,
482                                 golden_data[i].n, check, golden_data[i].expected);
483         }
485 END_TEST
487 START_TEST(test_clear)
489         const char *data;
490         size_t len;
492         sdb_strbuf_append(buf, "abc");
493         len = sdb_strbuf_len(buf);
494         fail_unless(len != 0,
495                         "sdb_strbuf_len() = %zu; expected: != 0", len);
497         sdb_strbuf_clear(buf);
498         len = sdb_strbuf_len(buf);
499         fail_unless(len == 0,
500                         "sdb_strbuf_len() = %zu (after clear); expected: 0", len);
502         data = sdb_strbuf_string(buf);
503         fail_unless(*data == '\0',
504                         "sdb_strbuf_string() = '%s' (after clear); expected: ''", data);
506 END_TEST
508 START_TEST(test_string)
510         struct {
511                 const char *input;
512                 const char *expected;
513         } golden_data[] = {
514                 { NULL, "" },
515                 { "a", "a" },
516                 { "abcdef", "abcdef" },
517         };
519         size_t i;
521         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
522                 const char *check;
524                 if (golden_data[i].input)
525                         sdb_strbuf_sprintf(buf, golden_data[i].input);
526                 check = sdb_strbuf_string(buf);
527                 fail_unless(!strcmp(check, golden_data[i].expected),
528                                 "sdb_strbuf_string() = '%s'; expected: '%s'",
529                                 check, golden_data[i].expected);
530         }
532 END_TEST
534 START_TEST(test_len)
536         struct {
537                 const char *input;
538                 size_t expected;
539         } golden_data[] = {
540                 { NULL, 0 },
541                 { "a", 1 },
542                 { "12345", 5 },
543         };
545         size_t i;
547         for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
548                 size_t check;
550                 if (golden_data[i].input)
551                         sdb_strbuf_sprintf(buf, golden_data[i].input);
552                 check = sdb_strbuf_len(buf);
553                 fail_unless(check == golden_data[i].expected,
554                                 "sdb_strbuf_len() = %zu; expected: %zu",
555                                 check, golden_data[i].expected);
556         }
558 END_TEST
560 Suite *
561 util_strbuf_suite(void)
563         Suite *s = suite_create("utils::strbuf");
564         TCase *tc;
566         tc = tcase_create("empty");
567         tcase_add_test(tc, test_null);
568         tcase_add_test(tc, test_empty);
569         suite_add_tcase(s, tc);
571         tc = tcase_create("core");
572         tcase_add_checked_fixture(tc, setup, teardown);
573         tcase_add_test(tc, test_create);
574         tcase_add_test(tc, test_append);
575         tcase_add_test(tc, test_sprintf);
576         tcase_add_test(tc, test_incremental);
577         tcase_add_test(tc, test_memcpy);
578         tcase_add_test(tc, test_memappend);
579         tcase_add_test(tc, test_chomp);
580         tcase_add_test(tc, test_skip);
581         tcase_add_test(tc, test_clear);
582         tcase_add_test(tc, test_string);
583         tcase_add_test(tc, test_len);
584         suite_add_tcase(s, tc);
586         return s;
587 } /* util_strbuf_suite */
589 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */