diff --git a/TESTS/mbedmicro-rtos-mbed/signals/main.cpp b/TESTS/mbedmicro-rtos-mbed/signals/main.cpp index 1418bd2c8f..0a4d7caef5 100644 --- a/TESTS/mbedmicro-rtos-mbed/signals/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/signals/main.cpp @@ -14,10 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#if defined(MBED_RTOS_SINGLE_THREAD) || !defined(MBED_CONF_RTOS_PRESENT) -#error [NOT_SUPPORTED] Signals test cases require RTOS with multithread to run -#else - #include "mbed.h" #include "greentea-client/test_env.h" #include "utest/utest.h" @@ -29,16 +25,166 @@ using utest::v1::Case; #error [NOT_SUPPORTED] UsTicker need to be enabled for this test. #else -#define TEST_STACK_SIZE 512 -#define MAX_FLAG_POS 30 - #define ALL_SIGNALS 0x7fffffff #define NO_SIGNALS 0x0 -#define PROHIBITED_SIGNAL 0x80000000 + #define SIGNAL1 0x1 #define SIGNAL2 0x2 #define SIGNAL3 0x4 +template +void run_signal_wait(void) +{ + uint32_t ret = ThisThread::flags_wait_all_for(signals, timeout); + TEST_ASSERT_EQUAL(test_val, ret); +} + +template +void run_clear(void) +{ + int32_t ret = ThisThread::flags_clear(signals); + TEST_ASSERT_EQUAL(test_val, ret); +} + +void run_multiple_wait_clear(int32_t signals1, int32_t signals2, int32_t test_val1, int32_t test_val2) +{ + int32_t ret; + ret = ThisThread::flags_clear(signals1); + TEST_ASSERT_EQUAL(test_val1, ret); + ret = ThisThread::flags_clear(signals2); + TEST_ASSERT_EQUAL(test_val2, ret); +} +/** Validate that ticker callback to flags_clr(NO_SIGNALS) doesn't change main thread signals and return actual signals + + Given main thread and ticker instance with callback registered + When callback calls @a flags_clear(NO_SIGNALS) + then callback @a flags_clear return status should be ALL_SIGNALS indicating that the signal is unchanged + */ +void test_clear_no_signals_with_ticker(void) +{ + Ticker t; + osThreadFlagsSet(ThisThread::get_id(), ALL_SIGNALS); + t.attach_us([&] { run_multiple_wait_clear(NO_SIGNALS, NO_SIGNALS, ALL_SIGNALS, ALL_SIGNALS); }, 3000); +} + +/** Validate all flags_clr clears the signal in one shot + + Given main thread and ticker instance with callback registered + When callback calls @a flags_clear(ALL_SIGNALS) with all possible signals + then callback @a flags_clear(NO_SIGNALS) return status should be NO_SIGNALS(0) indicating all signals cleared correctly + */ +void test_clear_all_with_ticker(void) +{ + Ticker t; + osThreadFlagsSet(ThisThread::get_id(), ALL_SIGNALS); + t.attach_us([&] { run_multiple_wait_clear(ALL_SIGNALS, NO_SIGNALS, ALL_SIGNALS, NO_SIGNALS); }, 3000); +} + +/** Validate if any signals are set on ticker callback + + Given main thread and ticker instance with callback registered + When callback calls @a flags_clear(NO_SIGNALS) + then callback @a flags_clear return status should be NO_SIGNALS(0) indicating no signals set + */ +void test_init_state_with_ticker(void) +{ + Ticker t; + t.attach_us(callback(run_clear), 3000); +} + +/** Validate signal_wait return status if timeout specified + + Given main thread and ticker instance with callback registered + When callback calls @a flags_wait_all_for(signals, timeout) with specified signals and timeout + then callback @a flags_wait_all_for timeout and return 0 indicating no signals set + */ +template +void test_wait_timeout_with_ticker(void) +{ + Ticker t; + t.attach_us(callback(run_signal_wait), 3000); +} + +void run_release_wait_signal_wait_callback() +{ + osThreadFlagsSet(ThisThread::get_id(), ALL_SIGNALS); +} + +/** Validate that call of signal_wait return correctly when thread has all signals already set + + Given main thread and ticker instance with callback registered + When main thread @a flags_wait_all_for(ALL_SIGNALS, osWaitForever), + then main thread is blocked + when a callback calls @a osThreadFlagsSet set ALL_SIGNALS + then the main thread is unblocked from @ flags_wait_all_for with the return of ALL_SIGNALS set + */ +void test_wait_all_already_set_with_ticker(void) +{ + Ticker t; + t.attach_us([&] { run_release_wait_signal_wait_callback(); }, 3000); + uint32_t ret = ThisThread::flags_wait_all_for(ALL_SIGNALS, osWaitForever); + TEST_ASSERT_EQUAL(ALL_SIGNALS, ret); +} + +void run_release_wait_signal_set_callback(int32_t signal, osThreadId_t id) +{ + int32_t ret; + if (signal == 0) { + for (int i = 0; i < 16; i++) { + int32_t signal = 1 << i; + ret = osThreadFlagsSet(id, signal); + } + } else { + ret = osThreadFlagsSet(id, signal); + } +} + +/** Validate if wait_signal accumulate signals and return correctly when all signals set + + Given the main thread and ticker instance with callback registered + When main thread @a flags_wait_all_for, + then main thread is blocked + when a callback calls @a osThreadFlagsSet in a loop to set 16 different signal + then the main thread is unblocked from @ flags_wait_all_for with the return of expected different signals set + */ +void test_wait_all_loop_with_ticker(void) +{ + int32_t ret; + Semaphore sem(0, 1); + Ticker t; + osThreadId_t id = ThisThread::get_id(); + t.attach_us([&] { run_release_wait_signal_set_callback(0, id); }, 4000); + ret = ThisThread::flags_wait_all_for((ALL_SIGNALS & 0xFFFF), osWaitForever, true); + TEST_ASSERT_EQUAL((ALL_SIGNALS & 0xFFFF), ret); +} + +/** Validate if setting same signal twice cause any unwanted behaviour + + Given the main thread and two ticker instance with callback registered + When main thread @a flags_wait_all_for, + then main thread is blocked + when a first callback calls @a osThreadFlagsSet set SIGNAL2 and + second callback calls @a osThreadFlagsSet set SIGNAL1 | SIGNAL2 | SIGNAL3 with SIGNAL2 set again + then the main thread is unblocked from @ flags_wait_all_for with return of expected signals set + */ +void test_set_double_with_ticker(void) +{ + int32_t ret; + Ticker t1, t2; + osThreadId_t id = ThisThread::get_id(); + t1.attach_us([&] { run_release_wait_signal_set_callback(SIGNAL2, id); }, 3000); + t2.attach_us([&] { run_release_wait_signal_set_callback(SIGNAL1 | SIGNAL2 | SIGNAL3, id); }, 4000); + + ret = ThisThread::flags_wait_all_for((SIGNAL1 | SIGNAL2 | SIGNAL3), osWaitForever, true); + TEST_ASSERT_EQUAL(SIGNAL1 | SIGNAL2 | SIGNAL3, ret); +} + +#if defined(MBED_CONF_RTOS_PRESENT) + +#define TEST_STACK_SIZE 512 +#define PROHIBITED_SIGNAL 0x80000000 +#define MAX_FLAG_POS 30 + struct Sync { Sync(Semaphore &parent, Semaphore &child): sem_parent(parent), sem_child(child) {} @@ -47,13 +193,6 @@ struct Sync { Semaphore &sem_child; }; -template -void run_signal_wait(void) -{ - uint32_t ret = ThisThread::flags_wait_all_for(signals, timeout); - TEST_ASSERT_EQUAL(test_val, ret); -} - template void run_release_signal_wait(Semaphore *sem) { @@ -71,13 +210,6 @@ void run_release_wait_signal_wait(Sync *sync) TEST_ASSERT_EQUAL(test_val, ret); } -template -void run_clear(void) -{ - int32_t ret = ThisThread::flags_clear(signals); - TEST_ASSERT_EQUAL(test_val, ret); -} - template void run_wait_clear(Sync *sync) { @@ -87,20 +219,6 @@ void run_wait_clear(Sync *sync) TEST_ASSERT_EQUAL(test_val, ret); } -template -void run_double_wait_clear(Sync *sync) -{ - int32_t ret; - - sync->sem_parent.release(); - sync->sem_child.acquire(); - ret = ThisThread::flags_clear(signals1); - TEST_ASSERT_EQUAL(test_val1, ret); - - ret = ThisThread::flags_clear(signals2); - TEST_ASSERT_EQUAL(test_val2, ret); -} - void run_loop_wait_clear(Sync *sync) { int32_t signals = NO_SIGNALS; @@ -114,6 +232,19 @@ void run_loop_wait_clear(Sync *sync) } } +template +void run_double_wait_clear(Sync *sync) +{ + int32_t ret; + + sync->sem_parent.release(); + sync->sem_child.acquire(); + ret = ThisThread::flags_clear(signals1); + TEST_ASSERT_EQUAL(test_val1, ret); + + ret = ThisThread::flags_clear(signals2); + TEST_ASSERT_EQUAL(test_val2, ret); +} /** Validate that call signal_clr(NO_SIGNALS) doesn't change thread signals and return actual signals @@ -365,15 +496,26 @@ void test_set_double(void) TEST_ASSERT_EQUAL(NO_SIGNALS, ret); t.join(); } - +#endif utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(10, "default_auto"); + GREENTEA_SETUP(20, "default_auto"); return utest::v1::verbose_test_setup_handler(number_of_cases); } Case cases[] = { + Case("Validate that ticker callback flags_clear(NO_SIGNALS) doesn't change main thread flags and return actual flags", test_clear_no_signals_with_ticker), + Case("Validate if any flags are set on ticker callback", test_init_state_with_ticker), + Case("Validate all flags clear in one shot using ticker callback", test_clear_all_with_ticker), + Case("Validate ticker callback flags_wait return status if timeout specified: 0[ms] no flags", test_wait_timeout_with_ticker<0, 0, 0>), + Case("Validate ticker callback flags_wait return status if timeout specified: 0[ms] all flags", test_wait_timeout_with_ticker), + Case("Validate ticker callback flags_wait return status if timeout specified: 1[ms] no flags", test_wait_timeout_with_ticker<0, 1, 0>), + Case("Validate ticker callback flags_wait return status if timeout specified: 1[ms] all flags", test_wait_timeout_with_ticker), + Case("Validate that main thread call of flags_wait_all_for return correctly when ticker callback set all flags", test_wait_all_already_set_with_ticker), + Case("Validate if setting same flag twice cause any unwanted behaviour when ticker callbacks set", test_set_double_with_ticker), + Case("Validate if main thread flags_wait_all_for accumulate flags and return correctly when all flags set by ticker callback", test_wait_all_loop_with_ticker), +#if defined(MBED_CONF_RTOS_PRESENT) Case("Validate that call flags_clear(NO_SIGNALS) doesn't change thread flags and return actual flags", test_clear_no_signals), Case("Validate if any flags are set on just created thread", test_init_state), Case("Validate all flags set in one shot", test_set_all), @@ -387,7 +529,9 @@ Case cases[] = { Case("Validate that call of flags_wait_all_for return correctly when thread has all flags already set", test_wait_all_already_set), Case("Validate if flags_wait_all_for return correctly when all flags set", test_wait_all), Case("Validate if flags_wait_all_for accumulate flags and return correctly when all flags set", test_wait_all_loop), - Case("Validate if setting same flag twice cause any unwanted behaviour", test_set_double) + Case("Validate if setting same flag twice cause any unwanted behaviour", test_set_double), + +#endif }; utest::v1::Specification specification(test_setup, cases); @@ -398,4 +542,3 @@ int main() } #endif // !DEVICE_USTICKER -#endif // defined(MBED_RTOS_SINGLE_THREAD) || !defined(MBED_CONF_RTOS_PRESENT)