Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "mbed.h"
00017 #include "greentea-client/test_env.h"
00018 #include "utest/utest.h"
00019 #include "unity/unity.h"
00020 
00021 
00022 #if defined(MBED_RTOS_SINGLE_THREAD)
00023   #error [NOT_SUPPORTED] test not supported
00024 #endif
00025 
00026 #if !DEVICE_USTICKER
00027   #error [NOT_SUPPORTED] test not supported
00028 #endif
00029 
00030 using utest::v1::Case;
00031 
00032 extern uint32_t mbed_heap_size;
00033 static const int test_timeout = 25;
00034 volatile bool thread_should_continue = true;
00035 #define NUM_THREADS         4
00036 #define THREAD_MALLOC_SIZE  100
00037 
00038 #if defined(__CORTEX_A9)
00039 #define THREAD_STACK_SIZE   512
00040 #else
00041 #define THREAD_STACK_SIZE   256
00042 #endif
00043 
00044 
00045 void task_using_malloc(void)
00046 {
00047     void *data = NULL;
00048 
00049     while (thread_should_continue) {
00050         // Repeatedly allocate and free memory
00051         data = malloc(THREAD_MALLOC_SIZE);
00052         TEST_ASSERT_NOT_NULL(data);
00053 
00054         // test whole allocated memory
00055         memset(data, 0, THREAD_MALLOC_SIZE);
00056 
00057         free(data);
00058     }
00059 }
00060 
00061 /** Test for multithreaded heap allocations
00062 
00063     Given multiple threads are started in parallel
00064     When each of the threads allocate memory
00065     Then the memory allocation succeed and @a malloc return valid memory
00066  */
00067 void test_multithread_allocation(void)
00068 {
00069     // static stack for threads to reduce heap usage on devices with small RAM
00070     // and eliminate run out of heap memory problem
00071     uint8_t stack[NUM_THREADS][THREAD_STACK_SIZE];
00072 
00073     bool thread_alloc_failure = false;
00074     Thread *thread_list[NUM_THREADS];
00075     int test_time = 20;
00076 
00077     // Allocate threads for the test
00078     for (int i = 0; i < NUM_THREADS; i++) {
00079         thread_list[i] = new Thread(osPriorityNormal, THREAD_STACK_SIZE, stack[i]);
00080         if (NULL == thread_list[i]) {
00081             thread_alloc_failure = true;
00082         } else {
00083             thread_list[i]->start(task_using_malloc);
00084         }
00085     }
00086 
00087     // Give the test time to run
00088     while (test_time--) {
00089         Thread::wait(1000);
00090     }
00091 
00092     // Join and delete all threads
00093     thread_should_continue = false;
00094     for (int i = 0; i < NUM_THREADS; i++) {
00095         if (NULL != thread_list[i]) {
00096             thread_list[i]->join();
00097             delete thread_list[i];
00098             thread_list[i] = NULL;
00099         }
00100     }
00101     TEST_ASSERT_FALSE(thread_alloc_failure);
00102 }
00103 
00104 /** Test for large heap allocation
00105 
00106     Given a heap of size mbed_heap_size
00107     When try to allocate memory of size mbed_heap_size/5 (20% of whole heap)
00108     Then the memory is allocated and @a malloc return valid memory
00109  */
00110 void test_big_allocation(void)
00111 {
00112     const uint32_t alloc_size = mbed_heap_size / 5;
00113     void *data = NULL;
00114 
00115     data = malloc(alloc_size);
00116     TEST_ASSERT_NOT_NULL(data);
00117 
00118     // test whole allocated memory
00119     memset(data, 0, alloc_size);
00120 
00121     free(data);
00122 }
00123 
00124 /** Test if allocation of zero size does not cause any undefined behaviour
00125 
00126     Given a heap
00127     When try to allocate memory of size 0
00128     Then the return value of @a malloc depends on the particular library implementation
00129      (NULL or smallest possible allocation) and no undefined behaviour happens
00130 
00131     @note If allocation size is zero, the return value depends on the particular library implementation
00132     (it may or may not be a null pointer), but the returned pointer shall not be dereferenced
00133  */
00134 void test_zero_allocation(void)
00135 {
00136     void *data = NULL;
00137 
00138     data = malloc(0);
00139     if(data != NULL) {
00140         free(data);
00141     }
00142     TEST_ASSERT_MESSAGE(true, "malloc(0) succeed - no undefined behaviour happens");
00143 }
00144 
00145 /** Test if free on NULL pointer does not cause any undefined behaviour
00146 
00147     Given a NULL pointer
00148     When try to free it
00149     Then the function @a free does nothing and no undefined behaviour happens
00150  */
00151 void test_null_free(void)
00152 {
00153     void *data = NULL;
00154     free(data);
00155 
00156     TEST_ASSERT_MESSAGE(true, "free(NULL) succeed - no undefined behaviour happens");
00157 }
00158 
00159 // Test cases
00160 Case cases[] = {
00161     Case("Test 0 size allocation", test_zero_allocation),
00162     Case("Test NULL pointer free", test_null_free),
00163     Case("Test multithreaded allocations", test_multithread_allocation),
00164     Case("Test large allocation", test_big_allocation)
00165 };
00166 
00167 utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
00168 {
00169     GREENTEA_SETUP(test_timeout, "timing_drift_auto");
00170     return utest::v1::greentea_test_setup_handler(number_of_cases);
00171 }
00172 
00173 utest::v1::Specification specification(greentea_test_setup, cases);
00174 
00175 int main()
00176 {
00177     return !utest::v1::Harness::run(specification);
00178 }