2 * Copyright (c) 2021 SUSE LLC
3 * SPDX-License-Identifier: GPL-2.0-only
19 void *__real_realloc(void *ptr, size_t size);
21 static bool mock_realloc = false;
22 void *__wrap_realloc(void *ptr, size_t size)
26 return __real_realloc(ptr, size);
28 p = mock_ptr_type(void *);
29 condlog(4, "%s: %p, %zu -> %p", __func__, ptr, size, p);
33 static void test_strbuf_00(void **state)
38 assert_ptr_equal(buf.buf, NULL);
39 assert_int_equal(buf.size, 0);
40 assert_int_equal(buf.offs, 0);
41 assert_int_equal(get_strbuf_len(&buf), 0);
42 assert_string_equal(get_strbuf_str(&buf), "");
43 p = steal_strbuf_str(&buf);
44 assert_ptr_equal(p, NULL);
46 assert_ptr_equal(buf.buf, NULL);
47 assert_int_equal(buf.size, 0);
48 assert_int_equal(buf.offs, 0);
49 assert_int_equal(get_strbuf_len(&buf), 0);
50 assert_string_equal(get_strbuf_str(&buf), "");
52 assert_int_equal(append_strbuf_str(&buf, "moin"), 4);
53 assert_int_equal(get_strbuf_len(&buf), 4);
54 assert_in_range(buf.size, 5, SIZE_MAX);
55 assert_string_equal(get_strbuf_str(&buf), "moin");
56 p = steal_strbuf_str(&buf);
57 assert_string_equal(p, "moin");
60 assert_ptr_equal(buf.buf, NULL);
61 assert_int_equal(buf.size, 0);
62 assert_int_equal(buf.offs, 0);
63 assert_int_equal(get_strbuf_len(&buf), 0);
64 assert_string_equal(get_strbuf_str(&buf), "");
66 assert_int_equal(append_strbuf_str(&buf, NULL), -EINVAL);
67 assert_int_equal(buf.size, 0);
68 assert_int_equal(buf.offs, 0);
69 assert_int_equal(get_strbuf_len(&buf), 0);
70 assert_string_equal(get_strbuf_str(&buf), "");
72 assert_int_equal(append_strbuf_str(&buf, ""), 0);
73 /* appending a 0-length string allocates memory */
74 assert_in_range(buf.size, 1, SIZE_MAX);
75 assert_int_equal(buf.offs, 0);
76 assert_int_equal(get_strbuf_len(&buf), 0);
77 assert_string_equal(get_strbuf_str(&buf), "");
78 p = steal_strbuf_str(&buf);
79 assert_string_equal(p, "");
82 assert_int_equal(__append_strbuf_str(&buf, "x", 0), 0);
83 /* appending a 0-length string allocates memory */
84 assert_in_range(buf.size, 1, SIZE_MAX);
85 assert_int_equal(buf.offs, 0);
86 assert_int_equal(get_strbuf_len(&buf), 0);
87 assert_string_equal(get_strbuf_str(&buf), "");
90 static void test_strbuf_alloc_err(void **state)
97 will_return(__wrap_realloc, NULL);
98 assert_int_equal(append_strbuf_str(&buf, "moin"), -ENOMEM);
99 assert_int_equal(buf.size, 0);
100 assert_int_equal(buf.offs, 0);
101 assert_int_equal(get_strbuf_len(&buf), 0);
102 assert_string_equal(get_strbuf_str(&buf), "");
104 mock_realloc = false;
105 assert_int_equal(append_strbuf_str(&buf, "moin"), 4);
107 assert_in_range(sz, 5, SIZE_MAX);
108 assert_int_equal(buf.offs, 4);
109 assert_int_equal(get_strbuf_len(&buf), 4);
110 assert_string_equal(get_strbuf_str(&buf), "moin");
113 will_return(__wrap_realloc, NULL);
114 ofs = get_strbuf_len(&buf);
115 while ((rc = append_strbuf_str(&buf, " hello")) >= 0) {
116 condlog(3, "%s", get_strbuf_str(&buf));
117 assert_int_equal(rc, 6);
118 assert_int_equal(get_strbuf_len(&buf), ofs + 6);
119 assert_memory_equal(get_strbuf_str(&buf), "moin", 4);
120 assert_string_equal(get_strbuf_str(&buf) + ofs, " hello");
121 ofs = get_strbuf_len(&buf);
123 assert_int_equal(rc, -ENOMEM);
124 assert_int_equal(buf.size, sz);
125 assert_int_equal(get_strbuf_len(&buf), ofs);
126 assert_memory_equal(get_strbuf_str(&buf), "moin", 4);
127 assert_string_equal(get_strbuf_str(&buf) + ofs - 6, " hello");
130 assert_ptr_equal(buf.buf, NULL);
131 assert_int_equal(buf.size, 0);
132 assert_int_equal(buf.offs, 0);
133 assert_int_equal(get_strbuf_len(&buf), 0);
134 assert_string_equal(get_strbuf_str(&buf), "");
136 mock_realloc = false;
139 static void test_strbuf_overflow(void **state)
141 STRBUF_ON_STACK(buf);
143 assert_int_equal(append_strbuf_str(&buf, "x"), 1);
144 /* fake huge buffer */
145 buf.size = SIZE_MAX - 1;
146 buf.offs = buf.size - 1;
147 assert_int_equal(append_strbuf_str(&buf, "x"), -EOVERFLOW);
150 static void test_strbuf_big(void **state)
152 STRBUF_ON_STACK(buf);
153 const char big[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n";
157 /* Under valgrind, 30000 iterations need ca. 30s on my laptop */
158 for (i = 0; i < 30000; i++) {
161 assert_int_equal(append_strbuf_str(&buf, big), sizeof(big) - 1);
162 assert_int_equal(get_strbuf_len(&buf), (sizeof(big) - 1) * (i + 1));
163 assert_memory_equal(get_strbuf_str(&buf), big, sizeof(big) - 1);
164 assert_string_equal(get_strbuf_str(&buf) + get_strbuf_len(&buf)
165 - (sizeof(big) - 1), big);
167 bbig = steal_strbuf_str(&buf);
169 assert_ptr_equal(buf.buf, NULL);
170 assert_int_equal(buf.size, 0);
171 assert_int_equal(buf.offs, 0);
172 assert_int_equal(get_strbuf_len(&buf), 0);
173 assert_string_equal(get_strbuf_str(&buf), "");
175 assert_int_equal(strlen(bbig), i * (sizeof(big) - 1));
176 assert_memory_equal(bbig, big, sizeof(big) - 1);
180 static void test_strbuf_nul(void **state)
182 STRBUF_ON_STACK(buf);
183 char greet[] = "hello, sir!";
185 assert_int_equal(__append_strbuf_str(&buf, greet, 6), 6);
186 assert_string_equal(get_strbuf_str(&buf), "hello,");
187 assert_int_equal(__append_strbuf_str(&buf, greet, 6), 6);
188 assert_string_equal(get_strbuf_str(&buf), "hello,hello,");
190 /* overwrite comma with NUL; append_strbuf_str() stops at NUL byte */
193 assert_int_equal(append_strbuf_str(&buf, greet), 5);
194 assert_int_equal(get_strbuf_len(&buf), 5);
195 assert_string_equal(get_strbuf_str(&buf), "hello");
196 assert_int_equal(append_strbuf_str(&buf, greet), 5);
197 assert_int_equal(get_strbuf_len(&buf), 10);
198 assert_string_equal(get_strbuf_str(&buf), "hellohello");
200 /* __append_strbuf_str() appends full memory, including NUL bytes */
202 assert_int_equal(__append_strbuf_str(&buf, greet, sizeof(greet) - 1),
204 assert_int_equal(get_strbuf_len(&buf), sizeof(greet) - 1);
205 assert_string_equal(get_strbuf_str(&buf), "hello");
206 assert_string_equal(get_strbuf_str(&buf) + get_strbuf_len(&buf) - 5, " sir!");
207 assert_int_equal(__append_strbuf_str(&buf, greet, sizeof(greet) - 1),
209 assert_string_equal(get_strbuf_str(&buf), "hello");
210 assert_int_equal(get_strbuf_len(&buf), 2 * (sizeof(greet) - 1));
211 assert_string_equal(get_strbuf_str(&buf) + get_strbuf_len(&buf) - 5, " sir!");
214 static void test_strbuf_quoted(void **state)
216 STRBUF_ON_STACK(buf);
217 const char said[] = "She said ";
218 const char greet[] = "hi, man!";
222 assert_int_equal(append_strbuf_str(&buf, said), sizeof(said) - 1);
223 assert_int_equal(append_strbuf_quoted(&buf, greet), sizeof(greet) + 1);
224 assert_string_equal(get_strbuf_str(&buf), "She said \"hi, man!\"");
225 n = get_strbuf_len(&buf);
226 p = steal_strbuf_str(&buf);
227 assert_int_equal(append_strbuf_str(&buf, said), sizeof(said) - 1);
228 assert_int_equal(append_strbuf_quoted(&buf, p), n + 4);
229 assert_string_equal(get_strbuf_str(&buf),
230 "She said \"She said \"\"hi, man!\"\"\"");
232 n = get_strbuf_len(&buf);
233 p = steal_strbuf_str(&buf);
234 assert_int_equal(append_strbuf_str(&buf, said), sizeof(said) - 1);
235 assert_int_equal(append_strbuf_quoted(&buf, p), n + 8);
236 assert_string_equal(get_strbuf_str(&buf),
237 "She said \"She said \"\"She said \"\"\"\"hi, man!\"\"\"\"\"\"\"");
241 static void test_strbuf_escaped(void **state)
243 STRBUF_ON_STACK(buf);
244 const char said[] = "She said \"hi, man\"";
246 assert_int_equal(append_strbuf_quoted(&buf, said), sizeof(said) + 3);
247 assert_string_equal(get_strbuf_str(&buf),
248 "\"She said \"\"hi, man\"\"\"");
251 assert_int_equal(append_strbuf_quoted(&buf, "\""), 4);
252 assert_string_equal(get_strbuf_str(&buf), "\"\"\"\"");
255 assert_int_equal(append_strbuf_quoted(&buf, "\"\""), 6);
256 assert_string_equal(get_strbuf_str(&buf), "\"\"\"\"\"\"");
259 assert_int_equal(append_strbuf_quoted(&buf, "\"Hi\""), 8);
260 assert_string_equal(get_strbuf_str(&buf), "\"\"\"Hi\"\"\"");
263 #define SENTENCE "yields, preceded by itself, falsehood"
264 static void test_print_strbuf(void **state)
266 STRBUF_ON_STACK(buf);
267 char sentence[] = SENTENCE;
269 assert_int_equal(print_strbuf(&buf, "\"%s\" %s.", sentence, sentence),
270 2 * (sizeof(sentence) - 1) + 4);
271 assert_string_equal(get_strbuf_str(&buf),
272 "\"" SENTENCE "\" " SENTENCE ".");
273 condlog(3, "%s", get_strbuf_str(&buf));
276 assert_int_equal(print_strbuf(&buf, "0x%08x", 0xdeadbeef), 10);
277 assert_string_equal(get_strbuf_str(&buf), "0xdeadbeef");
280 assert_int_equal(print_strbuf(&buf, "%d%% of %d is %0.2f",
282 assert_string_equal(get_strbuf_str(&buf), "5% of 100 is 0.05");
285 static void test_truncate_strbuf(void **state)
287 STRBUF_ON_STACK(buf);
288 const char str[] = "hello my dear!\n";
291 assert_int_equal(truncate_strbuf(&buf, 1), -EFAULT);
292 assert_int_equal(truncate_strbuf(&buf, 0), -EFAULT);
294 assert_int_equal(append_strbuf_str(&buf, str), sizeof(str) - 1);
295 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 1);
296 assert_string_equal(get_strbuf_str(&buf), str);
298 assert_int_equal(truncate_strbuf(&buf, sizeof(str)), -ERANGE);
299 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 1);
300 assert_string_equal(get_strbuf_str(&buf), str);
302 assert_int_equal(truncate_strbuf(&buf, sizeof(str) - 1), 0);
303 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 1);
304 assert_string_equal(get_strbuf_str(&buf), str);
306 assert_int_equal(truncate_strbuf(&buf, sizeof(str) - 2), 0);
307 assert_int_equal(get_strbuf_len(&buf), sizeof(str) - 2);
308 assert_string_not_equal(get_strbuf_str(&buf), str);
309 assert_memory_equal(get_strbuf_str(&buf), str, sizeof(str) - 2);
311 assert_int_equal(truncate_strbuf(&buf, 5), 0);
312 assert_int_equal(get_strbuf_len(&buf), 5);
313 assert_string_not_equal(get_strbuf_str(&buf), str);
314 assert_string_equal(get_strbuf_str(&buf), "hello");
317 assert_int_equal(append_strbuf_str(&buf, str), sizeof(str) - 1);
320 while (buf.size == sz)
321 assert_int_equal(append_strbuf_str(&buf, str), sizeof(str) - 1);
324 assert_in_range(get_strbuf_len(&buf), sz + 1, SIZE_MAX);
325 assert_string_equal(get_strbuf_str(&buf) +
326 get_strbuf_len(&buf) - (sizeof(str) - 1), str);
327 assert_int_equal(truncate_strbuf(&buf, get_strbuf_len(&buf) + 1),
329 assert_int_equal(truncate_strbuf(&buf, get_strbuf_len(&buf)), 0);
330 assert_int_equal(truncate_strbuf(&buf, get_strbuf_len(&buf)
331 - (sizeof(str) - 1)), 0);
332 assert_in_range(get_strbuf_len(&buf), 1, sz);
333 assert_string_equal(get_strbuf_str(&buf) +
334 get_strbuf_len(&buf) - (sizeof(str) - 1), str);
335 assert_int_equal(buf.size, sz1);
337 assert_int_equal(truncate_strbuf(&buf, 5), 0);
338 assert_int_equal(get_strbuf_len(&buf), 5);
339 assert_string_equal(get_strbuf_str(&buf), "hello");
340 assert_int_equal(buf.size, sz1);
342 assert_int_equal(truncate_strbuf(&buf, 0), 0);
343 assert_int_equal(get_strbuf_len(&buf), 0);
344 assert_string_equal(get_strbuf_str(&buf), "");
345 assert_int_equal(buf.size, sz1);
348 static void test_fill_strbuf(void **state)
350 STRBUF_ON_STACK(buf);
354 assert_int_equal(fill_strbuf(&buf, '+', -5), -EINVAL);
356 assert_int_equal(fill_strbuf(&buf, '+', 0), 0);
357 assert_int_equal(get_strbuf_len(&buf), 0);
358 assert_string_equal(get_strbuf_str(&buf), "");
360 assert_int_equal(fill_strbuf(&buf, '+', 1), 1);
361 assert_int_equal(get_strbuf_len(&buf), 1);
362 assert_string_equal(get_strbuf_str(&buf), "+");
364 assert_int_equal(fill_strbuf(&buf, '-', 3), 3);
365 assert_int_equal(get_strbuf_len(&buf), 4);
366 assert_string_equal(get_strbuf_str(&buf), "+---");
368 assert_int_equal(fill_strbuf(&buf, '\0', 3), 3);
369 assert_int_equal(get_strbuf_len(&buf), 7);
370 assert_string_equal(get_strbuf_str(&buf), "+---");
372 truncate_strbuf(&buf, 4);
373 assert_int_equal(fill_strbuf(&buf, '+', 4), 4);
374 assert_int_equal(get_strbuf_len(&buf), 8);
375 assert_string_equal(get_strbuf_str(&buf), "+---++++");
378 assert_int_equal(fill_strbuf(&buf, 'x', 30000), 30000);
379 assert_int_equal(get_strbuf_len(&buf), 30000);
380 p = steal_strbuf_str(&buf);
381 assert_int_equal(strlen(p), 30000);
382 for (i = 0; i < 30000; i++)
383 assert_int_equal(p[i], 'x');
387 static int test_strbuf(void)
389 const struct CMUnitTest tests[] = {
390 cmocka_unit_test(test_strbuf_00),
391 cmocka_unit_test(test_strbuf_alloc_err),
392 cmocka_unit_test(test_strbuf_overflow),
393 cmocka_unit_test(test_strbuf_big),
394 cmocka_unit_test(test_strbuf_nul),
395 cmocka_unit_test(test_strbuf_quoted),
396 cmocka_unit_test(test_strbuf_escaped),
397 cmocka_unit_test(test_print_strbuf),
398 cmocka_unit_test(test_truncate_strbuf),
399 cmocka_unit_test(test_fill_strbuf),
402 return cmocka_run_group_tests(tests, NULL, NULL);
409 init_test_verbosity(-1);
410 ret += test_strbuf();