Skip to content

Commit a7f31c9

Browse files
malloc test refactoring
1 parent 1394bf9 commit a7f31c9

File tree

1 file changed

+112
-31
lines changed
  • TESTS/mbedmicro-rtos-mbed/malloc

1 file changed

+112
-31
lines changed

TESTS/mbedmicro-rtos-mbed/malloc/main.cpp

Lines changed: 112 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,80 +14,161 @@
1414
* limitations under the License.
1515
*/
1616
#include "mbed.h"
17-
#include "test_env.h"
18-
#include "rtos.h"
17+
#include "greentea-client/test_env.h"
18+
#include "utest/utest.h"
19+
#include "unity/unity.h"
20+
1921

2022
#if defined(MBED_RTOS_SINGLE_THREAD)
2123
#error [NOT_SUPPORTED] test not supported
2224
#endif
2325

24-
#define NUM_THREADS 5
26+
using utest::v1::Case;
27+
28+
extern uint32_t mbed_heap_size;
29+
static const int test_timeout = 25;
30+
volatile bool thread_should_continue = true;
31+
#define NUM_THREADS 4
32+
#define THREAD_MALLOC_SIZE 100
2533

2634
#if defined(__CORTEX_A9)
2735
#define THREAD_STACK_SIZE DEFAULT_STACK_SIZE
2836
#else
2937
#define THREAD_STACK_SIZE 256
3038
#endif
3139

32-
DigitalOut led1(LED1);
33-
volatile bool should_exit = false;
34-
volatile bool allocation_failure = false;
3540

3641
void task_using_malloc(void)
3742
{
38-
void* data;
39-
while (1) {
43+
void *data = NULL;
44+
45+
while (thread_should_continue) {
4046
// Repeatedly allocate and free memory
41-
data = malloc(100);
42-
if (data != NULL) {
43-
memset(data, 0, 100);
44-
} else {
45-
allocation_failure = true;
46-
}
47-
free(data);
47+
data = malloc(THREAD_MALLOC_SIZE);
48+
TEST_ASSERT_NOT_NULL(data);
4849

49-
if (should_exit) {
50-
return;
51-
}
50+
// test whole allocated memory
51+
memset(data, 0, THREAD_MALLOC_SIZE);
52+
53+
free(data);
5254
}
5355
}
5456

55-
int main()
57+
/** Test for multithreaded heap allocations
58+
59+
Given multiple threads are started in parallel
60+
When each of the threads allocate memory
61+
Then the memory allocation succeed and @a malloc return valid memory
62+
*/
63+
void test_multithread_allocation(void)
5664
{
5765
// static stack for threads to reduce heap usage on devices with small RAM
5866
// and eliminate run out of heap memory problem
5967
uint8_t stack[NUM_THREADS][THREAD_STACK_SIZE];
6068

69+
bool thread_alloc_failure = false;
6170
Thread *thread_list[NUM_THREADS];
62-
int test_time = 15;
63-
GREENTEA_SETUP(20, "default_auto");
71+
int test_time = 20;
6472

6573
// Allocate threads for the test
6674
for (int i = 0; i < NUM_THREADS; i++) {
6775
thread_list[i] = new Thread(osPriorityNormal, THREAD_STACK_SIZE, stack[i]);
6876
if (NULL == thread_list[i]) {
69-
allocation_failure = true;
77+
thread_alloc_failure = true;
7078
} else {
7179
thread_list[i]->start(task_using_malloc);
7280
}
7381
}
7482

7583
// Give the test time to run
76-
while (test_time) {
77-
led1 = !led1;
84+
while (test_time--) {
7885
Thread::wait(1000);
79-
test_time--;
8086
}
8187

8288
// Join and delete all threads
83-
should_exit = 1;
89+
thread_should_continue = false;
8490
for (int i = 0; i < NUM_THREADS; i++) {
85-
if (NULL == thread_list[i]) {
86-
continue;
91+
if (NULL != thread_list[i]) {
92+
thread_list[i]->join();
93+
delete thread_list[i];
94+
thread_list[i] = NULL;
8795
}
88-
thread_list[i]->join();
89-
delete thread_list[i];
9096
}
97+
TEST_ASSERT_FALSE(thread_alloc_failure);
98+
}
99+
100+
/** Test for large heap allocation
101+
102+
Given a heap of size mbed_heap_size
103+
When try to allocate memory of size mbed_heap_size/5 (20% of whole heap)
104+
Then the memory is allocated and @a malloc return valid memory
105+
*/
106+
void test_big_allocation(void)
107+
{
108+
const uint32_t alloc_size = mbed_heap_size / 5;
109+
void *data = NULL;
110+
111+
data = malloc(alloc_size);
112+
TEST_ASSERT_NOT_NULL(data);
113+
114+
// test whole allocated memory
115+
memset(data, 0, alloc_size);
116+
117+
free(data);
118+
}
119+
120+
/** Test if allocation of zero size does not cause any undefined behaviour
121+
122+
Given a heap
123+
When try to allocate memory of size 0
124+
Then the return value of @a malloc depends on the particular library implementation
125+
(NULL or smallest possible allocation) and no undefined behaviour happens
126+
127+
@note If allocation size is zero, the return value depends on the particular library implementation
128+
(it may or may not be a null pointer), but the returned pointer shall not be dereferenced
129+
*/
130+
void test_zero_allocation(void)
131+
{
132+
void *data = NULL;
133+
134+
data = malloc(0);
135+
if(data != NULL) {
136+
free(data);
137+
}
138+
TEST_ASSERT_MESSAGE(true, "malloc(0) succeed - no undefined behaviour happens");
139+
}
140+
141+
/** Test if free on NULL pointer does not cause any undefined behaviour
142+
143+
Given a NULL pointer
144+
When try to free it
145+
Then the function @a free does nothing and no undefined behaviour happens
146+
*/
147+
void test_null_free(void)
148+
{
149+
void *data = NULL;
150+
free(data);
151+
152+
TEST_ASSERT_MESSAGE(true, "free(NULL) succeed - no undefined behaviour happens");
153+
}
154+
155+
// Test cases
156+
Case cases[] = {
157+
Case("Test 0 size allocation", test_zero_allocation),
158+
Case("Test NULL pointer free", test_null_free),
159+
Case("Test multithreaded allocations", test_multithread_allocation),
160+
Case("Test large allocation", test_big_allocation)
161+
};
91162

92-
GREENTEA_TESTSUITE_RESULT(!allocation_failure);
163+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
164+
{
165+
GREENTEA_SETUP(test_timeout, "timing_drift_auto");
166+
return utest::v1::greentea_test_setup_handler(number_of_cases);
167+
}
168+
169+
utest::v1::Specification specification(greentea_test_setup, cases);
170+
171+
int main()
172+
{
173+
return !utest::v1::Harness::run(specification);
93174
}

0 commit comments

Comments
 (0)