1
1
/*
2
- * Copyright (c) 2016-2016 , ARM Limited, All Rights Reserved
2
+ * Copyright (c) 2016-2017 , ARM Limited, All Rights Reserved
3
3
* SPDX-License-Identifier: Apache-2.0
4
4
*
5
5
* Licensed under the Apache License, Version 2.0 (the "License"); you may
17
17
#include < stdio.h>
18
18
#include < stdlib.h>
19
19
#include < string.h>
20
- #include " greentea-client/test_env.h"
21
- #include " cmsis.h"
20
+
22
21
#include " mbed.h"
23
- #include " rtos.h"
24
- #include " mbed_assert.h"
22
+ #include " cmsis.h"
23
+ #include " greentea-client/test_env.h"
24
+ #include " utest/utest.h"
25
+ #include " unity/unity.h"
26
+
27
+ using utest::v1::Case;
28
+
29
+ static const int test_timeout = 30 ;
30
+
25
31
26
32
// Amount to malloc for each iteration
27
33
#define MALLOC_TEST_SIZE 256
@@ -33,66 +39,37 @@ extern uint32_t mbed_heap_size;
33
39
extern uint32_t mbed_stack_isr_start;
34
40
extern uint32_t mbed_stack_isr_size;
35
41
36
- static uint32_t max_allocation_size = 0 ;
37
-
38
- static bool inrange (uint32_t addr, uint32_t start, uint32_t size);
39
- static bool rangeinrange (uint32_t addr, uint32_t size, uint32_t start, uint32_t len);
40
- static bool valid_fill (uint8_t * data, uint32_t size, uint8_t fill);
41
- static bool allocate_and_fill_heap (void );
42
- static bool check_and_free_heap (void );
43
-
44
- int main (void ) {
45
- GREENTEA_SETUP (30 , " default_auto" );
46
42
47
- char c;
48
- char * initial_stack = &c;
49
- char *initial_heap;
50
-
51
- // Sanity check malloc
52
- initial_heap = (char *)malloc (1 );
53
- if (initial_heap == NULL ) {
54
- printf (" Unable to malloc a single byte\n " );
55
- GREENTEA_TESTSUITE_RESULT (false );
56
- }
43
+ struct linked_list {
44
+ linked_list * next;
45
+ uint8_t data[MALLOC_TEST_SIZE];
46
+ };
57
47
58
- if (!inrange ((uint32_t )initial_heap, mbed_heap_start, mbed_heap_size)) {
59
- printf (" Heap in wrong location\n " );
60
- GREENTEA_TESTSUITE_RESULT (false );
61
- }
62
- // MSP stack should be very near end (test using within 128 bytes)
63
- uint32_t msp = __get_MSP ();
64
- if (!inrange (msp, mbed_stack_isr_start + mbed_stack_isr_size - 128 , 128 )) {
65
- printf (" Interrupt stack in wrong location\n " );
66
- GREENTEA_TESTSUITE_RESULT (false );
67
- }
68
48
69
- // Fully allocate the heap and stack
70
- bool ret = true ;
71
- ret = ret && allocate_and_fill_heap ();
72
- ret = ret && check_and_free_heap ();
73
49
74
- // Force a task switch so a stack check is performed
75
- Thread::wait (10 );
76
-
77
- printf (" Total size dynamically allocated: %lu\n " , max_allocation_size);
50
+ /* TODO: add memory layout test.
51
+ *
52
+ * The test was skipped for now since not all devices seems to comply with Mbed OS memory.
53
+ *
54
+ * @note Mbed OS memory model: https://os.mbed.com/docs/latest/reference/memory.html
55
+ *
56
+ */
78
57
79
- GREENTEA_TESTSUITE_RESULT (ret);
80
- }
81
58
82
59
/*
83
60
* Return true if addr is in range [start:start+size)
84
61
*/
85
62
static bool inrange (uint32_t addr, uint32_t start, uint32_t size)
86
63
{
87
- return (addr >= start) && (addr < start + size) ? true : false ;
64
+ return (addr >= start) && (addr < ( start + size)) ;
88
65
}
89
66
90
67
/*
91
68
* Return true if [addr:addr+size] is inside [start:start+len]
92
69
*/
93
70
static bool rangeinrange (uint32_t addr, uint32_t size, uint32_t start, uint32_t len)
94
71
{
95
- if (addr + size > start + len) {
72
+ if (( addr + size) > ( start + len) ) {
96
73
return false ;
97
74
}
98
75
if (addr < start) {
@@ -102,7 +79,7 @@ static bool rangeinrange(uint32_t addr, uint32_t size, uint32_t start, uint32_t
102
79
}
103
80
104
81
/*
105
- * Return true of the region is filled only the the specified fill value
82
+ * Return true if the region is filled only with the specified value
106
83
*/
107
84
static bool valid_fill (uint8_t * data, uint32_t size, uint8_t fill)
108
85
{
@@ -114,66 +91,155 @@ static bool valid_fill(uint8_t * data, uint32_t size, uint8_t fill)
114
91
return true ;
115
92
}
116
93
117
- struct linked_list {
118
- linked_list * next;
119
- uint8_t data[MALLOC_TEST_SIZE];
120
- };
121
-
122
- static linked_list *head = NULL ;
123
- static bool allocate_and_fill_heap ()
94
+ static void allocate_and_fill_heap (linked_list *&head)
124
95
{
125
-
126
96
linked_list *current;
127
97
128
- current = (linked_list*)malloc (sizeof (linked_list));
129
- if (0 == current) {
130
- return false ;
131
- }
98
+ current = (linked_list*) malloc (sizeof (linked_list));
99
+ TEST_ASSERT_NOT_NULL (current);
100
+
132
101
current->next = NULL ;
133
- memset ((void *)current->data , MALLOC_FILL, sizeof (current->data ));
102
+ memset ((void *) current->data , MALLOC_FILL, sizeof (current->data ));
134
103
135
104
// Allocate until malloc returns NULL
136
- bool pass = true ;
137
105
head = current;
138
106
while (true ) {
139
107
140
108
// Allocate
141
- linked_list *temp = (linked_list*)malloc (sizeof (linked_list));
109
+ linked_list *temp = (linked_list*) malloc (sizeof (linked_list));
110
+
142
111
if (NULL == temp) {
143
112
break ;
144
113
}
145
- if (!rangeinrange ((uint32_t )temp, sizeof (linked_list), mbed_heap_start, mbed_heap_size)) {
146
- printf (" Memory allocation out of range\n " );
147
- pass = false ;
148
- break ;
149
- }
114
+ bool result = rangeinrange ((uint32_t ) temp, sizeof (linked_list), mbed_heap_start, mbed_heap_size);
115
+
116
+ TEST_ASSERT_TRUE_MESSAGE (result, " Memory allocation out of range" );
150
117
151
118
// Init
152
119
temp->next = NULL ;
153
- memset ((void *)temp->data , MALLOC_FILL, sizeof (current->data ));
120
+ memset ((void *) temp->data , MALLOC_FILL, sizeof (current->data ));
154
121
155
122
// Add to list
156
123
current->next = temp;
157
124
current = temp;
158
125
}
159
- return pass;
160
126
}
161
127
162
- static bool check_and_free_heap ()
128
+ static void check_and_free_heap (linked_list *head, uint32_t &max_allocation_size )
163
129
{
164
130
uint32_t total_size = 0 ;
165
131
linked_list * current = head;
166
- bool pass = true ;
132
+
167
133
while (current != NULL ) {
168
134
total_size += sizeof (linked_list);
169
- if (!valid_fill (current->data , sizeof (current->data ), MALLOC_FILL)) {
170
- pass = false ;
171
- }
135
+ bool result = valid_fill (current->data , sizeof (current->data ), MALLOC_FILL);
136
+
137
+ TEST_ASSERT_TRUE_MESSAGE (result, " Memory fill check failed" );
138
+
172
139
linked_list * next = current->next ;
173
140
free (current);
174
141
current = next;
175
142
}
176
143
177
144
max_allocation_size = total_size;
178
- return pass;
145
+ }
146
+
147
+ /* * Test heap allocation
148
+
149
+ Given a heap
150
+ When memory is allocated from heap
151
+ Then the memory is within heap boundary
152
+
153
+ */
154
+ void test_heap_in_range (void )
155
+ {
156
+ char *initial_heap;
157
+
158
+ // Sanity check malloc
159
+ initial_heap = (char *) malloc (1 );
160
+ TEST_ASSERT_NOT_NULL (initial_heap);
161
+
162
+ bool result = inrange ((uint32_t ) initial_heap, mbed_heap_start, mbed_heap_size);
163
+
164
+ TEST_ASSERT_TRUE_MESSAGE (result, " Heap in wrong location" );
165
+ free (initial_heap);
166
+ }
167
+
168
+ /* * Test for Main thread stack
169
+
170
+ Given a Main thread and its stack
171
+ When check Main thread stack pointer
172
+ Then the SP is within Main stack boundary
173
+ */
174
+ void test_main_stack_in_range (void )
175
+ {
176
+ os_thread_t *thread = (os_thread_t *) osThreadGetId ();
177
+
178
+ uint32_t psp = __get_PSP ();
179
+ uint8_t *stack_mem = (uint8_t *) thread->stack_mem ;
180
+ uint32_t stack_size = thread->stack_size ;
181
+
182
+ // PSP stack should be somewhere in the middle
183
+ bool result = inrange (psp, (uint32_t ) stack_mem, stack_size);
184
+
185
+ TEST_ASSERT_TRUE_MESSAGE (result, " Main stack in wrong location" );
186
+ }
187
+
188
+ /* * Test for Scheduler/ISR thread stack
189
+
190
+ Given a Scheduler/ISR thread and its stack
191
+ When check Scheduler/ISR thread stack pointer
192
+ Then the SP is within Scheduler/ISR stack boundary
193
+ */
194
+ void test_isr_stack_in_range (void )
195
+ {
196
+ // MSP stack should be very near end (test using within 128 bytes)
197
+ uint32_t msp = __get_MSP ();
198
+ bool result = inrange (msp, mbed_stack_isr_start + mbed_stack_isr_size - 128 , 128 );
199
+
200
+ TEST_ASSERT_TRUE_MESSAGE (result, " Interrupt stack in wrong location" );
201
+ }
202
+
203
+ /* * Test full heap allocation
204
+
205
+ Given a heap and linked_list data structure
206
+ When linked_list is filled till run out of heap memory
207
+ Then the memory is properly initialised and freed
208
+ */
209
+ void test_heap_allocation_free (void )
210
+ {
211
+ linked_list *head = NULL ;
212
+ uint32_t max_allocation_size = 0 ;
213
+
214
+ // Fully allocate the heap and stack
215
+ allocate_and_fill_heap (head);
216
+
217
+ check_and_free_heap (head, max_allocation_size);
218
+
219
+ // Force a task switch so a stack check is performed
220
+ Thread::wait (10 );
221
+
222
+ printf (" Total size dynamically allocated: %luB\n " , max_allocation_size);
223
+ }
224
+
225
+
226
+ // Test cases
227
+ Case cases[] = {
228
+ Case (" Test heap in range" , test_heap_in_range),
229
+ Case (" Test main stack in range" , test_main_stack_in_range),
230
+ Case (" Test isr stack in range" , test_isr_stack_in_range),
231
+ Case (" Test heap allocation and free" , test_heap_allocation_free)
232
+ };
233
+
234
+ utest::v1::status_t greentea_test_setup (const size_t number_of_cases)
235
+ {
236
+ GREENTEA_SETUP (test_timeout, " default_auto" );
237
+ return utest::v1::greentea_test_setup_handler (number_of_cases);
238
+ }
239
+
240
+ utest::v1::Specification specification (greentea_test_setup, cases);
241
+
242
+ int main ()
243
+ {
244
+ return !utest::v1::Harness::run (specification);
179
245
}
0 commit comments