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