2 * Copyright (c) 2021 SUSE LLC
3 * SPDX-License-Identifier: GPL-2.0-only
18 void *__real_realloc(void *ptr, size_t size);
20 static bool mock_realloc = false;
21 void *__wrap_realloc(void *ptr, size_t size)
25 return __real_realloc(ptr, size);
27 p = mock_ptr_type(void *);
28 condlog(4, "%s: %p, %zu -> %p", __func__, ptr, size, p);
32 static void test_strbuf_00(void **state)
37 assert_ptr_equal(buf.buf, NULL);
38 assert_int_equal(buf.size, 0);
39 assert_int_equal(buf.offs, 0);
40 assert_int_equal(get_strbuf_len(&buf), 0);
41 assert_string_equal(get_strbuf_str(&buf), "");
42 p = steal_strbuf_str(&buf);
43 assert_ptr_equal(p, NULL);
45 assert_ptr_equal(buf.buf, NULL);
46 assert_int_equal(buf.size, 0);
47 assert_int_equal(buf.offs, 0);
48 assert_int_equal(get_strbuf_len(&buf), 0);
49 assert_string_equal(get_strbuf_str(&buf), "");
51 assert_int_equal(append_strbuf_str(&buf, "moin"), 4);
52 assert_int_equal(get_strbuf_len(&buf), 4);
53 assert_in_range(buf.size, 5, SIZE_MAX);
54 assert_string_equal(get_strbuf_str(&buf), "moin");
55 p = steal_strbuf_str(&buf);
56 assert_string_equal(p, "moin");
59 assert_ptr_equal(buf.buf, NULL);
60 assert_int_equal(buf.size, 0);
61 assert_int_equal(buf.offs, 0);
62 assert_int_equal(get_strbuf_len(&buf), 0);
63 assert_string_equal(get_strbuf_str(&buf), "");
65 assert_int_equal(append_strbuf_str(&buf, NULL), -EINVAL);
66 assert_int_equal(buf.size, 0);
67 assert_int_equal(buf.offs, 0);
68 assert_int_equal(get_strbuf_len(&buf), 0);
69 assert_string_equal(get_strbuf_str(&buf), "");
71 assert_int_equal(append_strbuf_str(&buf, ""), 0);
72 /* appending a 0-length string allocates memory */
73 assert_in_range(buf.size, 1, SIZE_MAX);
74 assert_int_equal(buf.offs, 0);
75 assert_int_equal(get_strbuf_len(&buf), 0);
76 assert_string_equal(get_strbuf_str(&buf), "");
77 p = steal_strbuf_str(&buf);
78 assert_string_equal(p, "");
81 assert_int_equal(__append_strbuf_str(&buf, "x", 0), 0);
82 /* appending a 0-length string allocates memory */
83 assert_in_range(buf.size, 1, SIZE_MAX);
84 assert_int_equal(buf.offs, 0);
85 assert_int_equal(get_strbuf_len(&buf), 0);
86 assert_string_equal(get_strbuf_str(&buf), "");
89 static void test_strbuf_alloc_err(void **state)
96 will_return(__wrap_realloc, NULL);
97 assert_int_equal(append_strbuf_str(&buf, "moin"), -ENOMEM);
98 assert_int_equal(buf.size, 0);
99 assert_int_equal(buf.offs, 0);
100 assert_int_equal(get_strbuf_len(&buf), 0);
101 assert_string_equal(get_strbuf_str(&buf), "");
103 mock_realloc = false;
104 assert_int_equal(append_strbuf_str(&buf, "moin"), 4);
106 assert_in_range(sz, 5, SIZE_MAX);
107 assert_int_equal(buf.offs, 4);
108 assert_int_equal(get_strbuf_len(&buf), 4);
109 assert_string_equal(get_strbuf_str(&buf), "moin");
112 will_return(__wrap_realloc, NULL);
113 ofs = get_strbuf_len(&buf);
114 while ((rc = append_strbuf_str(&buf, " hello")) >= 0) {
115 condlog(3, "%s", get_strbuf_str(&buf));
116 assert_int_equal(rc, 6);
117 assert_int_equal(get_strbuf_len(&buf), ofs + 6);
118 assert_memory_equal(get_strbuf_str(&buf), "moin", 4);
119 assert_string_equal(get_strbuf_str(&buf) + ofs, " hello");
120 ofs = get_strbuf_len(&buf);
122 assert_int_equal(rc, -ENOMEM);
123 assert_int_equal(buf.size, sz);
124 assert_int_equal(get_strbuf_len(&buf), ofs);
125 assert_memory_equal(get_strbuf_str(&buf), "moin", 4);
126 assert_string_equal(get_strbuf_str(&buf) + ofs - 6, " hello");
129 assert_ptr_equal(buf.buf, NULL);
130 assert_int_equal(buf.size, 0);
131 assert_int_equal(buf.offs, 0);
132 assert_int_equal(get_strbuf_len(&buf), 0);
133 assert_string_equal(get_strbuf_str(&buf), "");
135 mock_realloc = false;
138 static void test_strbuf_overflow(void **state)
140 STRBUF_ON_STACK(buf);
142 assert_int_equal(append_strbuf_str(&buf, "x"), 1);
143 /* fake huge buffer */
144 buf.size = SIZE_MAX - 1;
145 buf.offs = buf.size - 1;
146 assert_int_equal(append_strbuf_str(&buf, "x"), -EOVERFLOW);
149 static void test_strbuf_big(void **state)
151 STRBUF_ON_STACK(buf);
152 const char big[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n";
156 /* Under valgrind, 30000 iterations need ca. 30s on my laptop */
157 for (i = 0; i < 30000; i++) {
160 assert_int_equal(append_strbuf_str(&buf, big), sizeof(big) - 1);
161 assert_int_equal(get_strbuf_len(&buf), (sizeof(big) - 1) * (i + 1));
162 assert_memory_equal(get_strbuf_str(&buf), big, sizeof(big) - 1);
163 assert_string_equal(get_strbuf_str(&buf) + get_strbuf_len(&buf)
164 - (sizeof(big) - 1), big);
166 bbig = steal_strbuf_str(&buf);
168 assert_ptr_equal(buf.buf, NULL);
169 assert_int_equal(buf.size, 0);
170 assert_int_equal(buf.offs, 0);
171 assert_int_equal(get_strbuf_len(&buf), 0);
172 assert_string_equal(get_strbuf_str(&buf), "");
174 assert_int_equal(strlen(bbig), i * (sizeof(big) - 1));
175 assert_memory_equal(bbig, big, sizeof(big) - 1);
179 static void test_strbuf_nul(void **state)
181 STRBUF_ON_STACK(buf);
182 char greet[] = "hello, sir!";
184 assert_int_equal(__append_strbuf_str(&buf, greet, 6), 6);
185 assert_string_equal(get_strbuf_str(&buf), "hello,");
186 assert_int_equal(__append_strbuf_str(&buf, greet, 6), 6);
187 assert_string_equal(get_strbuf_str(&buf), "hello,hello,");
189 /* overwrite comma with NUL; append_strbuf_str() stops at NUL byte */
192 assert_int_equal(append_strbuf_str(&buf, greet), 5);
193 assert_int_equal(get_strbuf_len(&buf), 5);
194 assert_string_equal(get_strbuf_str(&buf), "hello");
195 assert_int_equal(append_strbuf_str(&buf, greet), 5);
196 assert_int_equal(get_strbuf_len(&buf), 10);
197 assert_string_equal(get_strbuf_str(&buf), "hellohello");
199 /* __append_strbuf_str() appends full memory, including NUL bytes */
201 assert_int_equal(__append_strbuf_str(&buf, greet, sizeof(greet) - 1),
203 assert_int_equal(get_strbuf_len(&buf), sizeof(greet) - 1);
204 assert_string_equal(get_strbuf_str(&buf), "hello");
205 assert_string_equal(get_strbuf_str(&buf) + get_strbuf_len(&buf) - 5, " sir!");
206 assert_int_equal(__append_strbuf_str(&buf, greet, sizeof(greet) - 1),
208 assert_string_equal(get_strbuf_str(&buf), "hello");
209 assert_int_equal(get_strbuf_len(&buf), 2 * (sizeof(greet) - 1));
210 assert_string_equal(get_strbuf_str(&buf) + get_strbuf_len(&buf) - 5, " sir!");
213 static void test_strbuf_quoted(void **state)
215 STRBUF_ON_STACK(buf);
216 const char said[] = "She said ";
217 const char greet[] = "hi, man!";
221 assert_int_equal(append_strbuf_str(&buf, said), sizeof(said) - 1);
222 assert_int_equal(append_strbuf_quoted(&buf, greet), sizeof(greet) + 1);
223 assert_string_equal(get_strbuf_str(&buf), "She said \"hi, man!\"");
224 n = get_strbuf_len(&buf);
225 p = steal_strbuf_str(&buf);
226 assert_int_equal(append_strbuf_str(&buf, said), sizeof(said) - 1);
227 assert_int_equal(append_strbuf_quoted(&buf, p), n + 4);
228 assert_string_equal(get_strbuf_str(&buf),
229 "She said \"She said \"\"hi, man!\"\"\"");
231 n = get_strbuf_len(&buf);
232 p = steal_strbuf_str(&buf);
233 assert_int_equal(append_strbuf_str(&buf, said), sizeof(said) - 1);
234 assert_int_equal(append_strbuf_quoted(&buf, p), n + 8);
235 assert_string_equal(get_strbuf_str(&buf),
236 "She said \"She said \"\"She said \"\"\"\"hi, man!\"\"\"\"\"\"\"");
240 static void test_strbuf_escaped(void **state)
242 STRBUF_ON_STACK(buf);
243 const char said[] = "She said \"hi, man\"";
245 assert_int_equal(append_strbuf_quoted(&buf, said), sizeof(said) + 3);
246 assert_string_equal(get_strbuf_str(&buf),
247 "\"She said \"\"hi, man\"\"\"");
250 assert_int_equal(append_strbuf_quoted(&buf, "\""), 4);
251 assert_string_equal(get_strbuf_str(&buf), "\"\"\"\"");
254 assert_int_equal(append_strbuf_quoted(&buf, "\"\""), 6);
255 assert_string_equal(get_strbuf_str(&buf), "\"\"\"\"\"\"");
258 assert_int_equal(append_strbuf_quoted(&buf, "\"Hi\""), 8);
259 assert_string_equal(get_strbuf_str(&buf), "\"\"\"Hi\"\"\"");
262 #define SENTENCE "yields, preceded by itself, falsehood"
263 static void test_print_strbuf(void **state)
265 STRBUF_ON_STACK(buf);
266 char sentence[] = SENTENCE;
268 assert_int_equal(print_strbuf(&buf, "\"%s\" %s.", sentence, sentence),
269 2 * (sizeof(sentence) - 1) + 4);
270 assert_string_equal(get_strbuf_str(&buf),
271 "\"" SENTENCE "\" " SENTENCE ".");
272 condlog(3, "%s", get_strbuf_str(&buf));
275 assert_int_equal(print_strbuf(&buf, "0x%08x", 0xdeadbeef), 10);
276 assert_string_equal(get_strbuf_str(&buf), "0xdeadbeef");
279 assert_int_equal(print_strbuf(&buf, "%d%% of %d is %0.2f",
281 assert_string_equal(get_strbuf_str(&buf), "5% of 100 is 0.05");
284 static void test_truncate_strbuf(void **state)
286 STRBUF_ON_STACK(buf);
287 const char str[] = "hello my dear!\n";
290 assert_int_equal(truncate_strbuf(&buf, 1), -EFAULT);
291 assert_int_equal(truncate_strbuf(&buf, 0), -EFAULT);
293 assert_int_equal(append_strbuf_str(&buf, str), sizeof(str) - 1);
294 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 1);
295 assert_string_equal(get_strbuf_str(&buf), str);
297 assert_int_equal(truncate_strbuf(&buf, sizeof(str)), -ERANGE);
298 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 1);
299 assert_string_equal(get_strbuf_str(&buf), str);
301 assert_int_equal(truncate_strbuf(&buf, sizeof(str) - 1), 0);
302 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 1);
303 assert_string_equal(get_strbuf_str(&buf), str);
305 assert_int_equal(truncate_strbuf(&buf, sizeof(str) - 2), 0);
306 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 2);
307 assert_string_not_equal(get_strbuf_str(&buf), str);
308 assert_memory_equal(get_strbuf_str(&buf), str, sizeof(str) - 2);
310 assert_int_equal(truncate_strbuf(&buf, 5), 0);
311 assert_int_equal(get_strbuf_len(&buf), 5);
312 assert_string_not_equal(get_strbuf_str(&buf), str);
313 assert_string_equal(get_strbuf_str(&buf), "hello");
316 assert_int_equal(append_strbuf_str(&buf, str), sizeof(str) - 1);
319 while (buf.size == sz)
320 assert_int_equal(append_strbuf_str(&buf, str), sizeof(str) - 1);
323 assert_in_range(get_strbuf_len(&buf), sz + 1, SIZE_MAX);
324 assert_string_equal(get_strbuf_str(&buf) +
325 get_strbuf_len(&buf) - (sizeof(str) - 1), str);
326 assert_int_equal(truncate_strbuf(&buf, get_strbuf_len(&buf) + 1),
328 assert_int_equal(truncate_strbuf(&buf, get_strbuf_len(&buf)), 0);
329 assert_int_equal(truncate_strbuf(&buf, get_strbuf_len(&buf)
330 - (sizeof(str) - 1)), 0);
331 assert_in_range(get_strbuf_len(&buf), 1, sz);
332 assert_string_equal(get_strbuf_str(&buf) +
333 get_strbuf_len(&buf) - (sizeof(str) - 1), str);
334 assert_int_equal(buf.size, sz1);
336 assert_int_equal(truncate_strbuf(&buf, 5), 0);
337 assert_int_equal(get_strbuf_len(&buf), 5);
338 assert_string_equal(get_strbuf_str(&buf), "hello");
339 assert_int_equal(buf.size, sz1);
341 assert_int_equal(truncate_strbuf(&buf, 0), 0);
342 assert_int_equal(get_strbuf_len(&buf), 0);
343 assert_string_equal(get_strbuf_str(&buf), "");
344 assert_int_equal(buf.size, sz1);
347 static void test_fill_strbuf(void **state)
349 STRBUF_ON_STACK(buf);
353 assert_int_equal(fill_strbuf(&buf, '+', -5), -EINVAL);
355 assert_int_equal(fill_strbuf(&buf, '+', 0), 0);
356 assert_int_equal(get_strbuf_len(&buf), 0);
357 assert_string_equal(get_strbuf_str(&buf), "");
359 assert_int_equal(fill_strbuf(&buf, '+', 1), 1);
360 assert_int_equal(get_strbuf_len(&buf), 1);
361 assert_string_equal(get_strbuf_str(&buf), "+");
363 assert_int_equal(fill_strbuf(&buf, '-', 3), 3);
364 assert_int_equal(get_strbuf_len(&buf), 4);
365 assert_string_equal(get_strbuf_str(&buf), "+---");
367 assert_int_equal(fill_strbuf(&buf, '\0', 3), 3);
368 assert_int_equal(get_strbuf_len(&buf), 7);
369 assert_string_equal(get_strbuf_str(&buf), "+---");
371 truncate_strbuf(&buf, 4);
372 assert_int_equal(fill_strbuf(&buf, '+', 4), 4);
373 assert_int_equal(get_strbuf_len(&buf), 8);
374 assert_string_equal(get_strbuf_str(&buf), "+---++++");
377 assert_int_equal(fill_strbuf(&buf, 'x', 30000), 30000);
378 assert_int_equal(get_strbuf_len(&buf), 30000);
379 p = steal_strbuf_str(&buf);
380 assert_int_equal(strlen(p), 30000);
381 for (i = 0; i < 30000; i++)
382 assert_int_equal(p[i], 'x');
386 static int test_strbuf(void)
388 const struct CMUnitTest tests[] = {
389 cmocka_unit_test(test_strbuf_00),
390 cmocka_unit_test(test_strbuf_alloc_err),
391 cmocka_unit_test(test_strbuf_overflow),
392 cmocka_unit_test(test_strbuf_big),
393 cmocka_unit_test(test_strbuf_nul),
394 cmocka_unit_test(test_strbuf_quoted),
395 cmocka_unit_test(test_strbuf_escaped),
396 cmocka_unit_test(test_print_strbuf),
397 cmocka_unit_test(test_truncate_strbuf),
398 cmocka_unit_test(test_fill_strbuf),
401 return cmocka_run_group_tests(tests, NULL, NULL);
408 init_test_verbosity(-1);
409 ret += test_strbuf();