blob: f5d528e1c4f5acf0249e60512114ff48ebfe7965 [file] [log] [blame]
Jakub Czapiga7a187212021-02-15 09:54:03 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3/* Include malloc() and memalign() source code and alter its name to indicate the functions
4 source origin. */
Tim Wawrzynczakc556dff2021-03-30 11:49:14 -06005#define calloc cb_calloc
Jakub Czapiga7a187212021-02-15 09:54:03 +01006#define malloc cb_malloc
7#define free cb_free
8#define memalign cb_memalign
9#undef __noreturn
10#define __noreturn
11
12#include "../lib/malloc.c"
13
Tim Wawrzynczakc556dff2021-03-30 11:49:14 -060014#undef calloc
Jakub Czapiga7a187212021-02-15 09:54:03 +010015#undef malloc
16#undef free
17#undef memalign
18#undef __noreturn
19#define __noreturn __attribute__((noreturn))
20
21#include <stdlib.h>
22#include <tests/test.h>
23#include <commonlib/helpers.h>
24#include <types.h>
25#include <symbols.h>
26
27/* 4 MiB */
28#define TEST_HEAP_SZ 0x400000
29
30/* Heap region setup */
31__weak extern uint8_t _test_heap[];
32__weak extern uint8_t _etest_heap[];
33TEST_REGION(test_heap, TEST_HEAP_SZ);
34TEST_SYMBOL(_heap, _test_heap);
35TEST_SYMBOL(_eheap, _etest_heap);
36
Jakub Czapiga7a187212021-02-15 09:54:03 +010037static int setup_test(void **state)
38{
39 free_mem_ptr = &_heap;
40 free_mem_end_ptr = &_eheap;
41 free_last_alloc_ptr = &_heap;
42
43 return 0;
44}
45
Tim Wawrzynczakc556dff2021-03-30 11:49:14 -060046static int setup_calloc_test(void **state)
47{
Jakub Czapiga13145e52021-04-06 18:27:30 +020048 memset(_test_heap, 0xFF, TEST_HEAP_SZ);
Tim Wawrzynczakc556dff2021-03-30 11:49:14 -060049 return setup_test(state);
50}
51
Jakub Czapiga7a187212021-02-15 09:54:03 +010052static void test_malloc_out_of_memory(void **state)
53{
Patrick Georgic59426f2024-01-26 19:47:29 +010054 void *ptr = cb_malloc(TEST_HEAP_SZ);
55 assert_ptr_equal(ptr, NULL);
Jakub Czapiga7a187212021-02-15 09:54:03 +010056}
57
58static void test_malloc_zero(void **state)
59{
60 void *ptr1 = cb_malloc(0);
61 void *ptr2 = cb_malloc(0);
62 void *ptr3 = cb_malloc(0);
63
64 /* Expect malloc(0) to return the same pointer as there are no bytes
65 to be added to the heap */
66 assert_ptr_equal(ptr1, ptr2);
67 assert_ptr_equal(ptr2, ptr3);
68}
69
70static void test_malloc_multiple_small_allocations(void **state)
71{
72 /* Make multiple small allocations (smaller than alignment)
73 Expect no call to die(), as this allocations should be small
74 enough to fit in provided memory */
75 void *prev;
76 void *curr = cb_malloc(3);
77 assert_non_null(curr);
78 for (int i = 0; i < 1000; ++i) {
79 prev = curr;
80 curr = cb_malloc(3);
81 assert_non_null(curr);
82 assert_true(prev < curr);
83 }
84}
85
86static void test_memalign_different_alignments(void **state)
87{
88 void *ptr1 = cb_memalign(4, 30);
89 void *ptr2 = cb_memalign(16, 22);
90 void *ptr3 = cb_memalign(8, 64);
91
92 assert_true((uintptr_t)ptr1 % 4 == 0);
93 assert_true((uintptr_t)ptr2 % 16 == 0);
94 assert_true((uintptr_t)ptr3 % 8 == 0);
95}
96
97static void test_memalign_out_of_memory(void **state)
98{
Patrick Georgic59426f2024-01-26 19:47:29 +010099 void *ptr = cb_memalign(16, TEST_HEAP_SZ);
100 assert_ptr_equal(ptr, NULL);
Jakub Czapiga7a187212021-02-15 09:54:03 +0100101}
102
103static void test_memalign_zero(void **state)
104{
105 void *ptr1 = cb_memalign(16, 0);
106 void *ptr2 = cb_memalign(7, 0);
107 void *ptr3 = cb_memalign(11, 0);
108
109 /* Expect memalign(x, 0) to return the same pointer as there are no bytes
110 to be added to the heap */
111 assert_ptr_equal(ptr1, ptr2);
112 assert_ptr_equal(ptr2, ptr3);
113}
114
115static void test_memalign_multiple_small_allocations(void **state)
116{
117 /* Make multiple small allocations (smaller than alignment)
118 Expect no call to die(), as this allocations should be small
119 enough to fit in provided memory. There should also be no error
120 when allocating memory with different align values. */
121 void *prev;
122 void *curr = cb_memalign(3, 3);
123 assert_non_null(curr);
124 for (int i = 0; i < 1000; ++i) {
125 /* Expect new pointer larger than previously allocated and aligned to provided
126 value. Alignment has to be power of 2 to be applied correctly. */
127 prev = curr;
128 curr = cb_memalign(2u << (i % 6), 3);
129 assert_non_null(curr);
130 assert_true(prev < curr);
131 assert_true((uintptr_t)curr % (2u << (i % 6)) == 0);
132 }
133}
134
Tim Wawrzynczakc556dff2021-03-30 11:49:14 -0600135static void test_calloc_memory_is_zeroed(void **state)
136{
137 const size_t nitems = 42;
138 const size_t size = sizeof(uint32_t);
139 void *ptr = cb_calloc(nitems, size);
140 assert_non_null(ptr);
141
142 for (size_t i = 0; i < nitems; i++) {
143 const uint32_t *p = (const uint32_t *)ptr + i;
144 assert_int_equal(*p, 0);
145 }
146}
147
Jakub Czapiga7a187212021-02-15 09:54:03 +0100148int main(void)
149{
150 const struct CMUnitTest tests[] = {
151 cmocka_unit_test_setup(test_malloc_out_of_memory, setup_test),
152 cmocka_unit_test_setup(test_malloc_zero, setup_test),
153 cmocka_unit_test_setup(test_malloc_multiple_small_allocations, setup_test),
154 cmocka_unit_test_setup(test_memalign_different_alignments, setup_test),
155 cmocka_unit_test_setup(test_memalign_out_of_memory, setup_test),
156 cmocka_unit_test_setup(test_memalign_zero, setup_test),
157 cmocka_unit_test_setup(test_memalign_multiple_small_allocations, setup_test),
Tim Wawrzynczakc556dff2021-03-30 11:49:14 -0600158 cmocka_unit_test_setup(test_calloc_memory_is_zeroed, setup_calloc_test),
Jakub Czapiga7a187212021-02-15 09:54:03 +0100159 };
160
Jakub Czapiga7c6081e2021-08-25 16:27:35 +0200161 return cb_run_group_tests(tests, NULL, NULL);
Jakub Czapiga7a187212021-02-15 09:54:03 +0100162}