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