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);
111 }
112 END_TEST
114 START_TEST(test_sdb_strbuf_append)
115 {
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);
159 }
160 END_TEST
162 START_TEST(test_sdb_strbuf_sprintf)
163 {
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);
207 }
208 END_TEST
210 START_TEST(test_incremental)
211 {
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 n = (ssize_t)sdb_strbuf_len(buf);
229 fail_unless(n == 1024, "sdb_strbuf_len() = %zi; expectd: 1024", n);
230 }
231 END_TEST
233 static struct {
234 const char *input;
235 size_t size;
236 } mem_golden_data[] = {
237 { "abc\0\x10\x42", 6 },
238 { "\0\1\2\3\4", 5 },
239 { "\n\n\0\n\n", 5 },
240 { "", 0 },
241 };
243 START_TEST(test_sdb_strbuf_memcpy)
244 {
245 size_t i;
247 for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
248 ssize_t n;
249 const char *check;
251 n = sdb_strbuf_memcpy(buf, mem_golden_data[i].input,
252 mem_golden_data[i].size);
253 fail_unless(n >= 0,
254 "sdb_strbuf_memcpy() = %zi; expected: >=0", n);
255 fail_unless((size_t)n == mem_golden_data[i].size,
256 "sdb_strbuf_memcpy() = %zi; expected: %zu",
257 n, mem_golden_data[i].size);
259 n = (ssize_t)sdb_strbuf_len(buf);
260 fail_unless((size_t)n == mem_golden_data[i].size,
261 "sdb_strbuf_len() = %zu (after memcpy); expected: %zu",
262 n, mem_golden_data[i].size);
264 check = sdb_strbuf_string(buf);
265 fail_unless(check != NULL,
266 "sdb_strbuf_string() = NULL (after memcpy); expected: data");
267 fail_unless(check[mem_golden_data[i].size] == '\0',
268 "sdb_strbuf_memcpy() did not nil-terminate the data");
269 fail_unless(!memcmp(check, mem_golden_data[i].input,
270 mem_golden_data[i].size),
271 "sdb_strbuf_memcpy() did not set the buffer correctly");
272 }
273 }
274 END_TEST
276 START_TEST(test_sdb_strbuf_memappend)
277 {
278 size_t i;
280 for (i = 0; i < SDB_STATIC_ARRAY_LEN(mem_golden_data); ++i) {
281 ssize_t n;
282 const char *check;
284 size_t total, j;
286 n = sdb_strbuf_memappend(buf, mem_golden_data[i].input,
287 mem_golden_data[i].size);
288 fail_unless(n >= 0,
289 "sdb_strbuf_memappend() = %zi; expected: >=0", n);
290 fail_unless((size_t)n == mem_golden_data[i].size,
291 "sdb_strbuf_memappend() = %zi; expected: %zu",
292 n, mem_golden_data[i].size);
294 check = sdb_strbuf_string(buf);
295 fail_unless(check != NULL,
296 "sdb_strbuf_string() = NULL (after memappend); "
297 "expected: data");
299 n = (ssize_t)sdb_strbuf_len(buf);
300 total = 0;
301 for (j = 0; j <= i; ++j) {
302 fail_unless(total + mem_golden_data[j].size <= (size_t)n,
303 "sdb_strbuf_len() = %zu (after memappend); "
304 "expected: >=%zu", n, total + mem_golden_data[j].size);
306 fail_unless(!memcmp(check + total, mem_golden_data[j].input,
307 mem_golden_data[j].size),
308 "sdb_strbuf_memappend() did not "
309 "set the buffer correctly");
310 total += mem_golden_data[j].size;
311 }
312 fail_unless((size_t)n == total,
313 "sdb_strbuf_len() = %zu (after memappend); expected: %zu",
314 n, total);
316 fail_unless(check[total] == '\0',
317 "sdb_strbuf_memappend() did not nil-terminate the data");
318 }
319 }
320 END_TEST
322 static struct {
323 const char *input;
324 ssize_t expected;
325 const char *expected_string;
326 } chomp_golden_data[] = {
327 { NULL, 0, "" },
328 { "\n", 1, "" },
329 { "\n\n", 2, "" },
330 { "12345\n\n\n", 3, "12345" },
331 { "abcd", 0, "abcd" },
332 };
334 START_TEST(test_sdb_strbuf_chomp)
335 {
336 size_t i;
338 for (i = 0; i < SDB_STATIC_ARRAY_LEN(chomp_golden_data); ++i) {
339 ssize_t n;
340 const char *check;
342 if (chomp_golden_data[i].input)
343 sdb_strbuf_sprintf(buf, chomp_golden_data[i].input);
345 /* empty buffer */
346 n = sdb_strbuf_chomp(buf);
347 fail_unless(n == chomp_golden_data[i].expected,
348 "sdb_strbuf_chomp() = %zi; expected: %zi", n,
349 chomp_golden_data[i].expected);
351 check = sdb_strbuf_string(buf);
352 fail_unless(!strcmp(check, chomp_golden_data[i].expected_string),
353 "sdb_strbuf_chomp() did not correctly remove newlines; "
354 "got string '%s'; expected: '%s'", check,
355 chomp_golden_data[i].expected_string);
356 }
357 }
358 END_TEST
360 /* input is "1234567890" */
361 static struct {
362 size_t n;
363 const char *expected;
364 size_t expected_len;
365 } skip_golden_data[] = {
366 { 0, "1234567890", 10 },
367 { 1, "234567890", 9 },
368 { 2, "34567890", 8 },
369 { 9, "0", 1 },
370 { 10, "", 0 },
371 { 11, "", 0 },
372 { 100, "", 0 },
373 };
375 START_TEST(test_sdb_strbuf_skip)
376 {
377 const char *input = "1234567890";
378 size_t i;
380 for (i = 0; i < SDB_STATIC_ARRAY_LEN(skip_golden_data); ++i) {
381 const char *check;
382 size_t n;
384 sdb_strbuf_sprintf(buf, input);
385 sdb_strbuf_skip(buf, skip_golden_data[i].n);
387 n = sdb_strbuf_len(buf);
388 fail_unless(n == skip_golden_data[i].expected_len,
389 "sdb_strbuf_len() = %zu (after skip); expected: %zu",
390 n, skip_golden_data[i].expected_len);
392 check = sdb_strbuf_string(buf);
393 fail_unless(!!check,
394 "sdb_strbuf_string() = NULL (after skip); expected: string");
396 fail_unless(check[n] == '\0',
397 "sdb_strbuf_skip() did not nil-terminate the string");
399 fail_unless(! strcmp(skip_golden_data[i].expected, check),
400 "sdb_strbuf_skip('%s', %zu) did not skip correctly; "
401 "got string '%s'; expected: '%s'", input,
402 skip_golden_data[i].n, check, skip_golden_data[i].expected);
403 }
404 }
405 END_TEST
407 static struct {
408 const char *input;
409 const char *expected;
410 } string_golden_data[] = {
411 { NULL, "" },
412 { "a", "a" },
413 { "abcdef", "abcdef" },
414 };
416 START_TEST(test_sdb_strbuf_string)
417 {
418 size_t i;
420 for (i = 0; i < SDB_STATIC_ARRAY_LEN(string_golden_data); ++i) {
421 const char *check;
423 if (string_golden_data[i].input)
424 sdb_strbuf_sprintf(buf, string_golden_data[i].input);
425 check = sdb_strbuf_string(buf);
426 fail_unless(!strcmp(check, string_golden_data[i].expected),
427 "sdb_strbuf_string() = '%s'; expected: '%s'",
428 check, string_golden_data[i].expected);
429 }
430 }
431 END_TEST
433 static struct {
434 const char *input;
435 size_t expected;
436 } len_golden_data[] = {
437 { NULL, 0 },
438 { "a", 1 },
439 { "12345", 5 },
440 };
442 START_TEST(test_sdb_strbuf_len)
443 {
444 size_t i;
446 for (i = 0; i < SDB_STATIC_ARRAY_LEN(len_golden_data); ++i) {
447 size_t check;
449 if (len_golden_data[i].input)
450 sdb_strbuf_sprintf(buf, len_golden_data[i].input);
451 check = sdb_strbuf_len(buf);
452 fail_unless(check == len_golden_data[i].expected,
453 "sdb_strbuf_len() = %zu; expected: %zu",
454 check, len_golden_data[i].expected);
455 }
456 }
457 END_TEST
459 Suite *
460 util_strbuf_suite(void)
461 {
462 Suite *s = suite_create("utils::strbuf");
463 TCase *tc;
465 tc = tcase_create("empty");
466 tcase_add_test(tc, test_empty);
467 suite_add_tcase(s, tc);
469 tc = tcase_create("core");
470 tcase_add_checked_fixture(tc, setup, teardown);
471 tcase_add_test(tc, test_sdb_strbuf_create);
472 tcase_add_test(tc, test_sdb_strbuf_append);
473 tcase_add_test(tc, test_sdb_strbuf_sprintf);
474 tcase_add_test(tc, test_incremental);
475 tcase_add_test(tc, test_sdb_strbuf_memcpy);
476 tcase_add_test(tc, test_sdb_strbuf_memappend);
477 tcase_add_test(tc, test_sdb_strbuf_chomp);
478 tcase_add_test(tc, test_sdb_strbuf_skip);
479 tcase_add_test(tc, test_sdb_strbuf_string);
480 tcase_add_test(tc, test_sdb_strbuf_len);
481 suite_add_tcase(s, tc);
483 return s;
484 } /* util_strbuf_suite */
486 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */