summaryrefslogtreecommitdiff
path: root/tests/lib/malloc-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/malloc-test.c')
-rw-r--r--tests/lib/malloc-test.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/tests/lib/malloc-test.c b/tests/lib/malloc-test.c
new file mode 100644
index 0000000000..e358fffd3b
--- /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);
+}