![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /* 00002 * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "mbed.h" 00019 #include "greentea-client/test_env.h" 00020 #include "unity/unity.h" 00021 #include "utest/utest.h" 00022 #include "mbed_mem_trace.h" 00023 #include <stdlib.h> 00024 #include <stdio.h> 00025 #include <stdarg.h> 00026 00027 #ifndef MBED_MEM_TRACING_ENABLED 00028 #error [NOT_SUPPORTED] test not supported 00029 #endif 00030 00031 using namespace utest::v1; 00032 00033 /******************************************************************************/ 00034 /* Helper functions and data structures */ 00035 /******************************************************************************/ 00036 00037 // This structure keeps data about the various memory allocation operations, 00038 // as traced by 'test_trace_cb' below. 00039 #define TEST_MAX_MEMORY_OPS 10 00040 // Trace results for all possible operations 00041 typedef struct { 00042 uint8_t op; 00043 void *res; 00044 union { 00045 struct { 00046 size_t arg_size; 00047 } malloc_info; 00048 struct { 00049 void *arg_ptr; 00050 size_t arg_size; 00051 } realloc_info; 00052 struct { 00053 size_t arg_nmemb; 00054 size_t arg_size; 00055 } calloc_info; 00056 struct { 00057 void *arg_ptr; 00058 } free_info; 00059 }; 00060 } mem_trace_data_t; 00061 // Memory operation statistics 00062 typedef struct { 00063 mem_trace_data_t op_data[TEST_MAX_MEMORY_OPS]; 00064 uint32_t total_ops; 00065 bool invalid_op, overflow; 00066 } stats_t; 00067 static stats_t stats; 00068 00069 // Clear all the memory statistics 00070 static void test_clear_stats() { 00071 memset(&stats, 0, sizeof(stats)); 00072 } 00073 00074 // Memory tracer callback that records each operation in "stats" (above) 00075 extern "C" void test_trace_cb(uint8_t op, void *res, void *caller, ...) { 00076 va_list va; 00077 mem_trace_data_t *pmem = stats.op_data + stats.total_ops; 00078 00079 if (stats.total_ops >= TEST_MAX_MEMORY_OPS) { 00080 stats.overflow = true; 00081 return; 00082 } 00083 va_start(va, caller); 00084 pmem->op = op; 00085 pmem->res = res; 00086 switch(op) { 00087 case MBED_MEM_TRACE_MALLOC: 00088 pmem->malloc_info.arg_size = va_arg(va, size_t); 00089 break; 00090 00091 case MBED_MEM_TRACE_REALLOC: 00092 pmem->realloc_info.arg_ptr = va_arg(va, void *); 00093 pmem->realloc_info.arg_size = va_arg(va, size_t); 00094 break; 00095 00096 case MBED_MEM_TRACE_CALLOC: 00097 pmem->calloc_info.arg_nmemb = va_arg(va, size_t); 00098 pmem->calloc_info.arg_size = va_arg(va, size_t); 00099 break; 00100 00101 case MBED_MEM_TRACE_FREE: 00102 pmem->free_info.arg_ptr = va_arg(va, void *); 00103 break; 00104 00105 default: 00106 stats.invalid_op = true; 00107 } 00108 stats.total_ops ++; 00109 va_end(va); 00110 } 00111 00112 // Generic sanity checks for the tracer 00113 static void check_sanity(uint32_t expected_ops) { 00114 TEST_ASSERT_FALSE(stats.overflow); 00115 TEST_ASSERT_FALSE(stats.invalid_op); 00116 TEST_ASSERT_EQUAL_UINT32(stats.total_ops, expected_ops); 00117 } 00118 00119 // Check a "malloc" operation 00120 static void check_malloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_size) { 00121 TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_MALLOC); 00122 TEST_ASSERT_EQUAL_PTR(p->res, expected_res); 00123 TEST_ASSERT_EQUAL_UINT32(p->malloc_info.arg_size, expected_arg_size); 00124 } 00125 00126 // Check a "free" operation 00127 static void check_free_op(const mem_trace_data_t *p, void *expected_arg_ptr) { 00128 TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_FREE); 00129 TEST_ASSERT_EQUAL_PTR(p->free_info.arg_ptr, expected_arg_ptr); 00130 } 00131 00132 // Check a "realloc" operation 00133 static void check_realloc_op(const mem_trace_data_t *p, void *expected_res, void *expected_arg_ptr, size_t expected_arg_size) { 00134 TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_REALLOC); 00135 TEST_ASSERT_EQUAL_PTR(p->res, expected_res); 00136 TEST_ASSERT_EQUAL_UINT32(p->realloc_info.arg_ptr, expected_arg_ptr); 00137 TEST_ASSERT_EQUAL_UINT32(p->realloc_info.arg_size, expected_arg_size); 00138 } 00139 00140 // Check a "calloc" operation 00141 static void check_calloc_op(const mem_trace_data_t *p, void *expected_res, size_t expected_arg_nmemb, size_t expected_arg_size) { 00142 TEST_ASSERT_EQUAL_UINT8(p->op, MBED_MEM_TRACE_CALLOC); 00143 TEST_ASSERT_EQUAL_PTR(p->res, expected_res); 00144 TEST_ASSERT_EQUAL_UINT32(p->calloc_info.arg_nmemb, expected_arg_nmemb); 00145 TEST_ASSERT_EQUAL_UINT32(p->calloc_info.arg_size, expected_arg_size); 00146 } 00147 00148 /******************************************************************************/ 00149 /* Tests */ 00150 /******************************************************************************/ 00151 00152 // Allocate a single buffer, then free it. Check that tracing matches the operations. 00153 static void test_case_single_malloc_free() { 00154 const size_t block_size = 126; 00155 const mem_trace_data_t *pmem = stats.op_data; 00156 00157 test_clear_stats(); 00158 mbed_mem_trace_set_callback(test_trace_cb); 00159 // Allocate a single memory block 00160 void *p = malloc(block_size); 00161 TEST_ASSERT_NOT_EQUAL(p, NULL); 00162 // Free the memory block 00163 free(p); 00164 // Stop tracing 00165 mbed_mem_trace_set_callback(NULL); 00166 // Check tracer result 00167 check_sanity(2); 00168 check_malloc_op(pmem ++, p, block_size); 00169 check_free_op(pmem, p); 00170 } 00171 00172 // Test all memory operations (malloc, realloc, free, calloc) 00173 static void test_case_all_memory_ops() { 00174 const size_t malloc_size = 40, realloc_size = 80, nmemb = 25, size = 10; 00175 const mem_trace_data_t *pmem = stats.op_data; 00176 00177 test_clear_stats(); 00178 mbed_mem_trace_set_callback(test_trace_cb); 00179 // Allocate a single memory block, the realloc it 00180 void *p_malloc = malloc(malloc_size); 00181 TEST_ASSERT_NOT_EQUAL(p_malloc, NULL); 00182 void *p_realloc = realloc(p_malloc, realloc_size); 00183 TEST_ASSERT_NOT_EQUAL(p_realloc, NULL); 00184 // Use calloc() now 00185 void *p_calloc = calloc(nmemb, size); 00186 //TEST_ASSERT_NOT_EQUAL(p_calloc, NULL); 00187 // Free the realloc() pointer first, then the calloc() one 00188 free(p_realloc); 00189 free(p_calloc); 00190 // Stop tracing 00191 mbed_mem_trace_set_callback(NULL); 00192 // Check tracer result 00193 check_sanity(6); 00194 check_malloc_op(pmem ++, p_malloc, malloc_size); 00195 check_realloc_op(pmem ++, p_realloc, p_malloc, realloc_size); 00196 // calloc() calls malloc() internally 00197 check_malloc_op(pmem ++, p_calloc, nmemb * size); 00198 check_calloc_op(pmem ++, p_calloc, nmemb, size); 00199 check_free_op(pmem ++, p_realloc); 00200 check_free_op(pmem, p_calloc); 00201 } 00202 00203 // Test that tracing is off when using a NULL callback 00204 static void test_case_trace_off() { 00205 const size_t malloc_size = 10; 00206 00207 test_clear_stats(); 00208 // We don't want any tracing 00209 mbed_mem_trace_set_callback(NULL); 00210 // Allocate a buffer and free it 00211 void *p_malloc = malloc(malloc_size); 00212 TEST_ASSERT_NOT_EQUAL(p_malloc, NULL); 00213 free(p_malloc); 00214 // Check that we didn't trace anything 00215 check_sanity(0); 00216 } 00217 00218 // Test partial tracing (start tracing, stop tracing, restart later) 00219 static void test_case_partial_trace() { 00220 const size_t malloc_size_1 = 20, malloc_size_2 = 30; 00221 const mem_trace_data_t *pmem = stats.op_data; 00222 00223 test_clear_stats(); 00224 // Start tracing 00225 mbed_mem_trace_set_callback(test_trace_cb); 00226 // Allocate a buffer 00227 void *p_malloc_1 = malloc(malloc_size_1); 00228 TEST_ASSERT_NOT_EQUAL(p_malloc_1, NULL); 00229 // Disable tracing before freeing the first buffer 00230 mbed_mem_trace_set_callback(NULL); 00231 free(p_malloc_1); 00232 // Allocate another buffer (still not traced) 00233 void *p_malloc_2 = malloc(malloc_size_2); 00234 TEST_ASSERT_NOT_EQUAL(p_malloc_2, NULL); 00235 // Re-enable tracing 00236 mbed_mem_trace_set_callback(test_trace_cb); 00237 // And free the second buffer (this operation should be tracer) 00238 free(p_malloc_2); 00239 // Stop tracing 00240 mbed_mem_trace_set_callback(NULL); 00241 // Check tracer result 00242 check_sanity(2); 00243 check_malloc_op(pmem ++, p_malloc_1, malloc_size_1); 00244 check_free_op(pmem, p_malloc_2); 00245 } 00246 00247 // Test new/delete tracing 00248 static void test_case_new_delete() { 00249 const mem_trace_data_t *pmem = stats.op_data; 00250 00251 test_clear_stats(); 00252 // Start tracing 00253 mbed_mem_trace_set_callback(test_trace_cb); 00254 // Test new, new[], delete and delete[] 00255 int *p_int = new int; 00256 int *p_int_array = new int[10]; 00257 delete p_int; 00258 delete[] p_int_array; 00259 // Stop tracing 00260 mbed_mem_trace_set_callback(NULL); 00261 // Check tracer result 00262 check_sanity(4); 00263 check_malloc_op(pmem ++, p_int, sizeof(int)); 00264 check_malloc_op(pmem ++, p_int_array, 10 * sizeof(int)); 00265 check_free_op(pmem ++, p_int); 00266 check_free_op(pmem ++, p_int_array); 00267 } 00268 00269 static Case cases[] = { 00270 Case("single malloc/free", test_case_single_malloc_free), 00271 Case("all memory operations", test_case_all_memory_ops), 00272 Case("trace off", test_case_trace_off), 00273 Case("partial trace", test_case_partial_trace), 00274 Case("test new/delete", test_case_new_delete) 00275 }; 00276 00277 static status_t greentea_test_setup(const size_t number_of_cases) { 00278 GREENTEA_SETUP(20, "default_auto"); 00279 return greentea_test_setup_handler(number_of_cases); 00280 } 00281 00282 static Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); 00283 00284 int main() { 00285 // Disable stdout buffering to prevent any unwanted allocations 00286 setvbuf(stdout, NULL, _IONBF, 0); 00287 Harness::run(specification); 00288 } 00289
Generated on Sun Jul 17 2022 08:25:27 by
![doxygen](doxygen.png)