Skip to content

Commit bb3a401

Browse files
dobangelinaAngelina Dobardzieva
andauthored
unit-test: Add unit tests for heap management module (#122)
Adds 16 unit tests. In addition, adds mocks for malloc, calloc and free which are used to support the unit tests. Also creates a heap_management.h file. Updates CMakeLists.txt files to allow tests to run. Signed-off-by: Angelina Dobardzieva <[email protected]> Co-authored-by: Angelina Dobardzieva <[email protected]>
1 parent 55da3cc commit bb3a401

File tree

10 files changed

+358
-8
lines changed

10 files changed

+358
-8
lines changed

components/freertos_kernel/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2023-2024 Arm Limited and/or its affiliates
1+
# Copyright 2023-2025 Arm Limited and/or its affiliates
22
33
# SPDX-License-Identifier: MIT
44

@@ -29,6 +29,9 @@ else()
2929
$<$<STREQUAL:${ARM_CORSTONE_BSP_TARGET_PLATFORM},corstone310>:${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone310/include>
3030
$<$<STREQUAL:${ARM_CORSTONE_BSP_TARGET_PLATFORM},corstone315>:${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone315/include>
3131
$<$<STREQUAL:${ARM_CORSTONE_BSP_TARGET_PLATFORM},corstone320>:${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone320/include>
32+
${CMAKE_CURRENT_LIST_DIR}/integration/inc
3233
)
3334
add_subdirectory(library)
3435
endif()
36+
37+
add_subdirectory(integration)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2025 Arm Limited and/or its affiliates
2+
3+
# SPDX-License-Identifier: MIT
4+
5+
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
6+
7+
add_library(heap-management
8+
STATIC
9+
src/heap_management.c
10+
)
11+
12+
target_include_directories(heap-management
13+
PRIVATE
14+
inc
15+
)
16+
17+
if(BUILD_TESTING AND NOT CMAKE_CROSSCOMPILING)
18+
add_subdirectory(tests)
19+
endif()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/* Copyright 2025 Arm Limited and/or its affiliates
2+
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
6+
/**
7+
* @file heap_management.h
8+
* @brief Thin wrappers around the C library used by the integration code.
9+
*/
10+
#ifndef HEAP_MANAGEMENT_H
11+
#define HEAP_MANAGEMENT_H
12+
13+
#include <stddef.h>
14+
15+
#ifdef __cplusplus
16+
extern "C" {
17+
#endif
18+
19+
/**
20+
* @brief Wrapper for the C libraries malloc
21+
* @param xWantedSize The number of bytes to be allocated
22+
* @return Either a non-NULL pointer to a block of memory on success, or NULL on failure
23+
*/
24+
void * pvPortMalloc( size_t xWantedSize );
25+
26+
/**
27+
* @brief Wrapper for the C libraries free function
28+
* @param pv Pointer to a memory location to be freed, or NULL
29+
*/
30+
void vPortFree( void * pv );
31+
32+
/**
33+
* @brief Wrapper for the C libraries calloc
34+
* @param xNum The number of elements
35+
* @param xSize The size of each element in bytes
36+
* @return Either a non-NULL pointer to a block of memory on success, or NULL on failure
37+
*/
38+
void * pvPortCalloc( size_t xNum,
39+
size_t xSize );
40+
41+
/**
42+
* @brief A dummy implementation as C standard library does not provide
43+
* functions to get the statistics of heap memory.
44+
* @return Always 0 in the integration build
45+
* @note These dummy implementation are needed
46+
* as this API is used as part of FreeRTOS Plus TCP code which is unused in the
47+
* FRI code (removed by the linker) but ARMClang linker requires all the compiled
48+
* symbols to be defined.
49+
*/
50+
size_t xPortGetFreeHeapSize( void );
51+
52+
/**
53+
* @brief A dummy implementation as C standard library does not provide
54+
* functions to get the statistics of heap memory.
55+
* @return Always 0 in the integration build
56+
* @note These dummy implementation are needed
57+
* as this API is used as part of FreeRTOS Plus TCP code which is unused in the
58+
* FRI code (removed by the linker) but ARMClang linker requires all the compiled
59+
* symbols to be defined.
60+
*/
61+
size_t xPortGetMinimumEverFreeHeapSize( void );
62+
63+
#ifdef __cplusplus
64+
}
65+
#endif
66+
67+
#endif /* HEAP_MANAGEMENT_H */

components/freertos_kernel/integration/src/heap_management.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
/* Copyright 2024 Arm Limited and/or its affiliates
1+
/* Copyright 2024-2025 Arm Limited and/or its affiliates
22
33
* SPDX-License-Identifier: MIT
44
*/
55

6+
#include "heap_management.h"
67
#include <stdlib.h>
78

89
void * pvPortMalloc( size_t xWantedSize )
@@ -21,11 +22,6 @@ void * pvPortCalloc( size_t xNum,
2122
return calloc( xNum, xSize );
2223
}
2324

24-
/* These are dummy implementations as C standard library does not provide
25-
* functions to get the statistics of heap memory. These dummy implementation are needed
26-
* as these APIs are used as part of FreeRTOS Plus TCP code which is unused in the FRI code (removed by the linker)
27-
* but ARMClang linker requires all the compiled symbols to be defined.
28-
*/
2925
size_t xPortGetFreeHeapSize( void )
3026
{
3127
return 0;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2025 Arm Limited and/or its affiliates
2+
3+
# SPDX-License-Identifier: MIT
4+
5+
cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR)
6+
7+
add_executable(heap-management-test
8+
test_heap_management.cpp
9+
)
10+
11+
target_include_directories(heap-management-test
12+
PRIVATE
13+
../inc
14+
../../library_mocks/inc
15+
)
16+
17+
target_link_libraries(heap-management-test
18+
PRIVATE
19+
fff
20+
freertos-kernel-mock
21+
heap-management
22+
)
23+
24+
target_link_options(heap-management-test
25+
PRIVATE
26+
-Wl,--wrap=malloc
27+
-Wl,--wrap=calloc
28+
-Wl,--wrap=free
29+
)
30+
31+
iot_reference_arm_corstone3xx_add_test(heap-management-test)
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/* Copyright 2025 Arm Limited and/or its affiliates
2+
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
6+
#include "gtest/gtest.h"
7+
#include <stdint.h>
8+
9+
extern "C" {
10+
#include "heap_management.h"
11+
#include "alloc_fakes.h"
12+
}
13+
14+
class TestHeapManagement : public ::testing::Test {
15+
public:
16+
TestHeapManagement()
17+
{
18+
RESET_FAKE( test_malloc );
19+
RESET_FAKE( test_calloc );
20+
RESET_FAKE( test_free );
21+
}
22+
};
23+
24+
TEST_F( TestHeapManagement, calls_malloc_and_returns_same_pointer )
25+
{
26+
static uint8_t dummy[ 32 ];
27+
28+
test_malloc_fake.return_val = dummy;
29+
void * allocated_ptr = pvPortMalloc( 32 );
30+
ASSERT_EQ( allocated_ptr, static_cast<void *>( dummy ) );
31+
32+
EXPECT_EQ( test_malloc_fake.call_count, 1 );
33+
EXPECT_EQ( test_malloc_fake.arg0_val, static_cast<size_t>( 32 ) );
34+
}
35+
36+
TEST_F( TestHeapManagement, calling_malloc_with_size_zero_may_return_null )
37+
{
38+
test_malloc_fake.return_val = nullptr;
39+
void * allocated_ptr = pvPortMalloc( 0 );
40+
ASSERT_EQ( allocated_ptr, nullptr );
41+
42+
EXPECT_EQ( test_malloc_fake.call_count, 1 );
43+
EXPECT_EQ( test_malloc_fake.arg0_val, static_cast<size_t>( 0 ) );
44+
}
45+
46+
TEST_F( TestHeapManagement, calling_malloc_with_size_zero_may_return_pointer )
47+
{
48+
static uint8_t dummy[ 1 ];
49+
50+
test_malloc_fake.return_val = dummy;
51+
void * allocated_ptr = pvPortMalloc( 0 );
52+
ASSERT_EQ( allocated_ptr, static_cast<void *>( dummy ) );
53+
54+
EXPECT_EQ( test_malloc_fake.call_count, 1 );
55+
EXPECT_EQ( test_malloc_fake.arg0_val, static_cast<size_t>( 0 ) );
56+
}
57+
58+
TEST_F( TestHeapManagement, returns_null_when_malloc_fails )
59+
{
60+
test_malloc_fake.return_val = nullptr;
61+
void * allocated_ptr = pvPortMalloc( 64 );
62+
ASSERT_EQ( allocated_ptr, nullptr );
63+
64+
EXPECT_EQ( test_malloc_fake.call_count, 1 );
65+
EXPECT_EQ( test_malloc_fake.arg0_val, static_cast<size_t>( 64 ) );
66+
}
67+
68+
TEST_F( TestHeapManagement, calls_free_with_same_pointer )
69+
{
70+
static uint8_t dummy[ 16 ];
71+
void * allocated_ptr = static_cast<void *>( dummy );
72+
73+
vPortFree( allocated_ptr );
74+
75+
EXPECT_EQ( test_free_fake.call_count, 1 );
76+
EXPECT_EQ( test_free_fake.arg0_val, allocated_ptr );
77+
}
78+
79+
TEST_F( TestHeapManagement, calls_free_with_null )
80+
{
81+
vPortFree( nullptr );
82+
EXPECT_EQ( test_free_fake.call_count, 1 );
83+
EXPECT_EQ( test_free_fake.arg0_val, nullptr );
84+
}
85+
86+
TEST_F( TestHeapManagement, calls_calloc_and_returns_same_pointer )
87+
{
88+
static uint64_t dummy[ 4 ];
89+
90+
test_calloc_fake.return_val = dummy;
91+
void * allocated_ptr = pvPortCalloc( 4, 8 );
92+
ASSERT_EQ( allocated_ptr, static_cast<void *>( dummy ) );
93+
94+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
95+
EXPECT_EQ( test_calloc_fake.arg0_val, 4 );
96+
EXPECT_EQ( test_calloc_fake.arg1_val, 8 );
97+
}
98+
99+
TEST_F( TestHeapManagement, calling_calloc_with_num_zero_may_return_null )
100+
{
101+
test_calloc_fake.return_val = nullptr;
102+
void * allocated_ptr = pvPortCalloc( 0, 8 );
103+
ASSERT_EQ( allocated_ptr, nullptr );
104+
105+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
106+
EXPECT_EQ( test_calloc_fake.arg0_val, 0 );
107+
EXPECT_EQ( test_calloc_fake.arg1_val, 8 );
108+
}
109+
110+
TEST_F( TestHeapManagement, calling_calloc_with_num_zero_may_return_pointer )
111+
{
112+
static uint8_t dummy[ 1 ];
113+
114+
test_calloc_fake.return_val = dummy;
115+
void * allocated_ptr = pvPortCalloc( 0, 8 );
116+
ASSERT_EQ( allocated_ptr, static_cast<void *>( dummy ) );
117+
118+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
119+
EXPECT_EQ( test_calloc_fake.arg0_val, 0 );
120+
EXPECT_EQ( test_calloc_fake.arg1_val, 8 );
121+
}
122+
123+
TEST_F( TestHeapManagement, calling_calloc_with_size_zero_may_return_null )
124+
{
125+
test_calloc_fake.return_val = nullptr;
126+
void * allocated_ptr = pvPortCalloc( 8, 0 );
127+
ASSERT_EQ( allocated_ptr, nullptr );
128+
129+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
130+
EXPECT_EQ( test_calloc_fake.arg0_val, 8 );
131+
EXPECT_EQ( test_calloc_fake.arg1_val, 0 );
132+
}
133+
134+
TEST_F( TestHeapManagement, calling_calloc_with_size_zero_may_return_pointer )
135+
{
136+
static uint8_t dummy[ 1 ];
137+
138+
test_calloc_fake.return_val = dummy;
139+
void * allocated_ptr = pvPortCalloc( 8, 0 );
140+
ASSERT_EQ( allocated_ptr, static_cast<void *>( dummy ) );
141+
142+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
143+
EXPECT_EQ( test_calloc_fake.arg0_val, 8 );
144+
EXPECT_EQ( test_calloc_fake.arg1_val, 0 );
145+
}
146+
147+
TEST_F( TestHeapManagement, calling_calloc_zero_zero_may_return_null )
148+
{
149+
test_calloc_fake.return_val = nullptr;
150+
void * allocated_ptr = pvPortCalloc( 0, 0 );
151+
ASSERT_EQ( allocated_ptr, nullptr );
152+
153+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
154+
EXPECT_EQ( test_calloc_fake.arg0_val, 0 );
155+
EXPECT_EQ( test_calloc_fake.arg1_val, 0 );
156+
}
157+
158+
TEST_F( TestHeapManagement, calling_calloc_zero_zero_may_return_pointer )
159+
{
160+
static uint8_t dummy[ 1 ];
161+
162+
test_calloc_fake.return_val = dummy;
163+
void * allocated_ptr = pvPortCalloc( 0, 0 );
164+
ASSERT_EQ( allocated_ptr, static_cast<void *>( dummy ) );
165+
166+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
167+
EXPECT_EQ( test_calloc_fake.arg0_val, 0 );
168+
EXPECT_EQ( test_calloc_fake.arg1_val, 0 );
169+
}
170+
171+
TEST_F( TestHeapManagement, returns_null_when_calloc_fails )
172+
{
173+
test_calloc_fake.return_val = nullptr;
174+
void * allocated_ptr = pvPortCalloc( 16, 8 );
175+
ASSERT_EQ( allocated_ptr, nullptr );
176+
177+
EXPECT_EQ( test_calloc_fake.call_count, 1 );
178+
EXPECT_EQ( test_calloc_fake.arg0_val, 16 );
179+
EXPECT_EQ( test_calloc_fake.arg1_val, 8 );
180+
}
181+
182+
TEST_F( TestHeapManagement, xPortGetFreeHeapSize_returns_zero )
183+
{
184+
ASSERT_EQ( xPortGetFreeHeapSize(), 0 );
185+
}
186+
187+
TEST_F( TestHeapManagement, xPortGetMinimumEverFreeHeapSize_returns_zero )
188+
{
189+
ASSERT_EQ( xPortGetMinimumEverFreeHeapSize(), 0 );
190+
}

components/freertos_kernel/library_mocks/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2023-2024 Arm Limited and/or its affiliates
1+
# Copyright 2023-2025 Arm Limited and/or its affiliates
22
33
# SPDX-License-Identifier: MIT
44

@@ -7,6 +7,7 @@ add_library(freertos-kernel-mock
77
src/semphr.c
88
src/tasks.c
99
src/queue.c
10+
src/alloc_fakes.c
1011
)
1112

1213
target_include_directories(freertos-kernel-mock
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* Copyright 2025 Arm Limited and/or its affiliates
2+
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
6+
#ifndef ALLOC_FAKES_H
7+
#define ALLOC_FAKES_H
8+
9+
#include <stddef.h>
10+
#include "fff.h"
11+
12+
DECLARE_FAKE_VALUE_FUNC( void *, test_malloc, size_t );
13+
DECLARE_FAKE_VALUE_FUNC( void *, test_calloc, size_t, size_t );
14+
DECLARE_FAKE_VOID_FUNC( test_free, void * );
15+
16+
#endif /* ALLOC_FAKES_H*/

0 commit comments

Comments
 (0)