Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 "unity.h" 00019 #include "utest.h" 00020 #include "rtos.h" 00021 00022 #if defined(MBED_RTOS_SINGLE_THREAD) 00023 #error [NOT_SUPPORTED] test not supported 00024 #endif 00025 00026 using namespace utest::v1; 00027 00028 #define TEST_STACK_SIZE 512 00029 00030 #define TEST_LONG_DELAY 20 00031 #define TEST_DELAY 10 00032 #define SIGNALS_TO_EMIT 100 00033 00034 Mutex stdio_mutex; 00035 00036 volatile int change_counter = 0; 00037 volatile bool changing_counter = false; 00038 volatile bool mutex_defect = false; 00039 00040 bool manipulate_protected_zone(const int thread_delay) 00041 { 00042 bool result = true; 00043 00044 osStatus stat = stdio_mutex.lock(); 00045 TEST_ASSERT_EQUAL(osOK, stat); 00046 00047 core_util_critical_section_enter(); 00048 if (changing_counter == true) { 00049 result = false; 00050 mutex_defect = true; 00051 } 00052 changing_counter = true; 00053 00054 change_counter++; 00055 core_util_critical_section_exit(); 00056 00057 Thread::wait(thread_delay); 00058 00059 core_util_critical_section_enter(); 00060 changing_counter = false; 00061 core_util_critical_section_exit(); 00062 00063 stat = stdio_mutex.unlock(); 00064 TEST_ASSERT_EQUAL(osOK, stat); 00065 return result; 00066 } 00067 00068 void test_thread(int const *thread_delay) 00069 { 00070 while (true) { 00071 manipulate_protected_zone(*thread_delay); 00072 } 00073 } 00074 00075 /** Test multiple thread 00076 00077 Given 3 threads started with different delays and a section protected with a mutex 00078 when each thread runs it tries to lock the mutex 00079 then no more than one thread should be able to access protected region 00080 */ 00081 void test_multiple_threads(void) 00082 { 00083 const int t1_delay = TEST_DELAY * 1; 00084 const int t2_delay = TEST_DELAY * 2; 00085 const int t3_delay = TEST_DELAY * 3; 00086 00087 Thread t2(osPriorityNormal, TEST_STACK_SIZE); 00088 Thread t3(osPriorityNormal, TEST_STACK_SIZE); 00089 00090 t2.start(callback(test_thread, &t2_delay)); 00091 t3.start(callback(test_thread, &t3_delay)); 00092 00093 while (true) { 00094 // Thread 1 action 00095 Thread::wait(t1_delay); 00096 manipulate_protected_zone(t1_delay); 00097 00098 core_util_critical_section_enter(); 00099 if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) { 00100 core_util_critical_section_exit(); 00101 t2.terminate(); 00102 t3.terminate(); 00103 break; 00104 } 00105 core_util_critical_section_exit(); 00106 } 00107 00108 TEST_ASSERT_EQUAL(false, mutex_defect); 00109 } 00110 00111 void test_dual_thread_nolock_lock_thread(Mutex *mutex) 00112 { 00113 osStatus stat = mutex->lock(osWaitForever); 00114 TEST_ASSERT_EQUAL(osOK, stat); 00115 00116 stat = mutex->unlock(); 00117 TEST_ASSERT_EQUAL(osOK, stat); 00118 } 00119 00120 void test_dual_thread_nolock_trylock_thread(Mutex *mutex) 00121 { 00122 bool stat_b = mutex->trylock(); 00123 TEST_ASSERT_EQUAL(true, stat_b); 00124 00125 osStatus stat = mutex->unlock(); 00126 TEST_ASSERT_EQUAL(osOK, stat); 00127 } 00128 00129 /** Test dual thread no-lock 00130 00131 Test dual thread second thread lock 00132 Given two threads A & B and a mutex 00133 When thread A creates a mutex and starts thread B 00134 and thread B calls @a lock and @a unlock 00135 Then returned statuses are osOK 00136 00137 Test dual thread second thread trylock 00138 Given two threads A & B and a mutex 00139 When thread A creates a mutex and starts thread B 00140 and thread B calls @a trylock and @a unlock 00141 Then returned statuses are true and osOK 00142 */ 00143 template <void (*F)(Mutex *)> 00144 void test_dual_thread_nolock(void) 00145 { 00146 Mutex mutex; 00147 Thread thread(osPriorityNormal, TEST_STACK_SIZE); 00148 00149 thread.start(callback(F, &mutex)); 00150 00151 wait_ms(TEST_DELAY); 00152 } 00153 00154 void test_dual_thread_lock_unlock_thread(Mutex *mutex) 00155 { 00156 osStatus stat = mutex->lock(osWaitForever); 00157 TEST_ASSERT_EQUAL(osOK, stat); 00158 } 00159 00160 /** Test dual thread lock unlock 00161 00162 Given two threads and a lock 00163 When thread A locks the lock and starts thread B 00164 and thread B calls @a lock on the mutex 00165 Then thread B waits for thread A to unlock the lock 00166 When thread A calls @a unlock on the mutex 00167 Then thread B acquires the lock 00168 */ 00169 void test_dual_thread_lock_unlock(void) 00170 { 00171 Mutex mutex; 00172 osStatus stat; 00173 Thread thread(osPriorityNormal, TEST_STACK_SIZE); 00174 00175 stat = mutex.lock(); 00176 TEST_ASSERT_EQUAL(osOK, stat); 00177 00178 thread.start(callback(test_dual_thread_lock_unlock_thread, &mutex)); 00179 00180 stat = mutex.unlock(); 00181 TEST_ASSERT_EQUAL(osOK, stat); 00182 00183 wait_ms(TEST_DELAY); 00184 } 00185 00186 void test_dual_thread_lock_trylock_thread(Mutex *mutex) 00187 { 00188 bool stat = mutex->trylock(); 00189 TEST_ASSERT_EQUAL(false, stat); 00190 } 00191 00192 void test_dual_thread_lock_lock_thread(Mutex *mutex) 00193 { 00194 Timer timer; 00195 timer.start(); 00196 00197 osStatus stat = mutex->lock(TEST_DELAY); 00198 TEST_ASSERT_EQUAL(osErrorTimeout, stat); 00199 TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY*1000, timer.read_us()); 00200 } 00201 00202 /** Test dual thread lock 00203 00204 Test dual thread lock locked 00205 Given a mutex and two threads A & B 00206 When thread A calls @a lock and starts thread B 00207 and thread B calls @a lock with 500ms timeout 00208 Then thread B waits 500ms and timeouts 00209 00210 Test dual thread trylock locked 00211 Given a mutex and two threads A & B 00212 When thread A calls @a lock and starts thread B 00213 Then thread B calls @a trylock 00214 and thread B fails to acquire the lock 00215 */ 00216 template <void (*F)(Mutex *)> 00217 void test_dual_thread_lock(void) 00218 { 00219 Mutex mutex; 00220 osStatus stat; 00221 Thread thread(osPriorityNormal, TEST_STACK_SIZE); 00222 00223 stat = mutex.lock(); 00224 TEST_ASSERT_EQUAL(osOK, stat); 00225 00226 thread.start(callback(F, &mutex)); 00227 00228 wait_ms(TEST_LONG_DELAY); 00229 00230 stat = mutex.unlock(); 00231 TEST_ASSERT_EQUAL(osOK, stat); 00232 } 00233 00234 /** Test single thread lock recursive 00235 00236 Given a mutex and a single running thread 00237 When thread calls @a lock twice and @a unlock twice on the mutex 00238 Then the returned statuses are osOK 00239 */ 00240 void test_single_thread_lock_recursive(void) 00241 { 00242 Mutex mutex; 00243 osStatus stat; 00244 00245 stat = mutex.lock(); 00246 TEST_ASSERT_EQUAL(osOK, stat); 00247 00248 stat = mutex.lock(); 00249 TEST_ASSERT_EQUAL(osOK, stat); 00250 00251 stat = mutex.unlock(); 00252 TEST_ASSERT_EQUAL(osOK, stat); 00253 00254 stat = mutex.unlock(); 00255 TEST_ASSERT_EQUAL(osOK, stat); 00256 } 00257 00258 /** Test single thread trylock 00259 00260 Given a mutex and a single running thread 00261 When thread calls @a trylock and @a unlock on the mutex 00262 Then the returned statuses are osOK 00263 */ 00264 void test_single_thread_trylock(void) 00265 { 00266 Mutex mutex; 00267 00268 bool stat_b = mutex.trylock(); 00269 TEST_ASSERT_EQUAL(true, stat_b); 00270 00271 osStatus stat = mutex.unlock(); 00272 TEST_ASSERT_EQUAL(osOK, stat); 00273 } 00274 00275 /** Test single thread lock 00276 00277 Given a mutex and a single running thread 00278 When thread calls @a lock and @a unlock on the mutex 00279 Then the returned statuses are osOK 00280 */ 00281 void test_single_thread_lock(void) 00282 { 00283 Mutex mutex; 00284 osStatus stat; 00285 00286 stat = mutex.lock(); 00287 TEST_ASSERT_EQUAL(osOK, stat); 00288 00289 stat = mutex.unlock(); 00290 TEST_ASSERT_EQUAL(osOK, stat); 00291 } 00292 00293 utest::v1::status_t test_setup(const size_t number_of_cases) 00294 { 00295 GREENTEA_SETUP(10, "default_auto"); 00296 return verbose_test_setup_handler(number_of_cases); 00297 } 00298 00299 Case cases[] = { 00300 Case("Test single thread lock", test_single_thread_lock), 00301 Case("Test single thread trylock", test_single_thread_trylock), 00302 Case("Test single thread lock recursive", test_single_thread_lock_recursive), 00303 Case("Test dual thread lock locked", test_dual_thread_lock<test_dual_thread_lock_lock_thread>), 00304 Case("Test dual thread trylock locked", test_dual_thread_lock<test_dual_thread_lock_trylock_thread>), 00305 Case("Test dual thread lock unlock", test_dual_thread_lock_unlock), 00306 Case("Test dual thread second thread lock", test_dual_thread_nolock<test_dual_thread_nolock_lock_thread>), 00307 Case("Test dual thread second thread trylock", test_dual_thread_nolock<test_dual_thread_nolock_trylock_thread>), 00308 Case("Test multiple thread", test_multiple_threads), 00309 }; 00310 00311 Specification specification(test_setup, cases); 00312 00313 int main() 00314 { 00315 return !Harness::run(specification); 00316 }
Generated on Thu Jul 14 2022 14:36:19 by
