Code

strbuf test: Further extended the incremental append test.
[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_empty)
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);
66         sdb_strbuf_skip(b, 10);
68         /* check that methods return an error */
69         fail_unless(sdb_strbuf_vappend(b, "test", ap) < 0,
70                         "sdb_strbuf_vappend(NULL) didn't report failure");
71         fail_unless(sdb_strbuf_append(b, "test") < 0,
72                         "sdb_strbuf_append(NULL) didn't report failure");
73         fail_unless(sdb_strbuf_vsprintf(b, "test", ap) < 0,
74                         "sdb_strbuf_vsprintf(NULL) didn't report failure");
75         fail_unless(sdb_strbuf_sprintf(b, "test") < 0,
76                         "sdb_strbuf_sprintf(NULL) didn't report failure");
77         fail_unless(sdb_strbuf_memcpy(b, "test", 4) < 0,
78                         "sdb_strbuf_memcpy(NULL) didn't report failure");
79         fail_unless(sdb_strbuf_memappend(b, "test", 4) < 0,
80                         "sdb_strbuf_memappend(NULL) didn't report failure");
81         fail_unless(sdb_strbuf_read(b, 0, 32) < 0,
82                         "sdb_strbuf_read(NULL) didn't report failure");
83         fail_unless(sdb_strbuf_chomp(b) < 0,
84                         "sdb_strbuf_chomp(NULL) didn't report failure");
85 }
86 END_TEST
88 START_TEST(test_sdb_strbuf_create)
89 {
90         sdb_strbuf_t *s;
91         size_t len;
93         s = sdb_strbuf_create(0);
94         fail_unless(s != NULL,
95                         "sdb_strbuf_create() = NULL; expected strbuf object");
96         len = sdb_strbuf_len(s);
97         fail_unless(len == 0,
98                         "sdb_strbuf_create() created buffer with len = %zu; "
99                         "expected: 0", len);
100         sdb_strbuf_destroy(s);
102         s = sdb_strbuf_create(128);
103         fail_unless(s != NULL,
104                         "sdb_strbuf_create() = NULL; expected strbuf object");
105         len = sdb_strbuf_len(s);
106         /* len still has to be 0 -- there's no content */
107         fail_unless(len == 0,
108                         "sdb_strbuf_create() created buffer with len = %zu; "
109                         "expected: 0", len);
110         sdb_strbuf_destroy(s);
112 END_TEST
114 START_TEST(test_sdb_strbuf_append)
116         ssize_t n, expected;
117         size_t len;
118         const char *test;
120         n = sdb_strbuf_append(buf, "1234567890");
121         fail_unless(n == 10,
122                         "sdb_strbuf_append() appended %zi bytes; expected: 10", n);
123         len = sdb_strbuf_len(buf);
124         fail_unless(len == 10,
125                         "sdb_strbuf_append() left behind buffer with len = %zu; "
126                         "expected: 10", len);
128         n = sdb_strbuf_append(buf, "ABCDE");
129         fail_unless(n == 5,
130                         "sdb_strbuf_append() appended %zi bytes; expected: 5", n);
131         len = sdb_strbuf_len(buf);
132         fail_unless(len == 15,
133                         "sdb_strbuf_append() left behind buffer with len = %zu; "
134                         "expected: 15", len);
136         test = sdb_strbuf_string(buf);
137         fail_unless(test[len] == '\0',
138                         "sdb_strbuf_append() did not nil-terminate the string");
139         fail_unless(!strcmp(test, "1234567890ABCDE"),
140                         "sdb_strbuf_append() did not correctly concatenate two string; "
141                         "got: %s; expected: 1234567890ABCDE", test);
143         n = sdb_strbuf_append(buf, "%zu; %5.4f", len, (double)len / 10.0);
144         expected = /* len */ 2 + /* "; " */ 2 + /* decimal len/10 */ 6;
145         fail_unless(n == expected,
146                         "sdb_strbuf_append() appended %zi bytes; expected: %zi",
147                         n, expected);
148         len = sdb_strbuf_len(buf);
149         fail_unless(len == 15 + (size_t)expected,
150                         "sdb_strbuf_append() left behind buffer with len = %zu; "
151                         "expected: %zu", len, 15 + (size_t)expected);
153         test = sdb_strbuf_string(buf);
154         fail_unless(test[len] == '\0',
155                         "sdb_strbuf_append() did not nil-terminate the string");
156         fail_unless(!strcmp(test, "1234567890ABCDE15; 1.5000"),
157                         "sdb_strbuf_append() did not correctly concatenate two string; "
158                         "got: %s; expected: 1234567890ABCDE15; 1.5000", test);
160 END_TEST
162 START_TEST(test_sdb_strbuf_sprintf)
164         ssize_t n, expected;
165         size_t len;
166         const char *test;
168         n = sdb_strbuf_sprintf(buf, "1234567890");
169         fail_unless(n == 10,
170                         "sdb_strbuf_sprintf() wrote %zi bytes; expected: 10", n);
171         len = sdb_strbuf_len(buf);
172         fail_unless(len == 10,
173                         "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
174                         "expected: 10", len);
176         n = sdb_strbuf_sprintf(buf, "ABCDE");
177         fail_unless(n == 5,
178                         "sdb_strbuf_sprintf() wrote %zi bytes; expected: 5", n);
179         len = sdb_strbuf_len(buf);
180         fail_unless(len == 5,
181                         "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
182                         "expected: 5", len);
184         test = sdb_strbuf_string(buf);
185         fail_unless(test[len] == '\0',
186                         "sdb_strbuf_sprintf() did not nil-terminate the string");
187         fail_unless(!strcmp(test, "ABCDE"),
188                         "sdb_strbuf_sprintf() did not format string correctly; "
189                         "got: %s; expected: ABCDE", test);
191         n = sdb_strbuf_sprintf(buf, "%zu; %5.4f", len, (double)len / 10.0);
192         expected = /* len */ 1 + /* "; " */ 2 + /* decimal len/10 */ 6;
193         fail_unless(n == expected,
194                         "sdb_strbuf_sprintf() wrote %zi bytes; expected: %zi",
195                         n, expected);
196         len = sdb_strbuf_len(buf);
197         fail_unless(len == (size_t)expected,
198                         "sdb_strbuf_sprintf() left behind buffer with len = %zu; "
199                         "expected: %zu", len, (size_t)expected);
201         test = sdb_strbuf_string(buf);
202         fail_unless(test[len] == '\0',
203                         "sdb_strbuf_sprintf() did not nil-terminate the string");
204         fail_unless(!strcmp(test, "5; 0.5000"),
205                         "sdb_strbuf_sprintf() did not format string correctly; "
206                         "got: %s; expected: 5; 0.5000", test);
208 END_TEST
210 START_TEST(test_incremental)
212         ssize_t n;
213         size_t i;
215         sdb_strbuf_destroy(buf);
216         buf = sdb_strbuf_create(1024);
218         /* fill buffer one by one; leave room for nul-byte */
219         for (i = 0; i < 1023; ++i) {
220                 n = sdb_strbuf_append(buf, ".");
221                 fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
222         }
224         /* write another byte; this has to trigger a resize */
225         n = sdb_strbuf_append(buf, ".");
226         fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
228         /* write more bytes; this should trigger at least one more resize but
229          * that's an implementation detail */
230         for (i = 0; i < 1024; ++i) {
231                 n = sdb_strbuf_append(buf, ".");
232                 fail_unless(n == 1, "sdb_strbuf_append() = %zi; expected: 1", n);
233         }
235         n = (ssize_t)sdb_strbuf_len(buf);
236         fail_unless(n == 2048, "sdb_strbuf_len() = %zi; expectd: 2048", n);
238 END_TEST
240 static struct {
241         const char *input;
242         size_t size;
243 } mem_golden_data[] = {
244         { "abc\0\x10\x42", 6 },
245         { "\0\1\2\3\4", 5 },
246         { "\n\n\0\n\n", 5 },
247         { "", 0 },
248 };
250 START_TEST(test_sdb_strbuf_memcpy)
252         size_t i;
254         for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
255                 ssize_t n;
256                 const char *check;
258                 n = sdb_strbuf_memcpy(buf, mem_golden_data[i].input,
259                                 mem_golden_data[i].size);
260                 fail_unless(n >= 0,
261                                 "sdb_strbuf_memcpy() = %zi; expected: >=0", n);
262                 fail_unless((size_t)n == mem_golden_data[i].size,
263                                 "sdb_strbuf_memcpy() = %zi; expected: %zu",
264                                 n, mem_golden_data[i].size);
266                 n = (ssize_t)sdb_strbuf_len(buf);
267                 fail_unless((size_t)n == mem_golden_data[i].size,
268                                 "sdb_strbuf_len() = %zu (after memcpy); expected: %zu",
269                                 n, mem_golden_data[i].size);
271                 check = sdb_strbuf_string(buf);
272                 fail_unless(check != NULL,
273                                 "sdb_strbuf_string() = NULL (after memcpy); expected: data");
274                 fail_unless(check[mem_golden_data[i].size] == '\0',
275                                 "sdb_strbuf_memcpy() did not nil-terminate the data");
276                 fail_unless(!memcmp(check, mem_golden_data[i].input,
277                                         mem_golden_data[i].size),
278                                 "sdb_strbuf_memcpy() did not set the buffer correctly");
279         }
281 END_TEST
283 START_TEST(test_sdb_strbuf_memappend)
285         size_t i;
287         for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
288                 ssize_t n;
289                 const char *check;
291                 size_t total, j;
293                 n = sdb_strbuf_memappend(buf, mem_golden_data[i].input,
294                                 mem_golden_data[i].size);
295                 fail_unless(n >= 0,
296                                 "sdb_strbuf_memappend() = %zi; expected: >=0", n);
297                 fail_unless((size_t)n == mem_golden_data[i].size,
298                                 "sdb_strbuf_memappend() = %zi; expected: %zu",
299                                 n, mem_golden_data[i].size);
301                 check = sdb_strbuf_string(buf);
302                 fail_unless(check != NULL,
303                                 "sdb_strbuf_string() = NULL (after memappend); "
304                                 "expected: data");
306                 n = (ssize_t)sdb_strbuf_len(buf);
307                 total = 0;
308                 for (j = 0; j <= i; ++j) {
309                         fail_unless(total + mem_golden_data[j].size <= (size_t)n,
310                                         "sdb_strbuf_len() = %zu (after memappend); "
311                                         "expected: >=%zu", n, total + mem_golden_data[j].size);
313                         fail_unless(!memcmp(check + total, mem_golden_data[j].input,
314                                                 mem_golden_data[j].size),
315                                         "sdb_strbuf_memappend() did not "
316                                         "set the buffer correctly");
317                         total += mem_golden_data[j].size;
318                 }
319                 fail_unless((size_t)n == total,
320                                 "sdb_strbuf_len() = %zu (after memappend); expected: %zu",
321                                 n, total);
323                 fail_unless(check[total] == '\0',
324                                 "sdb_strbuf_memappend() did not nil-terminate the data");
325         }
327 END_TEST
329 static struct {
330         const char *input;
331         ssize_t expected;
332         const char *expected_string;
333 } chomp_golden_data[] = {
334         { NULL, 0, "" },
335         { "\n", 1, "" },
336         { "\n\n", 2, "" },
337         { "12345\n\n\n", 3, "12345" },
338         { "abcd", 0, "abcd" },
339 };
341 START_TEST(test_sdb_strbuf_chomp)
343         size_t i;
345         for (i = 0; i < SDB_STATIC_ARRAY_LEN(chomp_golden_data); ++i) {
346                 ssize_t n;
347                 const char *check;
349                 if (chomp_golden_data[i].input)
350                         sdb_strbuf_sprintf(buf, chomp_golden_data[i].input);
352                 /* empty buffer */
353                 n = sdb_strbuf_chomp(buf);
354                 fail_unless(n == chomp_golden_data[i].expected,
355                                 "sdb_strbuf_chomp() = %zi; expected: %zi", n,
356                                 chomp_golden_data[i].expected);
358                 check = sdb_strbuf_string(buf);
359                 fail_unless(!strcmp(check, chomp_golden_data[i].expected_string),
360                                 "sdb_strbuf_chomp() did not correctly remove newlines; "
361                                 "got string '%s'; expected: '%s'", check,
362                                 chomp_golden_data[i].expected_string);
363         }
365 END_TEST
367 /* input is "1234567890" */
368 static struct {
369         size_t n;
370         const char *expected;
371         size_t expected_len;
372 } skip_golden_data[] = {
373         { 0, "1234567890", 10 },
374         { 1, "234567890", 9 },
375         { 2, "34567890", 8 },
376         { 9, "0", 1 },
377         { 10, "", 0 },
378         { 11, "", 0 },
379         { 100, "", 0 },
380 };
382 START_TEST(test_sdb_strbuf_skip)
384         const char *input = "1234567890";
385         size_t i;
387         for (i = 0; i < SDB_STATIC_ARRAY_LEN(skip_golden_data); ++i) {
388                 const char *check;
389                 size_t n;
391                 sdb_strbuf_sprintf(buf, input);
392                 sdb_strbuf_skip(buf, skip_golden_data[i].n);
394                 n = sdb_strbuf_len(buf);
395                 fail_unless(n == skip_golden_data[i].expected_len,
396                                 "sdb_strbuf_len() = %zu (after skip); expected: %zu",
397                                 n, skip_golden_data[i].expected_len);
399                 check = sdb_strbuf_string(buf);
400                 fail_unless(!!check,
401                                 "sdb_strbuf_string() = NULL (after skip); expected: string");
403                 fail_unless(check[n] == '\0',
404                                 "sdb_strbuf_skip() did not nil-terminate the string");
406                 fail_unless(! strcmp(skip_golden_data[i].expected, check),
407                                 "sdb_strbuf_skip('%s', %zu) did not skip correctly; "
408                                 "got string '%s'; expected: '%s'", input,
409                                 skip_golden_data[i].n, check, skip_golden_data[i].expected);
410         }
412 END_TEST
414 static struct {
415         const char *input;
416         const char *expected;
417 } string_golden_data[] = {
418         { NULL, "" },
419         { "a", "a" },
420         { "abcdef", "abcdef" },
421 };
423 START_TEST(test_sdb_strbuf_string)
425         size_t i;
427         for (i = 0; i < SDB_STATIC_ARRAY_LEN(string_golden_data); ++i) {
428                 const char *check;
430                 if (string_golden_data[i].input)
431                         sdb_strbuf_sprintf(buf, string_golden_data[i].input);
432                 check = sdb_strbuf_string(buf);
433                 fail_unless(!strcmp(check, string_golden_data[i].expected),
434                                 "sdb_strbuf_string() = '%s'; expected: '%s'",
435                                 check, string_golden_data[i].expected);
436         }
438 END_TEST
440 static struct {
441         const char *input;
442         size_t expected;
443 } len_golden_data[] = {
444         { NULL, 0 },
445         { "a", 1 },
446         { "12345", 5 },
447 };
449 START_TEST(test_sdb_strbuf_len)
451         size_t i;
453         for (i = 0; i < SDB_STATIC_ARRAY_LEN(len_golden_data); ++i) {
454                 size_t check;
456                 if (len_golden_data[i].input)
457                         sdb_strbuf_sprintf(buf, len_golden_data[i].input);
458                 check = sdb_strbuf_len(buf);
459                 fail_unless(check == len_golden_data[i].expected,
460                                 "sdb_strbuf_len() = %zu; expected: %zu",
461                                 check, len_golden_data[i].expected);
462         }
464 END_TEST
466 Suite *
467 util_strbuf_suite(void)
469         Suite *s = suite_create("utils::strbuf");
470         TCase *tc;
472         tc = tcase_create("empty");
473         tcase_add_test(tc, test_empty);
474         suite_add_tcase(s, tc);
476         tc = tcase_create("core");
477         tcase_add_checked_fixture(tc, setup, teardown);
478         tcase_add_test(tc, test_sdb_strbuf_create);
479         tcase_add_test(tc, test_sdb_strbuf_append);
480         tcase_add_test(tc, test_sdb_strbuf_sprintf);
481         tcase_add_test(tc, test_incremental);
482         tcase_add_test(tc, test_sdb_strbuf_memcpy);
483         tcase_add_test(tc, test_sdb_strbuf_memappend);
484         tcase_add_test(tc, test_sdb_strbuf_chomp);
485         tcase_add_test(tc, test_sdb_strbuf_skip);
486         tcase_add_test(tc, test_sdb_strbuf_string);
487         tcase_add_test(tc, test_sdb_strbuf_len);
488         suite_add_tcase(s, tc);
490         return s;
491 } /* util_strbuf_suite */
493 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */