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 using namespace utest::v1; 00023 00024 #if defined(MBED_RTOS_SINGLE_THREAD) 00025 #error [NOT_SUPPORTED] test not supported 00026 #endif 00027 00028 #define THREAD_DELAY 30 00029 #define SEMAPHORE_SLOTS 2 00030 #define SEM_CHANGES 100 00031 #define SHORT_WAIT 5 00032 00033 #define THREAD_STACK_SIZE 320 /* larger stack cause out of heap memory on some 16kB RAM boards in multi thread test*/ 00034 00035 Semaphore two_slots(SEMAPHORE_SLOTS); 00036 00037 volatile int change_counter = 0; 00038 volatile int sem_counter = 0; 00039 volatile bool sem_defect = false; 00040 00041 void test_thread(int const *delay) 00042 { 00043 const int thread_delay = *delay; 00044 while (true) { 00045 two_slots.wait(); 00046 sem_counter++; 00047 const bool sem_lock_failed = sem_counter > SEMAPHORE_SLOTS; 00048 if (sem_lock_failed) { 00049 sem_defect = true; 00050 } 00051 Thread::wait(thread_delay); 00052 sem_counter--; 00053 change_counter++; 00054 two_slots.release(); 00055 } 00056 } 00057 00058 /* Test multiple threads 00059 00060 Given 3 threads started with different delays and a semaphore with 2 tokens 00061 when each thread runs it tries to acquire a token 00062 then no more than two threads should be able to access protected region 00063 */ 00064 void test_multi() 00065 { 00066 const int t1_delay = THREAD_DELAY * 1; 00067 const int t2_delay = THREAD_DELAY * 2; 00068 const int t3_delay = THREAD_DELAY * 3; 00069 00070 Thread t1(osPriorityNormal, THREAD_STACK_SIZE); 00071 Thread t2(osPriorityNormal, THREAD_STACK_SIZE); 00072 Thread t3(osPriorityNormal, THREAD_STACK_SIZE); 00073 00074 t1.start(callback(test_thread, &t1_delay)); 00075 t2.start(callback(test_thread, &t2_delay)); 00076 t3.start(callback(test_thread, &t3_delay)); 00077 00078 while (true) { 00079 if (change_counter >= SEM_CHANGES or sem_defect == true) { 00080 t1.terminate(); 00081 t2.terminate(); 00082 t3.terminate(); 00083 break; 00084 } 00085 } 00086 } 00087 00088 struct thread_data { 00089 Semaphore *sem; 00090 uint32_t data; 00091 }; 00092 00093 void single_thread(struct thread_data *data) 00094 { 00095 int32_t cnt = data->sem->wait(); 00096 TEST_ASSERT_EQUAL(1, cnt); 00097 data->data++; 00098 } 00099 00100 /** Test single thread 00101 00102 Given a two threads A & B and a semaphore (with count of 0) and a counter (equals to 0) 00103 when thread B calls @a wait 00104 then thread B waits for a token to become available 00105 then the counter is equal to 0 00106 when thread A calls @a release on the semaphore 00107 then thread B acquires a token and increments the counter 00108 then the counter equals to 1 00109 */ 00110 void test_single_thread() 00111 { 00112 Thread t(osPriorityNormal, THREAD_STACK_SIZE); 00113 Semaphore sem(0); 00114 struct thread_data data; 00115 osStatus res; 00116 00117 data.sem = &sem; 00118 data.data = 0; 00119 00120 res = t.start(callback(single_thread, &data)); 00121 TEST_ASSERT_EQUAL(osOK, res); 00122 Thread::wait(SHORT_WAIT); 00123 00124 TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state()); 00125 TEST_ASSERT_EQUAL(0, data.data); 00126 00127 res = sem.release(); 00128 TEST_ASSERT_EQUAL(osOK, res); 00129 00130 Thread::wait(SHORT_WAIT); 00131 00132 TEST_ASSERT_EQUAL(1, data.data); 00133 00134 t.join(); 00135 } 00136 00137 void timeout_thread(Semaphore *sem) 00138 { 00139 int32_t cnt = sem->wait(30); 00140 TEST_ASSERT_EQUAL(0, cnt); 00141 } 00142 00143 /** Test timeout 00144 00145 Given thread and a semaphore with no tokens available 00146 when thread calls @a wait on the semaphore with timeout of 10ms 00147 then the thread waits for 10ms and timeouts after 00148 */ 00149 void test_timeout() 00150 { 00151 Thread t(osPriorityNormal, THREAD_STACK_SIZE); 00152 Semaphore sem(0); 00153 osStatus res; 00154 00155 Timer timer; 00156 timer.start(); 00157 res = t.start(callback(timeout_thread, &sem)); 00158 TEST_ASSERT_EQUAL(osOK, res); 00159 Thread::wait(SHORT_WAIT); 00160 00161 TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state()); 00162 00163 t.join(); 00164 TEST_ASSERT_UINT32_WITHIN(5000, 30000, timer.read_us()); 00165 } 00166 00167 /** Test no timeouts 00168 00169 Test 1 token no timeout 00170 Given thread and a semaphore with one token available 00171 when thread calls @a wait on the semaphore with timeout of 0ms 00172 then the thread acquires the token immediately 00173 00174 Test 0 tokens no timeout 00175 Given thread and a semaphore with no tokens available 00176 when thread calls @a wait on the semaphore with timeout of 0ms 00177 then the thread returns immediately without acquiring a token 00178 */ 00179 template<int T> 00180 void test_no_timeout() 00181 { 00182 Semaphore sem(T); 00183 00184 Timer timer; 00185 timer.start(); 00186 00187 int32_t cnt = sem.wait(0); 00188 TEST_ASSERT_EQUAL(T, cnt); 00189 00190 TEST_ASSERT_UINT32_WITHIN(5000, 0, timer.read_us()); 00191 } 00192 00193 /** Test multiple tokens wait 00194 00195 Given a thread and a semaphore initialized with 5 tokens 00196 when thread calls @a wait 6 times on the semaphore 00197 then the token counts goes to zero 00198 */ 00199 void test_multiple_tokens_wait() 00200 { 00201 Semaphore sem(5); 00202 00203 for(int i = 5; i >= 0; i--) { 00204 int32_t cnt = sem.wait(0); 00205 TEST_ASSERT_EQUAL(i, cnt); 00206 } 00207 } 00208 00209 /** Test multiple tokens release 00210 00211 Given a thread and a semaphore initialized with zero tokens and max of 5 00212 when thread calls @a release 6 times on the semaphore 00213 then the token count should be equal to 5 and last release call should fail 00214 */ 00215 void test_multiple_tokens_release() 00216 { 00217 Semaphore sem(0, 5); 00218 00219 for(int i = 5; i > 0; i--) { 00220 osStatus stat = sem.release(); 00221 TEST_ASSERT_EQUAL(osOK, stat); 00222 } 00223 osStatus stat = sem.release(); 00224 TEST_ASSERT_EQUAL(osErrorResource, stat); 00225 } 00226 00227 utest::v1::status_t test_setup(const size_t number_of_cases) 00228 { 00229 GREENTEA_SETUP(10, "default_auto"); 00230 return verbose_test_setup_handler(number_of_cases); 00231 } 00232 00233 Case cases[] = { 00234 Case("Test single thread", test_single_thread), 00235 Case("Test timeout", test_timeout), 00236 Case("Test 1 token no timeout", test_no_timeout<1>), 00237 Case("Test 0 tokens no timeout", test_no_timeout<0>), 00238 Case("Test multiple tokens wait", test_multiple_tokens_wait), 00239 Case("Test multiple tokens release", test_multiple_tokens_release), 00240 Case("Test multiple threads", test_multi) 00241 }; 00242 00243 Specification specification(test_setup, cases); 00244 00245 int main() 00246 { 00247 return !Harness::run(specification); 00248 }
Generated on Thu Jul 14 2022 14:36:19 by
