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 <common.h>
8 #include <abuf.h>
9 #include <mapmem.h>
10 #include <test/lib.h>
11 #include <test/test.h>
12 #include <test/ut.h>
13 
14 static char test_data[] = "1234";
15 #define TEST_DATA_LEN	sizeof(test_data)
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_map_sysmem() */
lib_test_abuf_map_sysmem(struct unit_test_state * uts)51 static int lib_test_abuf_map_sysmem(struct unit_test_state *uts)
52 {
53 	struct abuf buf;
54 	ulong addr;
55 
56 	abuf_init(&buf);
57 	addr = 0x100;
58 	abuf_map_sysmem(&buf, addr, TEST_DATA_LEN);
59 
60 	ut_asserteq_ptr(map_sysmem(0x100, 0), buf.data);
61 	ut_asserteq(TEST_DATA_LEN, buf.size);
62 	ut_asserteq(false, buf.alloced);
63 
64 	return 0;
65 }
66 LIB_TEST(lib_test_abuf_map_sysmem, 0);
67 
68 /* Test abuf_realloc() */
lib_test_abuf_realloc(struct unit_test_state * uts)69 static int lib_test_abuf_realloc(struct unit_test_state *uts)
70 {
71 	struct abuf buf;
72 	ulong start;
73 	void *ptr;
74 
75 	/*
76 	 * TODO: crashes on sandbox sometimes due to an apparent bug in
77 	 * realloc().
78 	 */
79 	return 0;
80 
81 	start = ut_check_free();
82 
83 	abuf_init(&buf);
84 
85 	/* Allocate an empty buffer */
86 	ut_asserteq(true, abuf_realloc(&buf, 0));
87 	ut_assertnull(buf.data);
88 	ut_asserteq(0, buf.size);
89 	ut_asserteq(false, buf.alloced);
90 
91 	/* Allocate a non-empty abuf */
92 	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
93 	ut_assertnonnull(buf.data);
94 	ut_asserteq(TEST_DATA_LEN, buf.size);
95 	ut_asserteq(true, buf.alloced);
96 	ptr = buf.data;
97 
98 	/*
99 	 * Make it smaller; the pointer should remain the same. Note this relies
100 	 * on knowledge of how U-Boot's realloc() works
101 	 */
102 	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN - 1));
103 	ut_asserteq(TEST_DATA_LEN - 1, buf.size);
104 	ut_asserteq(true, buf.alloced);
105 	ut_asserteq_ptr(ptr, buf.data);
106 
107 	/*
108 	 * Make it larger, forcing reallocation. Note this relies on knowledge
109 	 * of how U-Boot's realloc() works
110 	 */
111 	ut_asserteq(true, abuf_realloc(&buf, 0x1000));
112 	ut_assert(buf.data != ptr);
113 	ut_asserteq(0x1000, buf.size);
114 	ut_asserteq(true, buf.alloced);
115 
116 	/* Free it */
117 	ut_asserteq(true, abuf_realloc(&buf, 0));
118 	ut_assertnull(buf.data);
119 	ut_asserteq(0, buf.size);
120 	ut_asserteq(false, buf.alloced);
121 
122 	/* Check for memory leaks */
123 	ut_assertok(ut_check_delta(start));
124 
125 	return 0;
126 }
127 LIB_TEST(lib_test_abuf_realloc, 0);
128 
129 /* Test abuf_realloc() on an non-allocated buffer of zero size */
lib_test_abuf_realloc_size(struct unit_test_state * uts)130 static int lib_test_abuf_realloc_size(struct unit_test_state *uts)
131 {
132 	struct abuf buf;
133 	ulong start;
134 
135 	start = ut_check_free();
136 
137 	abuf_init(&buf);
138 
139 	/* Allocate some space */
140 	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
141 	ut_assertnonnull(buf.data);
142 	ut_asserteq(TEST_DATA_LEN, buf.size);
143 	ut_asserteq(true, buf.alloced);
144 
145 	/* Free it */
146 	ut_asserteq(true, abuf_realloc(&buf, 0));
147 	ut_assertnull(buf.data);
148 	ut_asserteq(0, buf.size);
149 	ut_asserteq(false, buf.alloced);
150 
151 	/* Check for memory leaks */
152 	ut_assertok(ut_check_delta(start));
153 
154 	return 0;
155 }
156 LIB_TEST(lib_test_abuf_realloc_size, 0);
157 
158 /* Test handling of buffers that are too large */
lib_test_abuf_large(struct unit_test_state * uts)159 static int lib_test_abuf_large(struct unit_test_state *uts)
160 {
161 	struct abuf buf;
162 	ulong start;
163 	size_t size;
164 	int delta;
165 	void *ptr;
166 
167 	/*
168 	 * This crashes at present due to trying to allocate more memory than
169 	 * available, which breaks something on sandbox.
170 	 */
171 	return 0;
172 
173 	start = ut_check_free();
174 
175 	/* Try an impossible size */
176 	abuf_init(&buf);
177 	ut_asserteq(false, abuf_realloc(&buf, CONFIG_SYS_MALLOC_LEN));
178 	ut_assertnull(buf.data);
179 	ut_asserteq(0, buf.size);
180 	ut_asserteq(false, buf.alloced);
181 
182 	abuf_uninit(&buf);
183 	ut_assertnull(buf.data);
184 	ut_asserteq(0, buf.size);
185 	ut_asserteq(false, buf.alloced);
186 
187 	/* Start with a normal size then try to increase it, to check realloc */
188 	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
189 	ut_assertnonnull(buf.data);
190 	ut_asserteq(TEST_DATA_LEN, buf.size);
191 	ut_asserteq(true, buf.alloced);
192 	ptr = buf.data;
193 	delta = ut_check_delta(start);
194 	ut_assert(delta > 0);
195 
196 	/* try to increase it */
197 	ut_asserteq(false, abuf_realloc(&buf, CONFIG_SYS_MALLOC_LEN));
198 	ut_asserteq_ptr(ptr, buf.data);
199 	ut_asserteq(TEST_DATA_LEN, buf.size);
200 	ut_asserteq(true, buf.alloced);
201 	ut_asserteq(delta, ut_check_delta(start));
202 
203 	/* Check for memory leaks */
204 	abuf_uninit(&buf);
205 	ut_assertok(ut_check_delta(start));
206 
207 	/* Start with a huge unallocated buf and try to move it */
208 	abuf_init(&buf);
209 	abuf_map_sysmem(&buf, 0, CONFIG_SYS_MALLOC_LEN);
210 	ut_asserteq(CONFIG_SYS_MALLOC_LEN, buf.size);
211 	ut_asserteq(false, buf.alloced);
212 	ut_assertnull(abuf_uninit_move(&buf, &size));
213 
214 	/* Check for memory leaks */
215 	abuf_uninit(&buf);
216 	ut_assertok(ut_check_delta(start));
217 
218 	return 0;
219 }
220 LIB_TEST(lib_test_abuf_large, 0);
221 
222 /* Test abuf_uninit_move() */
lib_test_abuf_uninit_move(struct unit_test_state * uts)223 static int lib_test_abuf_uninit_move(struct unit_test_state *uts)
224 {
225 	void *ptr, *orig_ptr;
226 	struct abuf buf;
227 	size_t size;
228 	ulong start;
229 	int delta;
230 
231 	start = ut_check_free();
232 
233 	/*
234 	 * TODO: crashes on sandbox sometimes due to an apparent bug in
235 	 * realloc().
236 	 */
237 	return 0;
238 
239 	/* Move an empty buffer */
240 	abuf_init(&buf);
241 	ut_assertnull(abuf_uninit_move(&buf, &size));
242 	ut_asserteq(0, size);
243 	ut_assertnull(abuf_uninit_move(&buf, NULL));
244 
245 	/* Move an unallocated buffer */
246 	abuf_set(&buf, test_data, TEST_DATA_LEN);
247 	ut_assertok(ut_check_delta(start));
248 	ptr = abuf_uninit_move(&buf, &size);
249 	ut_asserteq(TEST_DATA_LEN, size);
250 	ut_asserteq_str(ptr, test_data);
251 	ut_assertnonnull(ptr);
252 	ut_assertnull(buf.data);
253 	ut_asserteq(0, buf.size);
254 	ut_asserteq(false, buf.alloced);
255 
256 	/* Check that freeing it frees the only allocation */
257 	delta = ut_check_delta(start);
258 	ut_assert(delta > 0);
259 	free(ptr);
260 	ut_assertok(ut_check_delta(start));
261 
262 	/* Move an allocated buffer */
263 	ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN));
264 	orig_ptr = buf.data;
265 	strcpy(orig_ptr, test_data);
266 
267 	delta = ut_check_delta(start);
268 	ut_assert(delta > 0);
269 	ptr = abuf_uninit_move(&buf, &size);
270 	ut_asserteq(TEST_DATA_LEN, size);
271 	ut_assertnonnull(ptr);
272 	ut_asserteq_ptr(ptr, orig_ptr);
273 	ut_asserteq_str(ptr, test_data);
274 	ut_assertnull(buf.data);
275 	ut_asserteq(0, buf.size);
276 	ut_asserteq(false, buf.alloced);
277 
278 	/* Check there was no new allocation */
279 	ut_asserteq(delta, ut_check_delta(start));
280 
281 	/* Check that freeing it frees the only allocation */
282 	free(ptr);
283 	ut_assertok(ut_check_delta(start));
284 
285 	/* Move an unallocated buffer, without the size */
286 	abuf_set(&buf, test_data, TEST_DATA_LEN);
287 	ut_assertok(ut_check_delta(start));
288 	ptr = abuf_uninit_move(&buf, NULL);
289 	ut_asserteq_str(ptr, test_data);
290 
291 	return 0;
292 }
293 LIB_TEST(lib_test_abuf_uninit_move, 0);
294 
295 /* Test abuf_uninit() */
lib_test_abuf_uninit(struct unit_test_state * uts)296 static int lib_test_abuf_uninit(struct unit_test_state *uts)
297 {
298 	struct abuf buf;
299 
300 	/* Nothing in the buffer */
301 	abuf_init(&buf);
302 	abuf_uninit(&buf);
303 	ut_assertnull(buf.data);
304 	ut_asserteq(0, buf.size);
305 	ut_asserteq(false, buf.alloced);
306 
307 	/* Not allocated */
308 	abuf_set(&buf, test_data, TEST_DATA_LEN);
309 	abuf_uninit(&buf);
310 	ut_assertnull(buf.data);
311 	ut_asserteq(0, buf.size);
312 	ut_asserteq(false, buf.alloced);
313 
314 	return 0;
315 }
316 LIB_TEST(lib_test_abuf_uninit, 0);
317 
318 /* Test abuf_init_set() */
lib_test_abuf_init_set(struct unit_test_state * uts)319 static int lib_test_abuf_init_set(struct unit_test_state *uts)
320 {
321 	struct abuf buf;
322 
323 	abuf_init_set(&buf, test_data, TEST_DATA_LEN);
324 	ut_asserteq_ptr(test_data, buf.data);
325 	ut_asserteq(TEST_DATA_LEN, buf.size);
326 	ut_asserteq(false, buf.alloced);
327 
328 	return 0;
329 }
330 LIB_TEST(lib_test_abuf_init_set, 0);
331 
332 /* Test abuf_init_move() */
lib_test_abuf_init_move(struct unit_test_state * uts)333 static int lib_test_abuf_init_move(struct unit_test_state *uts)
334 {
335 	struct abuf buf;
336 	void *ptr;
337 
338 	/*
339 	 * TODO: crashes on sandbox sometimes due to an apparent bug in
340 	 * realloc().
341 	 */
342 	return 0;
343 
344 	ptr = strdup(test_data);
345 	ut_assertnonnull(ptr);
346 
347 	free(ptr);
348 
349 	abuf_init_move(&buf, ptr, TEST_DATA_LEN);
350 	ut_asserteq_ptr(ptr, abuf_data(&buf));
351 	ut_asserteq(TEST_DATA_LEN, abuf_size(&buf));
352 	ut_asserteq(true, buf.alloced);
353 
354 	return 0;
355 }
356 LIB_TEST(lib_test_abuf_init_move, 0);
357 
358 /* Test abuf_init() */
lib_test_abuf_init(struct unit_test_state * uts)359 static int lib_test_abuf_init(struct unit_test_state *uts)
360 {
361 	struct abuf buf;
362 
363 	buf.data = &buf;
364 	buf.size = 123;
365 	buf.alloced = true;
366 	abuf_init(&buf);
367 	ut_assertnull(buf.data);
368 	ut_asserteq(0, buf.size);
369 	ut_asserteq(false, buf.alloced);
370 
371 	return 0;
372 }
373 LIB_TEST(lib_test_abuf_init, 0);
374