takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /*
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2013-2017, ARM Limited, All Rights Reserved
kadonotakashi 0:8fdf9a60065b 3 * SPDX-License-Identifier: Apache-2.0
kadonotakashi 0:8fdf9a60065b 4 *
kadonotakashi 0:8fdf9a60065b 5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kadonotakashi 0:8fdf9a60065b 6 * not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 7 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 8 *
kadonotakashi 0:8fdf9a60065b 9 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 10 *
kadonotakashi 0:8fdf9a60065b 11 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kadonotakashi 0:8fdf9a60065b 13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 14 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 15 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 16 */
kadonotakashi 0:8fdf9a60065b 17
kadonotakashi 0:8fdf9a60065b 18 #include "mbed.h"
kadonotakashi 0:8fdf9a60065b 19 #include "greentea-client/test_env.h"
kadonotakashi 0:8fdf9a60065b 20 #include "unity/unity.h"
kadonotakashi 0:8fdf9a60065b 21 #include "utest/utest.h"
kadonotakashi 0:8fdf9a60065b 22 #include "mbed_mem_trace.h"
kadonotakashi 0:8fdf9a60065b 23 #include <stdlib.h>
kadonotakashi 0:8fdf9a60065b 24 #include <stdio.h>
kadonotakashi 0:8fdf9a60065b 25 #include <stdarg.h>
kadonotakashi 0:8fdf9a60065b 26
kadonotakashi 0:8fdf9a60065b 27 #if !MBED_MEM_TRACING_ENABLED
kadonotakashi 0:8fdf9a60065b 28 #error [NOT_SUPPORTED] test not supported
kadonotakashi 0:8fdf9a60065b 29 #endif
kadonotakashi 0:8fdf9a60065b 30
kadonotakashi 0:8fdf9a60065b 31 using utest::v1::Case;
kadonotakashi 0:8fdf9a60065b 32
kadonotakashi 0:8fdf9a60065b 33
kadonotakashi 0:8fdf9a60065b 34 /******************************************************************************/
kadonotakashi 0:8fdf9a60065b 35 /* Helper functions and data structures */
kadonotakashi 0:8fdf9a60065b 36 /******************************************************************************/
kadonotakashi 0:8fdf9a60065b 37
kadonotakashi 0:8fdf9a60065b 38 #define THREAD_STACK_SIZE 384
kadonotakashi 0:8fdf9a60065b 39 #define NUM_TEST_THREADS 3
kadonotakashi 0:8fdf9a60065b 40
kadonotakashi 0:8fdf9a60065b 41 template<osPriority PRIORITY, uint32_t STACK_SIZE>
kadonotakashi 0:8fdf9a60065b 42 class TestThread : public Thread {
kadonotakashi 0:8fdf9a60065b 43 uint8_t stack[STACK_SIZE];
kadonotakashi 0:8fdf9a60065b 44 public:
kadonotakashi 0:8fdf9a60065b 45 TestThread() : Thread(PRIORITY, STACK_SIZE, stack) { }
kadonotakashi 0:8fdf9a60065b 46 };
kadonotakashi 0:8fdf9a60065b 47
kadonotakashi 0:8fdf9a60065b 48 // This structure keeps data about the various memory allocation operations,
kadonotakashi 0:8fdf9a60065b 49 // as traced by 'test_trace_cb' below.
kadonotakashi 0:8fdf9a60065b 50 #define TEST_MAX_MEMORY_OPS 10
kadonotakashi 0:8fdf9a60065b 51
kadonotakashi 0:8fdf9a60065b 52 // Trace results for all possible operations
kadonotakashi 0:8fdf9a60065b 53 typedef struct {
kadonotakashi 0:8fdf9a60065b 54 uint8_t op;
kadonotakashi 0:8fdf9a60065b 55 void *res;
kadonotakashi 0:8fdf9a60065b 56 union {
kadonotakashi 0:8fdf9a60065b 57 struct {
kadonotakashi 0:8fdf9a60065b 58 size_t arg_size;
kadonotakashi 0:8fdf9a60065b 59 } malloc_info;
kadonotakashi 0:8fdf9a60065b 60 struct {
kadonotakashi 0:8fdf9a60065b 61 void *arg_ptr;
kadonotakashi 0:8fdf9a60065b 62 size_t arg_size;
kadonotakashi 0:8fdf9a60065b 63 } realloc_info;
kadonotakashi 0:8fdf9a60065b 64 struct {
kadonotakashi 0:8fdf9a60065b 65 size_t arg_nmemb;
kadonotakashi 0:8fdf9a60065b 66 size_t arg_size;
kadonotakashi 0:8fdf9a60065b 67 } calloc_info;
kadonotakashi 0:8fdf9a60065b 68 struct {
kadonotakashi 0:8fdf9a60065b 69 void *arg_ptr;
kadonotakashi 0:8fdf9a60065b 70 } free_info;
kadonotakashi 0:8fdf9a60065b 71 };
kadonotakashi 0:8fdf9a60065b 72 } mem_trace_data_t;
kadonotakashi 0:8fdf9a60065b 73
kadonotakashi 0:8fdf9a60065b 74 // Memory operation statistics
kadonotakashi 0:8fdf9a60065b 75 typedef struct {
kadonotakashi 0:8fdf9a60065b 76 mem_trace_data_t op_data[TEST_MAX_MEMORY_OPS];
kadonotakashi 0:8fdf9a60065b 77 uint32_t total_ops;
kadonotakashi 0:8fdf9a60065b 78 bool invalid_op, overflow;
kadonotakashi 0:8fdf9a60065b 79 } stats_t;
kadonotakashi 0:8fdf9a60065b 80
kadonotakashi 0:8fdf9a60065b 81 static stats_t stats;
kadonotakashi 0:8fdf9a60065b 82
kadonotakashi 0:8fdf9a60065b 83
kadonotakashi 0:8fdf9a60065b 84 // Clear all the memory statistics
kadonotakashi 0:8fdf9a60065b 85 static void test_clear_stats()
kadonotakashi 0:8fdf9a60065b 86 {
kadonotakashi 0:8fdf9a60065b 87 memset(&stats, 0, sizeof(stats));
kadonotakashi 0:8fdf9a60065b 88 }
kadonotakashi 0:8fdf9a60065b 89
kadonotakashi 0:8fdf9a60065b 90 // Memory tracer callback that records each operation in "stats" (above)
kadonotakashi 0:8fdf9a60065b 91 extern "C" void test_trace_cb(uint8_t op, void *res, void *caller, ...)
kadonotakashi 0:8fdf9a60065b 92 {
kadonotakashi 0:8fdf9a60065b 93 va_list va;
kadonotakashi 0:8fdf9a60065b 94 mem_trace_data_t *pmem = stats.op_data + stats.total_ops;
kadonotakashi 0:8fdf9a60065b 95 if (stats.total_ops >= TEST_MAX_MEMORY_OPS) {
kadonotakashi 0:8fdf9a60065b 96 stats.overflow = true;
kadonotakashi 0:8fdf9a60065b 97 return;
kadonotakashi 0:8fdf9a60065b 98 }
kadonotakashi 0:8fdf9a60065b 99 va_start(va, caller);
kadonotakashi 0:8fdf9a60065b 100 pmem->op = op;
kadonotakashi 0:8fdf9a60065b 101 pmem->res = res;
kadonotakashi 0:8fdf9a60065b 102 switch (op) {
kadonotakashi 0:8fdf9a60065b 103 case MBED_MEM_TRACE_MALLOC:
kadonotakashi 0:8fdf9a60065b 104 pmem->malloc_info.arg_size = va_arg(va, size_t);
kadonotakashi 0:8fdf9a60065b 105 break;
kadonotakashi 0:8fdf9a60065b 106
kadonotakashi 0:8fdf9a60065b 107 case MBED_MEM_TRACE_REALLOC:
kadonotakashi 0:8fdf9a60065b 108 pmem->realloc_info.arg_ptr = va_arg(va, void *);
kadonotakashi 0:8fdf9a60065b 109 pmem->realloc_info.arg_size = va_arg(va, size_t);
kadonotakashi 0:8fdf9a60065b 110 break;
kadonotakashi 0:8fdf9a60065b 111
kadonotakashi 0:8fdf9a60065b 112 case MBED_MEM_TRACE_CALLOC:
kadonotakashi 0:8fdf9a60065b 113 pmem->calloc_info.arg_nmemb = va_arg(va, size_t);
kadonotakashi 0:8fdf9a60065b 114 pmem->calloc_info.arg_size = va_arg(va, size_t);
kadonotakashi 0:8fdf9a60065b 115 break;
kadonotakashi 0:8fdf9a60065b 116
kadonotakashi 0:8fdf9a60065b 117 case MBED_MEM_TRACE_FREE:
kadonotakashi 0:8fdf9a60065b 118 pmem->free_info.arg_ptr = va_arg(va, void *);
kadonotakashi 0:8fdf9a60065b 119 break;
kadonotakashi 0:8fdf9a60065b 120
kadonotakashi 0:8fdf9a60065b 121 default:
kadonotakashi 0:8fdf9a60065b 122 stats.invalid_op = true;
kadonotakashi 0:8fdf9a60065b 123 }
kadonotakashi 0:8fdf9a60065b 124 stats.total_ops ++;
kadonotakashi 0:8fdf9a60065b 125 va_end(va);
kadonotakashi 0:8fdf9a60065b 126 }
kadonotakashi 0:8fdf9a60065b 127
kadonotakashi 0:8fdf9a60065b 128 // Generic sanity checks for the tracer
kadonotakashi 0:8fdf9a60065b 129 static void check_sanity(uint32_t expected_ops)
kadonotakashi 0:8fdf9a60065b 130 {
kadonotakashi 0:8fdf9a60065b 131 TEST_ASSERT_FALSE(stats.overflow);
kadonotakashi 0:8fdf9a60065b 132 TEST_ASSERT_FALSE(stats.invalid_op);
kadonotakashi 0:8fdf9a60065b 133 TEST_ASSERT_EQUAL_UINT32(expected_ops, stats.total_ops);
kadonotakashi 0:8fdf9a60065b 134 }
kadonotakashi 0:8fdf9a60065b 135
kadonotakashi 0:8fdf9a60065b 136 // Check a "malloc" operation
kadonotakashi 0:8fdf9a60065b 137 static void check_malloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_size)
kadonotakashi 0:8fdf9a60065b 138 {
kadonotakashi 0:8fdf9a60065b 139 TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_MALLOC, p->op);
kadonotakashi 0:8fdf9a60065b 140 TEST_ASSERT_EQUAL_PTR(expected_res, p->res);
kadonotakashi 0:8fdf9a60065b 141 TEST_ASSERT_EQUAL_UINT32(expected_arg_size, p->malloc_info.arg_size);
kadonotakashi 0:8fdf9a60065b 142 }
kadonotakashi 0:8fdf9a60065b 143
kadonotakashi 0:8fdf9a60065b 144 // Check a "free" operation
kadonotakashi 0:8fdf9a60065b 145 static void check_free_op(const mem_trace_data_t *p, void *expected_arg_ptr)
kadonotakashi 0:8fdf9a60065b 146 {
kadonotakashi 0:8fdf9a60065b 147 TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_FREE, p->op);
kadonotakashi 0:8fdf9a60065b 148 TEST_ASSERT_EQUAL_PTR(expected_arg_ptr, p->free_info.arg_ptr);
kadonotakashi 0:8fdf9a60065b 149 }
kadonotakashi 0:8fdf9a60065b 150
kadonotakashi 0:8fdf9a60065b 151 // Check a "realloc" operation
kadonotakashi 0:8fdf9a60065b 152 static void check_realloc_op(const mem_trace_data_t *p, void *expected_res, void *expected_arg_ptr, size_t expected_arg_size)
kadonotakashi 0:8fdf9a60065b 153 {
kadonotakashi 0:8fdf9a60065b 154 TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_REALLOC, p->op);
kadonotakashi 0:8fdf9a60065b 155 TEST_ASSERT_EQUAL_PTR(expected_res, p->res);
kadonotakashi 0:8fdf9a60065b 156 TEST_ASSERT_EQUAL_UINT32(expected_arg_ptr, p->realloc_info.arg_ptr);
kadonotakashi 0:8fdf9a60065b 157 TEST_ASSERT_EQUAL_UINT32(expected_arg_size, p->realloc_info.arg_size);
kadonotakashi 0:8fdf9a60065b 158 }
kadonotakashi 0:8fdf9a60065b 159
kadonotakashi 0:8fdf9a60065b 160 // Check a "calloc" operation
kadonotakashi 0:8fdf9a60065b 161 static void check_calloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_nmemb, size_t expected_arg_size)
kadonotakashi 0:8fdf9a60065b 162 {
kadonotakashi 0:8fdf9a60065b 163 TEST_ASSERT_EQUAL_UINT8(MBED_MEM_TRACE_CALLOC, p->op);
kadonotakashi 0:8fdf9a60065b 164 TEST_ASSERT_EQUAL_PTR(expected_res, p->res);
kadonotakashi 0:8fdf9a60065b 165 TEST_ASSERT_EQUAL_UINT32(expected_arg_nmemb, p->calloc_info.arg_nmemb);
kadonotakashi 0:8fdf9a60065b 166 TEST_ASSERT_EQUAL_UINT32(expected_arg_size, p->calloc_info.arg_size);
kadonotakashi 0:8fdf9a60065b 167 }
kadonotakashi 0:8fdf9a60065b 168
kadonotakashi 0:8fdf9a60065b 169 // Memory tracer callback to test thread safety
kadonotakashi 0:8fdf9a60065b 170 extern "C" void test_trace_cb_multithread(uint8_t op, void *res, void *caller, ...)
kadonotakashi 0:8fdf9a60065b 171 {
kadonotakashi 0:8fdf9a60065b 172 volatile static int trace_guard = 0;
kadonotakashi 0:8fdf9a60065b 173 trace_guard++;
kadonotakashi 0:8fdf9a60065b 174 TEST_ASSERT_TRUE_MESSAGE(trace_guard == 1, "Race condition occurred !!!!");
kadonotakashi 0:8fdf9a60065b 175 trace_guard--;
kadonotakashi 0:8fdf9a60065b 176 }
kadonotakashi 0:8fdf9a60065b 177
kadonotakashi 0:8fdf9a60065b 178 // Thread function
kadonotakashi 0:8fdf9a60065b 179 void malloc_free(volatile bool *thread_continue)
kadonotakashi 0:8fdf9a60065b 180 {
kadonotakashi 0:8fdf9a60065b 181 const size_t block_size = 126;
kadonotakashi 0:8fdf9a60065b 182
kadonotakashi 0:8fdf9a60065b 183 while (*thread_continue) {
kadonotakashi 0:8fdf9a60065b 184 void *p = malloc(block_size);
kadonotakashi 0:8fdf9a60065b 185 TEST_ASSERT_NOT_EQUAL(p, NULL);
kadonotakashi 0:8fdf9a60065b 186 free(p);
kadonotakashi 0:8fdf9a60065b 187 }
kadonotakashi 0:8fdf9a60065b 188 }
kadonotakashi 0:8fdf9a60065b 189
kadonotakashi 0:8fdf9a60065b 190
kadonotakashi 0:8fdf9a60065b 191 /** Test single malloc/free tracing
kadonotakashi 0:8fdf9a60065b 192 *
kadonotakashi 0:8fdf9a60065b 193 * Given a memory trace mechanism
kadonotakashi 0:8fdf9a60065b 194 * When perform single memory allocation/deallocation using malloc/free
kadonotakashi 0:8fdf9a60065b 195 * Then tracing matches the operations
kadonotakashi 0:8fdf9a60065b 196 *
kadonotakashi 0:8fdf9a60065b 197 */
kadonotakashi 0:8fdf9a60065b 198 static void test_case_single_malloc_free()
kadonotakashi 0:8fdf9a60065b 199 {
kadonotakashi 0:8fdf9a60065b 200 const uint32_t num_op = 2;
kadonotakashi 0:8fdf9a60065b 201 const size_t block_size = 126;
kadonotakashi 0:8fdf9a60065b 202 const mem_trace_data_t *pmem = stats.op_data;
kadonotakashi 0:8fdf9a60065b 203
kadonotakashi 0:8fdf9a60065b 204 test_clear_stats();
kadonotakashi 0:8fdf9a60065b 205 mbed_mem_trace_set_callback(test_trace_cb);
kadonotakashi 0:8fdf9a60065b 206
kadonotakashi 0:8fdf9a60065b 207 // Allocate a single memory block
kadonotakashi 0:8fdf9a60065b 208 void *p = malloc(block_size);
kadonotakashi 0:8fdf9a60065b 209 TEST_ASSERT_NOT_EQUAL(p, NULL);
kadonotakashi 0:8fdf9a60065b 210
kadonotakashi 0:8fdf9a60065b 211 // Free the memory block
kadonotakashi 0:8fdf9a60065b 212 free(p);
kadonotakashi 0:8fdf9a60065b 213
kadonotakashi 0:8fdf9a60065b 214 // Stop tracing
kadonotakashi 0:8fdf9a60065b 215 mbed_mem_trace_set_callback(NULL);
kadonotakashi 0:8fdf9a60065b 216
kadonotakashi 0:8fdf9a60065b 217 // Check tracer result
kadonotakashi 0:8fdf9a60065b 218 check_sanity(num_op);
kadonotakashi 0:8fdf9a60065b 219 check_malloc_op(pmem++, p, block_size);
kadonotakashi 0:8fdf9a60065b 220 check_free_op(pmem, p);
kadonotakashi 0:8fdf9a60065b 221 }
kadonotakashi 0:8fdf9a60065b 222
kadonotakashi 0:8fdf9a60065b 223
kadonotakashi 0:8fdf9a60065b 224 /** Test all memory operations (malloc, realloc, free, calloc) tracing
kadonotakashi 0:8fdf9a60065b 225 *
kadonotakashi 0:8fdf9a60065b 226 * Given a memory trace mechanism
kadonotakashi 0:8fdf9a60065b 227 * When perform all memory operations
kadonotakashi 0:8fdf9a60065b 228 * Then tracing matches the operations
kadonotakashi 0:8fdf9a60065b 229 *
kadonotakashi 0:8fdf9a60065b 230 */
kadonotakashi 0:8fdf9a60065b 231 static void test_case_all_memory_ops()
kadonotakashi 0:8fdf9a60065b 232 {
kadonotakashi 0:8fdf9a60065b 233 const uint32_t num_op = 5;
kadonotakashi 0:8fdf9a60065b 234 const size_t malloc_size = 40, realloc_size = 80, nmemb = 25, size = 10;
kadonotakashi 0:8fdf9a60065b 235 const mem_trace_data_t *pmem = stats.op_data;
kadonotakashi 0:8fdf9a60065b 236
kadonotakashi 0:8fdf9a60065b 237 test_clear_stats();
kadonotakashi 0:8fdf9a60065b 238 mbed_mem_trace_set_callback(test_trace_cb);
kadonotakashi 0:8fdf9a60065b 239
kadonotakashi 0:8fdf9a60065b 240 // Allocate a single memory block, the realloc it
kadonotakashi 0:8fdf9a60065b 241 void *p_malloc = malloc(malloc_size);
kadonotakashi 0:8fdf9a60065b 242 TEST_ASSERT_NOT_EQUAL(p_malloc, NULL);
kadonotakashi 0:8fdf9a60065b 243 void *p_realloc = realloc(p_malloc, realloc_size);
kadonotakashi 0:8fdf9a60065b 244 TEST_ASSERT_NOT_EQUAL(p_realloc, NULL);
kadonotakashi 0:8fdf9a60065b 245
kadonotakashi 0:8fdf9a60065b 246 // Use calloc() now
kadonotakashi 0:8fdf9a60065b 247 void *p_calloc = calloc(nmemb, size);
kadonotakashi 0:8fdf9a60065b 248 TEST_ASSERT_NOT_EQUAL(p_calloc, NULL);
kadonotakashi 0:8fdf9a60065b 249
kadonotakashi 0:8fdf9a60065b 250 // Free the realloc() pointer first, then the calloc() one
kadonotakashi 0:8fdf9a60065b 251 free(p_realloc);
kadonotakashi 0:8fdf9a60065b 252 free(p_calloc);
kadonotakashi 0:8fdf9a60065b 253
kadonotakashi 0:8fdf9a60065b 254 // Stop tracing
kadonotakashi 0:8fdf9a60065b 255 mbed_mem_trace_set_callback(NULL);
kadonotakashi 0:8fdf9a60065b 256
kadonotakashi 0:8fdf9a60065b 257 // Check tracer result
kadonotakashi 0:8fdf9a60065b 258 check_sanity(num_op);
kadonotakashi 0:8fdf9a60065b 259 check_malloc_op(pmem++, p_malloc, malloc_size);
kadonotakashi 0:8fdf9a60065b 260 check_realloc_op(pmem++, p_realloc, p_malloc, realloc_size);
kadonotakashi 0:8fdf9a60065b 261 check_calloc_op(pmem++, p_calloc, nmemb, size);
kadonotakashi 0:8fdf9a60065b 262 check_free_op(pmem++, p_realloc);
kadonotakashi 0:8fdf9a60065b 263 check_free_op(pmem, p_calloc);
kadonotakashi 0:8fdf9a60065b 264 }
kadonotakashi 0:8fdf9a60065b 265
kadonotakashi 0:8fdf9a60065b 266
kadonotakashi 0:8fdf9a60065b 267 /** Test that tracing is off when using a NULL callback
kadonotakashi 0:8fdf9a60065b 268 *
kadonotakashi 0:8fdf9a60065b 269 * Given a memory trace mechanism
kadonotakashi 0:8fdf9a60065b 270 * When tracing is turned off
kadonotakashi 0:8fdf9a60065b 271 * Then performed memory operations doesn't report any tracing
kadonotakashi 0:8fdf9a60065b 272 *
kadonotakashi 0:8fdf9a60065b 273 */
kadonotakashi 0:8fdf9a60065b 274 static void test_case_trace_off()
kadonotakashi 0:8fdf9a60065b 275 {
kadonotakashi 0:8fdf9a60065b 276 const uint32_t num_op = 0;
kadonotakashi 0:8fdf9a60065b 277 const size_t malloc_size = 10;
kadonotakashi 0:8fdf9a60065b 278
kadonotakashi 0:8fdf9a60065b 279 test_clear_stats();
kadonotakashi 0:8fdf9a60065b 280 // We don't want any tracing
kadonotakashi 0:8fdf9a60065b 281 mbed_mem_trace_set_callback(NULL);
kadonotakashi 0:8fdf9a60065b 282
kadonotakashi 0:8fdf9a60065b 283 // Allocate a buffer and free it
kadonotakashi 0:8fdf9a60065b 284 void *p_malloc = malloc(malloc_size);
kadonotakashi 0:8fdf9a60065b 285 TEST_ASSERT_NOT_EQUAL(p_malloc, NULL);
kadonotakashi 0:8fdf9a60065b 286 free(p_malloc);
kadonotakashi 0:8fdf9a60065b 287
kadonotakashi 0:8fdf9a60065b 288 // Check that we didn't trace anything
kadonotakashi 0:8fdf9a60065b 289 check_sanity(num_op);
kadonotakashi 0:8fdf9a60065b 290 }
kadonotakashi 0:8fdf9a60065b 291
kadonotakashi 0:8fdf9a60065b 292
kadonotakashi 0:8fdf9a60065b 293 /** Test partial tracing
kadonotakashi 0:8fdf9a60065b 294 *
kadonotakashi 0:8fdf9a60065b 295 * Given a memory trace mechanism
kadonotakashi 0:8fdf9a60065b 296 * When perform memory operations while tracing is on then off and on again
kadonotakashi 0:8fdf9a60065b 297 * Then tracing report only part of operations
kadonotakashi 0:8fdf9a60065b 298 *
kadonotakashi 0:8fdf9a60065b 299 */
kadonotakashi 0:8fdf9a60065b 300 static void test_case_partial_trace()
kadonotakashi 0:8fdf9a60065b 301 {
kadonotakashi 0:8fdf9a60065b 302 const uint32_t num_op = 2;
kadonotakashi 0:8fdf9a60065b 303 const size_t malloc_size_1 = 20, malloc_size_2 = 30;
kadonotakashi 0:8fdf9a60065b 304 const mem_trace_data_t *pmem = stats.op_data;
kadonotakashi 0:8fdf9a60065b 305
kadonotakashi 0:8fdf9a60065b 306 test_clear_stats();
kadonotakashi 0:8fdf9a60065b 307
kadonotakashi 0:8fdf9a60065b 308 // Start tracing
kadonotakashi 0:8fdf9a60065b 309 mbed_mem_trace_set_callback(test_trace_cb);
kadonotakashi 0:8fdf9a60065b 310
kadonotakashi 0:8fdf9a60065b 311 // Allocate a buffer
kadonotakashi 0:8fdf9a60065b 312 void *p_malloc_1 = malloc(malloc_size_1);
kadonotakashi 0:8fdf9a60065b 313 TEST_ASSERT_NOT_EQUAL(p_malloc_1, NULL);
kadonotakashi 0:8fdf9a60065b 314
kadonotakashi 0:8fdf9a60065b 315 // Disable tracing before freeing the first buffer
kadonotakashi 0:8fdf9a60065b 316 mbed_mem_trace_set_callback(NULL);
kadonotakashi 0:8fdf9a60065b 317 free(p_malloc_1);
kadonotakashi 0:8fdf9a60065b 318
kadonotakashi 0:8fdf9a60065b 319 // Allocate another buffer (still not traced)
kadonotakashi 0:8fdf9a60065b 320 void *p_malloc_2 = malloc(malloc_size_2);
kadonotakashi 0:8fdf9a60065b 321 TEST_ASSERT_NOT_EQUAL(p_malloc_2, NULL);
kadonotakashi 0:8fdf9a60065b 322
kadonotakashi 0:8fdf9a60065b 323 // Re-enable tracing
kadonotakashi 0:8fdf9a60065b 324 mbed_mem_trace_set_callback(test_trace_cb);
kadonotakashi 0:8fdf9a60065b 325
kadonotakashi 0:8fdf9a60065b 326 // And free the second buffer (this operation should be tracer)
kadonotakashi 0:8fdf9a60065b 327 free(p_malloc_2);
kadonotakashi 0:8fdf9a60065b 328
kadonotakashi 0:8fdf9a60065b 329 // Stop tracing
kadonotakashi 0:8fdf9a60065b 330 mbed_mem_trace_set_callback(NULL);
kadonotakashi 0:8fdf9a60065b 331
kadonotakashi 0:8fdf9a60065b 332 // Check tracer result
kadonotakashi 0:8fdf9a60065b 333 check_sanity(num_op);
kadonotakashi 0:8fdf9a60065b 334 check_malloc_op(pmem++, p_malloc_1, malloc_size_1);
kadonotakashi 0:8fdf9a60065b 335 check_free_op(pmem, p_malloc_2);
kadonotakashi 0:8fdf9a60065b 336 }
kadonotakashi 0:8fdf9a60065b 337
kadonotakashi 0:8fdf9a60065b 338
kadonotakashi 0:8fdf9a60065b 339 /** Test new/delete tracing
kadonotakashi 0:8fdf9a60065b 340 *
kadonotakashi 0:8fdf9a60065b 341 * Given a memory trace mechanism
kadonotakashi 0:8fdf9a60065b 342 * When memory allocation/deallocation is performed using new/delete
kadonotakashi 0:8fdf9a60065b 343 * Then tracing matches the operations
kadonotakashi 0:8fdf9a60065b 344 *
kadonotakashi 0:8fdf9a60065b 345 */
kadonotakashi 0:8fdf9a60065b 346 static void test_case_new_delete()
kadonotakashi 0:8fdf9a60065b 347 {
kadonotakashi 0:8fdf9a60065b 348 const uint32_t num_op = 4;
kadonotakashi 0:8fdf9a60065b 349 const mem_trace_data_t *pmem = stats.op_data;
kadonotakashi 0:8fdf9a60065b 350
kadonotakashi 0:8fdf9a60065b 351 test_clear_stats();
kadonotakashi 0:8fdf9a60065b 352
kadonotakashi 0:8fdf9a60065b 353 // Start tracing
kadonotakashi 0:8fdf9a60065b 354 mbed_mem_trace_set_callback(test_trace_cb);
kadonotakashi 0:8fdf9a60065b 355
kadonotakashi 0:8fdf9a60065b 356 // Test new, new[], delete and delete[]
kadonotakashi 0:8fdf9a60065b 357 int *p_int = new int;
kadonotakashi 0:8fdf9a60065b 358 int *p_int_array = new int[10];
kadonotakashi 0:8fdf9a60065b 359 delete p_int;
kadonotakashi 0:8fdf9a60065b 360 delete[] p_int_array;
kadonotakashi 0:8fdf9a60065b 361
kadonotakashi 0:8fdf9a60065b 362 // Stop tracing
kadonotakashi 0:8fdf9a60065b 363 mbed_mem_trace_set_callback(NULL);
kadonotakashi 0:8fdf9a60065b 364
kadonotakashi 0:8fdf9a60065b 365 // Check tracer result
kadonotakashi 0:8fdf9a60065b 366 check_sanity(num_op);
kadonotakashi 0:8fdf9a60065b 367 check_malloc_op(pmem++, p_int, sizeof(int));
kadonotakashi 0:8fdf9a60065b 368 check_malloc_op(pmem++, p_int_array, 10 * sizeof(int));
kadonotakashi 0:8fdf9a60065b 369 check_free_op(pmem++, p_int);
kadonotakashi 0:8fdf9a60065b 370 check_free_op(pmem, p_int_array);
kadonotakashi 0:8fdf9a60065b 371 }
kadonotakashi 0:8fdf9a60065b 372
kadonotakashi 0:8fdf9a60065b 373
kadonotakashi 0:8fdf9a60065b 374 /** Test tracing thread safety
kadonotakashi 0:8fdf9a60065b 375 *
kadonotakashi 0:8fdf9a60065b 376 * Given a memory trace mechanism and multiple threads are started in parallel
kadonotakashi 0:8fdf9a60065b 377 * When each of the threads perform memory allocation/deallocation (thus uses memory trace mechanisms)
kadonotakashi 0:8fdf9a60065b 378 * Then tracing is protected against simultaneous multithreaded access
kadonotakashi 0:8fdf9a60065b 379 *
kadonotakashi 0:8fdf9a60065b 380 */
kadonotakashi 0:8fdf9a60065b 381 static void test_case_multithread_malloc_free()
kadonotakashi 0:8fdf9a60065b 382 {
kadonotakashi 0:8fdf9a60065b 383 const uint32_t wait_time_us = 10000;
kadonotakashi 0:8fdf9a60065b 384 volatile bool threads_continue;
kadonotakashi 0:8fdf9a60065b 385 TestThread<osPriorityNormal, THREAD_STACK_SIZE> threads[NUM_TEST_THREADS];
kadonotakashi 0:8fdf9a60065b 386
kadonotakashi 0:8fdf9a60065b 387 mbed_mem_trace_set_callback(test_trace_cb_multithread);
kadonotakashi 0:8fdf9a60065b 388
kadonotakashi 0:8fdf9a60065b 389 threads_continue = true;
kadonotakashi 0:8fdf9a60065b 390 for (int i = 0; i < NUM_TEST_THREADS; i++) {
kadonotakashi 0:8fdf9a60065b 391 threads[i].start(callback(malloc_free, &threads_continue));
kadonotakashi 0:8fdf9a60065b 392 }
kadonotakashi 0:8fdf9a60065b 393
kadonotakashi 0:8fdf9a60065b 394 Thread::wait(wait_time_us);
kadonotakashi 0:8fdf9a60065b 395 threads_continue = false;
kadonotakashi 0:8fdf9a60065b 396
kadonotakashi 0:8fdf9a60065b 397 for (int i = 0; i < NUM_TEST_THREADS; i++) {
kadonotakashi 0:8fdf9a60065b 398 threads[i].join();
kadonotakashi 0:8fdf9a60065b 399 }
kadonotakashi 0:8fdf9a60065b 400
kadonotakashi 0:8fdf9a60065b 401 mbed_mem_trace_set_callback(NULL);
kadonotakashi 0:8fdf9a60065b 402 }
kadonotakashi 0:8fdf9a60065b 403
kadonotakashi 0:8fdf9a60065b 404
kadonotakashi 0:8fdf9a60065b 405
kadonotakashi 0:8fdf9a60065b 406 static Case cases[] = {
kadonotakashi 0:8fdf9a60065b 407 Case("Test single malloc/free trace", test_case_single_malloc_free),
kadonotakashi 0:8fdf9a60065b 408 Case("Test all memory operations trace", test_case_all_memory_ops),
kadonotakashi 0:8fdf9a60065b 409 Case("Test trace off", test_case_trace_off),
kadonotakashi 0:8fdf9a60065b 410 Case("Test partial trace", test_case_partial_trace),
kadonotakashi 0:8fdf9a60065b 411 Case("Test new/delete trace", test_case_new_delete),
kadonotakashi 0:8fdf9a60065b 412 Case("Test multithreaded trace", test_case_multithread_malloc_free)
kadonotakashi 0:8fdf9a60065b 413 };
kadonotakashi 0:8fdf9a60065b 414
kadonotakashi 0:8fdf9a60065b 415 static utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
kadonotakashi 0:8fdf9a60065b 416 {
kadonotakashi 0:8fdf9a60065b 417 GREENTEA_SETUP(15, "default_auto");
kadonotakashi 0:8fdf9a60065b 418 return utest::v1::greentea_test_setup_handler(number_of_cases);
kadonotakashi 0:8fdf9a60065b 419 }
kadonotakashi 0:8fdf9a60065b 420
kadonotakashi 0:8fdf9a60065b 421 static utest::v1::Specification specification(greentea_test_setup, cases, utest::v1::greentea_test_teardown_handler);
kadonotakashi 0:8fdf9a60065b 422
kadonotakashi 0:8fdf9a60065b 423 int main()
kadonotakashi 0:8fdf9a60065b 424 {
kadonotakashi 0:8fdf9a60065b 425 // Disable stdout buffering to prevent any unwanted allocations
kadonotakashi 0:8fdf9a60065b 426 setvbuf(stdout, NULL, _IONBF, 0);
kadonotakashi 0:8fdf9a60065b 427
kadonotakashi 0:8fdf9a60065b 428 return !utest::v1::Harness::run(specification);
kadonotakashi 0:8fdf9a60065b 429 }