Patrick Georgi has submitted this change. ( https://review.coreboot.org/c/coreboot/+/50715 )
Change subject: tests: Add lib/malloc-test test case ......................................................................
tests: Add lib/malloc-test test case
Signed-off-by: Jakub Czapiga jacz@semihalf.com Change-Id: Ic6b10ec382cc807772689e852bad300c75da1fe2 Reviewed-on: https://review.coreboot.org/c/coreboot/+/50715 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Paul Fagerburg pfagerburg@chromium.org --- M tests/lib/Makefile.inc A tests/lib/malloc-test.c 2 files changed, 150 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Paul Fagerburg: Looks good to me, approved
diff --git a/tests/lib/Makefile.inc b/tests/lib/Makefile.inc index 1640ce0..d31608c 100644 --- a/tests/lib/Makefile.inc +++ b/tests/lib/Makefile.inc @@ -18,6 +18,7 @@ tests-y += memcmp-test tests-y += memchr-test tests-y += memcpy-test +tests-y += malloc-test
string-test-srcs += tests/lib/string-test.c string-test-srcs += src/lib/string.c @@ -91,3 +92,6 @@
memcpy-test-srcs += tests/lib/memcpy-test.c
+malloc-test-srcs += tests/lib/malloc-test.c +malloc-test-srcs += tests/stubs/console.c + diff --git a/tests/lib/malloc-test.c b/tests/lib/malloc-test.c new file mode 100644 index 0000000..e358fff --- /dev/null +++ b/tests/lib/malloc-test.c @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* Include malloc() and memalign() source code and alter its name to indicate the functions + source origin. */ +#define malloc cb_malloc +#define free cb_free +#define memalign cb_memalign +#undef __noreturn +#define __noreturn + +#include "../lib/malloc.c" + +#undef malloc +#undef free +#undef memalign +#undef __noreturn +#define __noreturn __attribute__((noreturn)) + +#include <stdlib.h> +#include <tests/test.h> +#include <commonlib/helpers.h> +#include <types.h> +#include <symbols.h> + +/* 4 MiB */ +#define TEST_HEAP_SZ 0x400000 + +/* Heap region setup */ +__weak extern uint8_t _test_heap[]; +__weak extern uint8_t _etest_heap[]; +TEST_REGION(test_heap, TEST_HEAP_SZ); +TEST_SYMBOL(_heap, _test_heap); +TEST_SYMBOL(_eheap, _etest_heap); + +void die(const char *msg, ...) +{ + function_called(); +} + +static int setup_test(void **state) +{ + free_mem_ptr = &_heap; + free_mem_end_ptr = &_eheap; + free_last_alloc_ptr = &_heap; + + return 0; +} + +static void test_malloc_out_of_memory(void **state) +{ + /* Expect die() call if out of memory */ + expect_function_call(die); + cb_malloc(TEST_HEAP_SZ); +} + +static void test_malloc_zero(void **state) +{ + void *ptr1 = cb_malloc(0); + void *ptr2 = cb_malloc(0); + void *ptr3 = cb_malloc(0); + + /* Expect malloc(0) to return the same pointer as there are no bytes + to be added to the heap */ + assert_ptr_equal(ptr1, ptr2); + assert_ptr_equal(ptr2, ptr3); +} + +static void test_malloc_multiple_small_allocations(void **state) +{ + /* Make multiple small allocations (smaller than alignment) + Expect no call to die(), as this allocations should be small + enough to fit in provided memory */ + void *prev; + void *curr = cb_malloc(3); + assert_non_null(curr); + for (int i = 0; i < 1000; ++i) { + prev = curr; + curr = cb_malloc(3); + assert_non_null(curr); + assert_true(prev < curr); + } +} + +static void test_memalign_different_alignments(void **state) +{ + void *ptr1 = cb_memalign(4, 30); + void *ptr2 = cb_memalign(16, 22); + void *ptr3 = cb_memalign(8, 64); + + assert_true((uintptr_t)ptr1 % 4 == 0); + assert_true((uintptr_t)ptr2 % 16 == 0); + assert_true((uintptr_t)ptr3 % 8 == 0); +} + +static void test_memalign_out_of_memory(void **state) +{ + expect_function_call(die); + cb_memalign(16, TEST_HEAP_SZ); +} + +static void test_memalign_zero(void **state) +{ + void *ptr1 = cb_memalign(16, 0); + void *ptr2 = cb_memalign(7, 0); + void *ptr3 = cb_memalign(11, 0); + + /* Expect memalign(x, 0) to return the same pointer as there are no bytes + to be added to the heap */ + assert_ptr_equal(ptr1, ptr2); + assert_ptr_equal(ptr2, ptr3); +} + +static void test_memalign_multiple_small_allocations(void **state) +{ + /* Make multiple small allocations (smaller than alignment) + Expect no call to die(), as this allocations should be small + enough to fit in provided memory. There should also be no error + when allocating memory with different align values. */ + void *prev; + void *curr = cb_memalign(3, 3); + assert_non_null(curr); + for (int i = 0; i < 1000; ++i) { + /* Expect new pointer larger than previously allocated and aligned to provided + value. Alignment has to be power of 2 to be applied correctly. */ + prev = curr; + curr = cb_memalign(2u << (i % 6), 3); + assert_non_null(curr); + assert_true(prev < curr); + assert_true((uintptr_t)curr % (2u << (i % 6)) == 0); + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup(test_malloc_out_of_memory, setup_test), + cmocka_unit_test_setup(test_malloc_zero, setup_test), + cmocka_unit_test_setup(test_malloc_multiple_small_allocations, setup_test), + cmocka_unit_test_setup(test_memalign_different_alignments, setup_test), + cmocka_unit_test_setup(test_memalign_out_of_memory, setup_test), + cmocka_unit_test_setup(test_memalign_zero, setup_test), + cmocka_unit_test_setup(test_memalign_multiple_small_allocations, setup_test), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +}