1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2021 Google LLC
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7 #include <abuf.h>
8 #include <mapmem.h>
9 #include <test/lib.h>
10 #include <test/test.h>
11 #include <test/ut.h>
12
13 static char test_data[] = "1234";
14 #define TEST_DATA_LEN sizeof(test_data)
15 #define HUGE_ALLOC_SIZE 0x60000000
16
17 /* Test abuf_set() */
lib_test_abuf_set(struct unit_test_state * uts)18 static int lib_test_abuf_set(struct unit_test_state *uts)
19 {
20 struct abuf buf;
21 ulong start;
22
23 start = ut_check_free();
24
25 abuf_init(&buf);
26 abuf_set(&buf, test_data, TEST_DATA_LEN);
27 ut_asserteq_ptr(test_data, buf.data);
28 ut_asserteq(TEST_DATA_LEN, buf.size);
29 ut_asserteq(false, buf.alloced);
30
31 /* Force it to allocate */
32 ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN + 1));
33 ut_assertnonnull(buf.data);
34 ut_asserteq(TEST_DATA_LEN + 1, buf.size);
35 ut_asserteq(true, buf.alloced);
36
37 /* Now set it again, to force it to free */
38 abuf_set(&buf, test_data, TEST_DATA_LEN);
39 ut_asserteq_ptr(test_data, buf.data);
40 ut_asserteq(TEST_DATA_LEN, buf.size);
41 ut_asserteq(false, buf.alloced);
42
43 /* Check for memory leaks */
44 ut_assertok(ut_check_delta(start));
45
46 return 0;
47 }
48 LIB_TEST(lib_test_abuf_set, 0);
49
50 /* Test abuf_init_const() */
lib_test_abuf_init_const(struct unit_test_state * uts)51 static int lib_test_abuf_init_const(struct unit_test_state *uts)
52 {
53 struct abuf buf;
54 ulong start;
55 void *ptr;
56
57 start = ut_check_free();
58
59 ptr = map_sysmem(0x100, 0);
60
61 abuf_init_const(&buf, ptr, 10);
62 ut_asserteq_ptr(ptr, buf.data);
63 ut_asserteq(10, buf.size);
64
65 /* No memory should have been allocated */
66 ut_assertok(ut_check_delta(start));
67
68 return 0;
69 }
70 LIB_TEST(lib_test_abuf_init_const, 0);
71
72 /* Test abuf_map_sysmem() and abuf_addr() */
lib_test_abuf_map_sysmem(struct unit_test_state * uts)73 static int lib_test_abuf_map_sysmem(struct unit_test_state *uts)
74 {
75 struct abuf buf;
76 ulong addr;
77
78 abuf_init(&buf);
79 addr = 0x100;
80 abuf_map_sysmem(&buf, addr, TEST_DATA_LEN);
81
82 ut_asserteq_ptr(map_sysmem(0x100, 0), buf.data);
83 ut_asserteq(TEST_DATA_LEN, buf.size);
84 ut_asserteq(false, buf.alloced);
85
86 ut_asserteq(addr, abuf_addr(&buf));
87
88 return 0;
89 }
90 LIB_TEST(lib_test_abuf_map_sysmem, 0);
91
92 /* Test abuf_realloc() */
lib_test_abuf_realloc(struct unit_test_state * uts)93 static int lib_test_abuf_realloc(struct unit_test_state *uts)
94 {
95 struct abuf buf;
96 ulong start;
97
98 start = ut_check_free();
99
100 abuf_init(&buf);
101
102 /* Allocate an empty buffer */
103 ut_asserteq(true, abuf_realloc(&buf, 0));
104 ut_assertnull(buf.data);
105 ut_asserteq(0, buf.size);
106 ut_asserteq(false, buf.alloced);
107
108 /* Allocate a non-empty abuf */
109 ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
110 ut_assertnonnull(buf.data);
111 ut_asserteq(TEST_DATA_LEN, buf.size);
112 ut_asserteq(true, buf.alloced);
113
114 /*
115 * Make it smaller.
116 */
117 ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN - 1));
118 ut_asserteq(TEST_DATA_LEN - 1, buf.size);
119 ut_asserteq(true, buf.alloced);
120
121 /*
122 * Make it larger.
123 */
124 ut_asserteq(true, abuf_realloc(&buf, 0x1000));
125 ut_asserteq(0x1000, buf.size);
126 ut_asserteq(true, buf.alloced);
127
128 /* Free it */
129 ut_asserteq(true, abuf_realloc(&buf, 0));
130 ut_assertnull(buf.data);
131 ut_asserteq(0, buf.size);
132 ut_asserteq(false, buf.alloced);
133
134 /* Check for memory leaks */
135 ut_assertok(ut_check_delta(start));
136
137 return 0;
138 }
139 LIB_TEST(lib_test_abuf_realloc, 0);
140
141 /* Test abuf_realloc() on an non-allocated buffer of zero size */
lib_test_abuf_realloc_size(struct unit_test_state * uts)142 static int lib_test_abuf_realloc_size(struct unit_test_state *uts)
143 {
144 struct abuf buf;
145 ulong start;
146
147 start = ut_check_free();
148
149 abuf_init(&buf);
150
151 /* Allocate some space */
152 ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
153 ut_assertnonnull(buf.data);
154 ut_asserteq(TEST_DATA_LEN, buf.size);
155 ut_asserteq(true, buf.alloced);
156
157 /* Free it */
158 ut_asserteq(true, abuf_realloc(&buf, 0));
159 ut_assertnull(buf.data);
160 ut_asserteq(0, buf.size);
161 ut_asserteq(false, buf.alloced);
162
163 /* Check for memory leaks */
164 ut_assertok(ut_check_delta(start));
165
166 return 0;
167 }
168 LIB_TEST(lib_test_abuf_realloc_size, 0);
169
170 /* Test abuf_realloc_inc() */
lib_test_abuf_realloc_inc(struct unit_test_state * uts)171 static int lib_test_abuf_realloc_inc(struct unit_test_state *uts)
172 {
173 struct abuf buf;
174 ulong start;
175
176 start = ut_check_free();
177
178 abuf_init(&buf);
179 ut_asserteq(0, buf.size);
180 ut_asserteq(false, buf.alloced);
181
182 abuf_realloc_inc(&buf, 20);
183 ut_asserteq(20, buf.size);
184 ut_asserteq(true, buf.alloced);
185
186 abuf_uninit(&buf);
187
188 /* Check for memory leaks */
189 ut_assertok(ut_check_delta(start));
190
191 return 0;
192 }
193 LIB_TEST(lib_test_abuf_realloc_inc, 0);
194
195 /* Test handling of buffers that are too large */
lib_test_abuf_large(struct unit_test_state * uts)196 static int lib_test_abuf_large(struct unit_test_state *uts)
197 {
198 struct abuf buf;
199 ulong start;
200 size_t size;
201 int delta;
202
203 start = ut_check_free();
204
205 /* Try an impossible size */
206 abuf_init(&buf);
207 ut_asserteq(false, abuf_realloc(&buf, HUGE_ALLOC_SIZE));
208 ut_assertnull(buf.data);
209 ut_asserteq(0, buf.size);
210 ut_asserteq(false, buf.alloced);
211
212 abuf_uninit(&buf);
213 ut_assertnull(buf.data);
214 ut_asserteq(0, buf.size);
215 ut_asserteq(false, buf.alloced);
216
217 /* Start with a normal size then try to increase it, to check realloc */
218 ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
219 ut_assertnonnull(buf.data);
220 ut_asserteq(TEST_DATA_LEN, buf.size);
221 ut_asserteq(true, buf.alloced);
222 delta = ut_check_delta(start);
223 ut_assert(delta > 0);
224
225 /* try to increase it */
226 ut_asserteq(false, abuf_realloc(&buf, HUGE_ALLOC_SIZE));
227 ut_asserteq(TEST_DATA_LEN, buf.size);
228 ut_asserteq(true, buf.alloced);
229 ut_asserteq(delta, ut_check_delta(start));
230
231 /* Check for memory leaks */
232 abuf_uninit(&buf);
233 ut_assertok(ut_check_delta(start));
234
235 /* Start with a huge unallocated buf and try to move it */
236 abuf_init(&buf);
237 abuf_map_sysmem(&buf, 0, HUGE_ALLOC_SIZE);
238 ut_asserteq(HUGE_ALLOC_SIZE, buf.size);
239 ut_asserteq(false, buf.alloced);
240 ut_assertnull(abuf_uninit_move(&buf, &size));
241
242 /* Check for memory leaks */
243 abuf_uninit(&buf);
244 ut_assertok(ut_check_delta(start));
245
246 return 0;
247 }
248 LIB_TEST(lib_test_abuf_large, 0);
249
250 /* Test abuf_uninit_move() */
lib_test_abuf_uninit_move(struct unit_test_state * uts)251 static int lib_test_abuf_uninit_move(struct unit_test_state *uts)
252 {
253 void *ptr, *orig_ptr;
254 struct abuf buf;
255 size_t size;
256 ulong start;
257 int delta;
258
259 start = ut_check_free();
260
261 /* Move an empty buffer */
262 abuf_init(&buf);
263 ut_assertnull(abuf_uninit_move(&buf, &size));
264 ut_asserteq(0, size);
265 ut_assertnull(abuf_uninit_move(&buf, NULL));
266
267 /* Move an unallocated buffer */
268 abuf_set(&buf, test_data, TEST_DATA_LEN);
269 ut_assertok(ut_check_delta(start));
270 ptr = abuf_uninit_move(&buf, &size);
271 ut_asserteq(TEST_DATA_LEN, size);
272 ut_asserteq_str(ptr, test_data);
273 ut_assertnonnull(ptr);
274 ut_assertnull(buf.data);
275 ut_asserteq(0, buf.size);
276 ut_asserteq(false, buf.alloced);
277
278 /* Check that freeing it frees the only allocation */
279 delta = ut_check_delta(start);
280 ut_assert(delta > 0);
281 free(ptr);
282 ut_assertok(ut_check_delta(start));
283
284 /* Move an allocated buffer */
285 ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
286 orig_ptr = buf.data;
287 strcpy(orig_ptr, test_data);
288
289 delta = ut_check_delta(start);
290 ut_assert(delta > 0);
291 ptr = abuf_uninit_move(&buf, &size);
292 ut_asserteq(TEST_DATA_LEN, size);
293 ut_assertnonnull(ptr);
294 ut_asserteq_ptr(ptr, orig_ptr);
295 ut_asserteq_str(ptr, test_data);
296 ut_assertnull(buf.data);
297 ut_asserteq(0, buf.size);
298 ut_asserteq(false, buf.alloced);
299
300 /* Check there was no new allocation */
301 ut_asserteq(delta, ut_check_delta(start));
302
303 /* Check that freeing it frees the only allocation */
304 free(ptr);
305 ut_assertok(ut_check_delta(start));
306
307 /* Move an unallocated buffer, without the size */
308 abuf_set(&buf, test_data, TEST_DATA_LEN);
309 ut_assertok(ut_check_delta(start));
310 ptr = abuf_uninit_move(&buf, NULL);
311 ut_asserteq_str(ptr, test_data);
312
313 return 0;
314 }
315 LIB_TEST(lib_test_abuf_uninit_move, 0);
316
317 /* Test abuf_uninit() */
lib_test_abuf_uninit(struct unit_test_state * uts)318 static int lib_test_abuf_uninit(struct unit_test_state *uts)
319 {
320 struct abuf buf;
321
322 /* Nothing in the buffer */
323 abuf_init(&buf);
324 abuf_uninit(&buf);
325 ut_assertnull(buf.data);
326 ut_asserteq(0, buf.size);
327 ut_asserteq(false, buf.alloced);
328
329 /* Not allocated */
330 abuf_set(&buf, test_data, TEST_DATA_LEN);
331 abuf_uninit(&buf);
332 ut_assertnull(buf.data);
333 ut_asserteq(0, buf.size);
334 ut_asserteq(false, buf.alloced);
335
336 return 0;
337 }
338 LIB_TEST(lib_test_abuf_uninit, 0);
339
340 /* Test abuf_init_set() */
lib_test_abuf_init_set(struct unit_test_state * uts)341 static int lib_test_abuf_init_set(struct unit_test_state *uts)
342 {
343 struct abuf buf;
344
345 abuf_init_set(&buf, test_data, TEST_DATA_LEN);
346 ut_asserteq_ptr(test_data, buf.data);
347 ut_asserteq(TEST_DATA_LEN, buf.size);
348 ut_asserteq(false, buf.alloced);
349
350 return 0;
351 }
352 LIB_TEST(lib_test_abuf_init_set, 0);
353
354 /* Test abuf_init_move() */
lib_test_abuf_init_move(struct unit_test_state * uts)355 static int lib_test_abuf_init_move(struct unit_test_state *uts)
356 {
357 struct abuf buf;
358 void *ptr;
359
360 ptr = strdup(test_data);
361 ut_assertnonnull(ptr);
362
363 free(ptr);
364
365 abuf_init_move(&buf, ptr, TEST_DATA_LEN);
366 ut_asserteq_ptr(ptr, abuf_data(&buf));
367 ut_asserteq(TEST_DATA_LEN, abuf_size(&buf));
368 ut_asserteq(true, buf.alloced);
369
370 return 0;
371 }
372 LIB_TEST(lib_test_abuf_init_move, 0);
373
374 /* Test abuf_init() */
lib_test_abuf_init(struct unit_test_state * uts)375 static int lib_test_abuf_init(struct unit_test_state *uts)
376 {
377 struct abuf buf;
378
379 buf.data = &buf;
380 buf.size = 123;
381 buf.alloced = true;
382 abuf_init(&buf);
383 ut_assertnull(buf.data);
384 ut_asserteq(0, buf.size);
385 ut_asserteq(false, buf.alloced);
386
387 return 0;
388 }
389 LIB_TEST(lib_test_abuf_init, 0);
390
391 /* Test abuf_copy() */
lib_test_abuf_copy(struct unit_test_state * uts)392 static int lib_test_abuf_copy(struct unit_test_state *uts)
393 {
394 struct abuf buf, copy;
395 ulong start;
396
397 start = ut_check_free();
398
399 abuf_init_set(&buf, test_data, TEST_DATA_LEN);
400 ut_assert(abuf_copy(&buf, ©));
401 ut_asserteq(buf.size, copy.size);
402 ut_assert(buf.data != copy.data);
403 ut_assert(copy.alloced);
404 abuf_uninit(©);
405 abuf_uninit(&buf);
406
407 /* Check for memory leaks */
408 ut_assertok(ut_check_delta(start));
409
410 return 0;
411 }
412 LIB_TEST(lib_test_abuf_copy, 0);
413
414 /* Test abuf_init_size() */
lib_test_abuf_init_size(struct unit_test_state * uts)415 static int lib_test_abuf_init_size(struct unit_test_state *uts)
416 {
417 struct abuf buf;
418 ulong start;
419
420 start = ut_check_free();
421
422 ut_assert(abuf_init_size(&buf, TEST_DATA_LEN));
423 ut_assertnonnull(buf.data);
424 ut_asserteq(TEST_DATA_LEN, buf.size);
425 ut_asserteq(true, buf.alloced);
426 abuf_uninit(&buf);
427
428 /* Check for memory leaks */
429 ut_assertok(ut_check_delta(start));
430
431 return 0;
432 }
433 LIB_TEST(lib_test_abuf_init_size, 0);
434
435 /* Test abuf_printf() */
lib_test_abuf_printf(struct unit_test_state * uts)436 static int lib_test_abuf_printf(struct unit_test_state *uts)
437 {
438 struct abuf buf, fmt;
439 ulong start;
440 char *ptr;
441
442 start = ut_check_free();
443
444 /* start with a fresh buffer */
445 abuf_init(&buf);
446
447 /* check handling of out-of-memory condition */
448 malloc_enable_testing(0);
449 ut_asserteq(-ENOMEM, abuf_printf(&buf, "%s", ""));
450 malloc_enable_testing(1);
451
452 ut_asserteq(0, abuf_printf(&buf, "%s", ""));
453 ut_asserteq(1, buf.size);
454 ut_asserteq(true, buf.alloced);
455 ut_asserteq_str("", buf.data);
456
457 /* check expanding it, initially failing */
458 ut_asserteq(-ENOMEM, abuf_printf(&buf, "%s", "testing"));
459 malloc_disable_testing();
460
461 ut_asserteq(7, abuf_printf(&buf, "%s", "testing"));
462 ut_asserteq(8, buf.size);
463 ut_asserteq_str("testing", buf.data);
464
465 ut_asserteq(11, abuf_printf(&buf, "testing %d", 123));
466 ut_asserteq(12, buf.size);
467 ut_asserteq_str("testing 123", buf.data);
468
469 /* make it smaller; buffer should not shrink */
470 ut_asserteq(9, abuf_printf(&buf, "test %d", 456));
471 ut_asserteq(12, buf.size);
472 ut_asserteq_str("test 456", buf.data);
473
474 /* test the maximum size */
475 abuf_init(&fmt);
476 ut_assert(abuf_realloc(&fmt, 4100));
477 memset(fmt.data, 'x', 4100);
478 ptr = fmt.data;
479 ptr[4096] = '\0';
480
481 /* we are allowed up to 4K including the terminator */
482 ut_asserteq(-E2BIG, abuf_printf(&buf, "%s", ptr));
483 ptr[4095] = '\0';
484 ut_asserteq(4095, abuf_printf(&buf, "%s", ptr));
485
486 abuf_uninit(&fmt);
487 abuf_uninit(&buf);
488
489 /* Check for memory leaks */
490 ut_assertok(ut_check_delta(start));
491
492 return 0;
493 }
494 LIB_TEST(lib_test_abuf_printf, 0);
495