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 using utest::v1::Case;
00022 
00023 #if defined(MBED_RTOS_SINGLE_THREAD)
00024   #error [NOT_SUPPORTED] test not supported
00025 #endif
00026 
00027 #if !DEVICE_USTICKER
00028   #error [NOT_SUPPORTED] test not supported
00029 #endif
00030 
00031 #define TEST_STACK_SIZE   512
00032 #define MAX_FLAG_POS 30
00033 
00034 #define ALL_SIGNALS       0x7fffffff
00035 #define NO_SIGNALS        0x0
00036 #define PROHIBITED_SIGNAL 0x80000000
00037 #define SIGNAL1 0x1
00038 #define SIGNAL2 0x2
00039 #define SIGNAL3 0x4
00040 
00041 struct Sync {
00042     Sync(Semaphore &parent, Semaphore &child): sem_parent(parent), sem_child(child)
00043     {}
00044 
00045     Semaphore &sem_parent;
00046     Semaphore &sem_child;
00047 };
00048 
00049 
00050 /* In order to successfully run this test suite when compiled with --profile=debug
00051  * error() has to be redefined as noop.
00052  *
00053  * ThreadFlags calls RTX API which uses Event Recorder functionality. When compiled
00054  * with MBED_TRAP_ERRORS_ENABLED=1 (set in debug profile) EvrRtxEventFlagsError() calls error()
00055  * which aborts test program.
00056  */
00057 #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
00058 void error(const char* format, ...) {
00059     (void) format;
00060 }
00061 
00062 mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) 
00063 {
00064     return MBED_SUCCESS;
00065 }
00066 #endif
00067 
00068 
00069 template <int32_t signals, uint32_t timeout, int32_t test_val>
00070 void run_signal_wait(void)
00071 {
00072     osEvent ev = Thread::signal_wait(signals, timeout);
00073     TEST_ASSERT_EQUAL(test_val, ev.status);
00074 }
00075 
00076 template <int32_t signals, uint32_t timeout, int32_t test_val>
00077 void run_release_signal_wait(Semaphore *sem)
00078 {
00079     sem->release();
00080     osEvent ev = Thread::signal_wait(signals, timeout);
00081     TEST_ASSERT_EQUAL(test_val, ev.status);
00082 }
00083 
00084 template <int32_t signals, uint32_t timeout, int32_t test_val>
00085 void run_release_wait_signal_wait(Sync *sync)
00086 {
00087     sync->sem_parent.release();
00088     sync->sem_child.wait();
00089     osEvent ev = Thread::signal_wait(signals, timeout);
00090     TEST_ASSERT_EQUAL(test_val, ev.status);
00091 }
00092 
00093 template <int32_t signals, int32_t test_val>
00094 void run_clear(void)
00095 {
00096     int32_t ret = Thread::signal_clr(signals);
00097     TEST_ASSERT_EQUAL(test_val, ret);
00098 }
00099 
00100 template <int32_t signals, int32_t test_val>
00101 void run_wait_clear(Sync *sync)
00102 {
00103     sync->sem_parent.release();
00104     sync->sem_child.wait();
00105     int32_t ret = Thread::signal_clr(signals);
00106     TEST_ASSERT_EQUAL(test_val, ret);
00107 }
00108 
00109 template <int32_t signals1, int32_t signals2, int32_t test_val1, int32_t test_val2>
00110 void run_double_wait_clear(Sync *sync)
00111 {
00112     int32_t ret;
00113 
00114     sync->sem_parent.release();
00115     sync->sem_child.wait();
00116     ret = Thread::signal_clr(signals1);
00117     TEST_ASSERT_EQUAL(test_val1, ret);
00118 
00119     ret = Thread::signal_clr(signals2);
00120     TEST_ASSERT_EQUAL(test_val2, ret);
00121 }
00122 
00123 void run_loop_wait_clear(Sync *sync)
00124 {
00125     int32_t signals = NO_SIGNALS;
00126     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00127         int32_t signal = 1 << i;
00128         signals |= signal;
00129         sync->sem_child.wait();
00130         int32_t ret = Thread::signal_clr(NO_SIGNALS);
00131         TEST_ASSERT_EQUAL(signals, ret);
00132         sync->sem_parent.release();
00133     }
00134 }
00135 
00136 
00137 /** Validate that call signal_clr(NO_SIGNALS) doesn't change thread signals and return actual signals
00138 
00139     Given two threads A & B are started, B with all signals already set
00140     When thread B calls @a signal_clr(NO_SIGNALS)
00141     Then thread B @a signal_clr status should be ALL_SIGNALS indicating that thread B state is unchanged
00142  */
00143 void test_clear_no_signals(void)
00144 {
00145     Semaphore sem_parent(0, 1);
00146     Semaphore sem_child(0, 1);
00147     Sync sync(sem_parent, sem_child);
00148 
00149     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00150     t.start(callback(run_double_wait_clear<NO_SIGNALS, NO_SIGNALS, ALL_SIGNALS, ALL_SIGNALS>, &sync));
00151     sem_parent.wait();
00152     t.signal_set(ALL_SIGNALS);
00153     sem_child.release();
00154     t.join();
00155 }
00156 
00157 /** Validate if any signals are set on just created thread
00158 
00159     Given the thread is running
00160     When thread execute @a signal_clr(NO_SIGNALS)
00161     Then thread @a signal_clr return status should be NO_SIGNALS(0) indicating no signals set
00162  */
00163 void test_init_state(void)
00164 {
00165     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00166     t.start(callback(run_clear<NO_SIGNALS, NO_SIGNALS>));
00167     t.join();
00168 }
00169 
00170 /** Validate all signals set in one shot
00171 
00172     Given two threads A & B are started
00173     When thread A call @a signal_set(ALL_SIGNALS) with all possible signals
00174     Then thread B @a signal_clr(NO_SIGNALS) status should be ALL_SIGNALS indicating all signals set correctly
00175  */
00176 void test_set_all(void)
00177 {
00178     int32_t ret;
00179     Semaphore sem_parent(0, 1);
00180     Semaphore sem_child(0, 1);
00181     Sync sync(sem_parent, sem_child);
00182 
00183     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00184     t.start(callback(run_wait_clear<NO_SIGNALS, ALL_SIGNALS>, &sync));
00185 
00186     sem_parent.wait();
00187     ret = t.signal_set(ALL_SIGNALS);
00188     TEST_ASSERT_EQUAL(ALL_SIGNALS, ret);
00189 
00190     sem_child.release();
00191     t.join();
00192 }
00193 
00194 /** Validate that call signal_set with prohibited signal doesn't change thread signals
00195 
00196     Given two threads A & B are started, B with all signals set
00197     When thread A executes @a signal_set(PROHIBITED_SIGNAL) with prohibited signal
00198     Then thread B @a signal_clr(NO_SIGNALS) status should be ALL_SIGNALS indicating that thread B signals are unchanged
00199 
00200     @note Each signal has up to 31 event flags 0x1, 0x2, 0x4, 0x8, ...,  0x40000000
00201           Most significant bit is reserved and thereby flag 0x80000000 is prohibited
00202  */
00203 void test_set_prohibited(void)
00204 {
00205     int32_t ret;
00206     Semaphore sem_parent(0, 1);
00207     Semaphore sem_child(0, 1);
00208     Sync sync(sem_parent, sem_child);
00209 
00210     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00211     t.start(callback(run_wait_clear<NO_SIGNALS, ALL_SIGNALS>, &sync));
00212 
00213     sem_parent.wait();
00214     t.signal_set(ALL_SIGNALS);
00215 
00216     ret = t.signal_set(PROHIBITED_SIGNAL);
00217     TEST_ASSERT_EQUAL(osErrorParameter, ret);
00218 
00219     sem_child.release();
00220     t.join();
00221 }
00222 
00223 /** Validate all signals clear in one shot
00224 
00225     Given two threads A & B are started, B with all signals set
00226     When thread B execute @a signal_clr(ALL_SIGNALS) with all possible signals
00227     Then thread B @a signal_clr(NO_SIGNALS) status should be NO_SIGNALS(0) indicating all signals cleared correctly
00228  */
00229 void test_clear_all(void)
00230 {
00231     Semaphore sem_parent(0, 1);
00232     Semaphore sem_child(0, 1);
00233     Sync sync(sem_parent, sem_child);
00234 
00235     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00236     t.start(callback(run_double_wait_clear<ALL_SIGNALS, NO_SIGNALS, ALL_SIGNALS, NO_SIGNALS>, &sync));
00237     sem_parent.wait();
00238     t.signal_set(ALL_SIGNALS);
00239     sem_child.release();
00240     t.join();
00241 }
00242 
00243 /** Validate all signals set one by one in loop
00244 
00245     Given two threads A & B are started
00246     When thread A executes @a signal_set(signal) in loop with all possible signals
00247  */
00248 void test_set_all_loop(void)
00249 {
00250     int32_t ret;
00251     Semaphore sem_parent(0, 1);
00252     Semaphore sem_child(0, 1);
00253     Sync sync(sem_parent, sem_child);
00254 
00255     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00256     t.start(callback(run_loop_wait_clear, &sync));
00257 
00258     int32_t signals = 0;
00259     for (int i = 0; i <= MAX_FLAG_POS; i++) {
00260         int32_t signal = 1 << i;
00261 
00262         ret = t.signal_set(signal);
00263         signals |= signal;
00264         TEST_ASSERT_EQUAL(signals, ret);
00265         sem_child.release();
00266         sem_parent.wait();
00267     }
00268     t.join();
00269 }
00270 
00271 /** Validate signal_wait return status if timeout specified
00272 
00273     Given the thread is running
00274     When thread executes @a signal_wait(signals, timeout) with specified signals and timeout
00275     Then thread @a signal_wait status should be osEventTimeout indicating a timeout
00276          thread @a signal_wait status should be osOK indicating 0[ms] timeout set
00277  */
00278 template <int32_t signals, uint32_t timeout, int32_t status>
00279 void test_wait_timeout(void)
00280 {
00281     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00282     t.start(callback(run_signal_wait<signals, timeout, status>));
00283     t.join();
00284 }
00285 
00286 /** Validate that call of signal_wait return correctly when thread has all signals already set
00287 
00288     Given two threads A & B are started, B with all signals already set
00289     When thread B executes @a signal_wait(ALL_SIGNALS, osWaitForever),
00290     Then thread B @a signal_wait return immediately with status osEventSignal indicating all wait signals was already set
00291  */
00292 void test_wait_all_already_set(void)
00293 {
00294     Semaphore sem_parent(0, 1);
00295     Semaphore sem_child(0, 1);
00296     Sync sync(sem_parent, sem_child);
00297 
00298     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00299     t.start(callback(run_release_wait_signal_wait<ALL_SIGNALS, osWaitForever, osEventSignal>, &sync));
00300 
00301     sem_parent.wait();
00302     TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
00303     t.signal_set(ALL_SIGNALS);
00304     sem_child.release();
00305     t.join();
00306 }
00307 
00308 /** Validate if signal_wait return correctly when all signals set
00309 
00310     Given two threads A & B are started and B waiting for a thread flag to be set
00311     When thread A executes @a signal_set(ALL_SIGNALS) with all possible signals
00312     Then thread B @a signal_wait status is osEventSignal indicating all wait signals was set
00313  */
00314 void test_wait_all(void)
00315 {
00316     Semaphore sem(0, 1);
00317 
00318     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00319     t.start(callback(run_release_signal_wait<ALL_SIGNALS, osWaitForever, osEventSignal>, &sem));
00320 
00321     sem.wait();
00322     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00323 
00324     t.signal_set(ALL_SIGNALS);
00325     t.join();
00326 }
00327 
00328 /** Validate if signal_wait accumulate signals and return correctly when all signals set
00329 
00330     Given two threads A & B are started and B waiting for a thread signals to be set
00331     When thread A executes @a signal_set setting all signals in loop
00332     Then thread B @a signal_wait status is osEventSignal indicating that all wait signals was set
00333  */
00334 void test_wait_all_loop(void)
00335 {
00336     int32_t ret;
00337     Semaphore sem(0, 1);
00338 
00339     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00340     t.start(callback(run_release_signal_wait<ALL_SIGNALS, osWaitForever, osEventSignal>, &sem));
00341 
00342     sem.wait();
00343     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00344 
00345     for (int i = 0; i < MAX_FLAG_POS; i++) {
00346         int32_t signal = 1 << i;
00347         ret = t.signal_set(signal);
00348     }
00349     ret = t.signal_set(1 << MAX_FLAG_POS);
00350     TEST_ASSERT_EQUAL(NO_SIGNALS, ret);
00351     t.join();
00352 }
00353 
00354 /** Validate if setting same signal twice cause any unwanted behaviour
00355 
00356     Given two threads A & B are started and B waiting for a thread signals to be set
00357     When thread A executes @a signal_set twice for the same signal
00358     Then thread A @a signal_set status is current signal set
00359          thread B @a signal_wait status is osEventSignal indicating that all wait signals was set
00360  */
00361 void test_set_double(void)
00362 {
00363     int32_t ret;
00364     Semaphore sem(0, 1);
00365 
00366     Thread t(osPriorityNormal, TEST_STACK_SIZE);
00367     t.start(callback(run_release_signal_wait<SIGNAL1|SIGNAL2|SIGNAL3, osWaitForever, osEventSignal>, &sem));
00368 
00369     sem.wait();
00370     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00371 
00372     ret = t.signal_set(SIGNAL1);
00373     TEST_ASSERT_EQUAL(SIGNAL1, ret);
00374 
00375     ret = t.signal_set(SIGNAL2);
00376     TEST_ASSERT_EQUAL(SIGNAL1 | SIGNAL2, ret);
00377 
00378     ret = t.signal_set(SIGNAL2);
00379     TEST_ASSERT_EQUAL(SIGNAL1 | SIGNAL2, ret);
00380     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00381 
00382     ret = t.signal_set(SIGNAL3);
00383     TEST_ASSERT_EQUAL(NO_SIGNALS, ret);
00384     t.join();
00385 }
00386 
00387 
00388 utest::v1::status_t test_setup(const size_t number_of_cases)
00389 {
00390     GREENTEA_SETUP(10, "default_auto");
00391     return utest::v1::verbose_test_setup_handler(number_of_cases);
00392 }
00393 
00394 Case cases[] = {
00395     Case("Validate that call signal_clr(NO_SIGNALS) doesn't change thread signals and return actual signals", test_clear_no_signals),
00396     Case("Validate if any signals are set on just created thread", test_init_state),
00397     Case("Validate all signals set in one shot", test_set_all),
00398     Case("Validate that call signal_set with prohibited signal doesn't change thread signals", test_set_prohibited),
00399     Case("Validate all signals clear in one shot", test_clear_all),
00400     Case("Validate all signals set one by one in loop", test_set_all_loop),
00401     Case("Validate signal_wait return status if timeout specified: 0[ms] no signals", test_wait_timeout<0, 0, osOK>),
00402     Case("Validate signal_wait return status if timeout specified: 0[ms] all signals", test_wait_timeout<ALL_SIGNALS, 0, osOK>),
00403     Case("Validate signal_wait return status if timeout specified: 1[ms] no signals", test_wait_timeout<0, 1, osEventTimeout>),
00404     Case("Validate signal_wait return status if timeout specified: 1[ms] all signals", test_wait_timeout<ALL_SIGNALS, 1, osEventTimeout>),
00405     Case("Validate that call of signal_wait return correctly when thread has all signals already set", test_wait_all_already_set),
00406     Case("Validate if signal_wait return correctly when all signals set", test_wait_all),
00407     Case("Validate if signal_wait accumulate signals and return correctly when all signals set", test_wait_all_loop),
00408     Case("Validate if setting same signal twice cause any unwanted behaviour", test_set_double)
00409 };
00410 
00411 utest::v1::Specification specification(test_setup, cases);
00412 
00413 int main()
00414 {
00415     return !utest::v1::Harness::run(specification);
00416 }