Skip to content

Bare metal: Enable signals greentea test #12855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 24, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 183 additions & 40 deletions TESTS/mbedmicro-rtos-mbed/signals/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 <int32_t signals, uint32_t timeout, uint32_t test_val>
void run_signal_wait(void)
{
uint32_t ret = ThisThread::flags_wait_all_for(signals, timeout);
TEST_ASSERT_EQUAL(test_val, ret);
}

template <int32_t signals, int32_t test_val>
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<NO_SIGNALS, NO_SIGNALS>), 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 <int32_t signals, uint32_t timeout, uint32_t status>
void test_wait_timeout_with_ticker(void)
{
Ticker t;
t.attach_us(callback(run_signal_wait<signals, timeout, status>), 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)
{}
Expand All @@ -47,13 +193,6 @@ struct Sync {
Semaphore &sem_child;
};

template <int32_t signals, uint32_t timeout, uint32_t test_val>
void run_signal_wait(void)
{
uint32_t ret = ThisThread::flags_wait_all_for(signals, timeout);
TEST_ASSERT_EQUAL(test_val, ret);
}

template <int32_t signals, uint32_t timeout, uint32_t test_val>
void run_release_signal_wait(Semaphore *sem)
{
Expand All @@ -71,13 +210,6 @@ void run_release_wait_signal_wait(Sync *sync)
TEST_ASSERT_EQUAL(test_val, ret);
}

template <int32_t signals, int32_t test_val>
void run_clear(void)
{
int32_t ret = ThisThread::flags_clear(signals);
TEST_ASSERT_EQUAL(test_val, ret);
}

template <int32_t signals, int32_t test_val>
void run_wait_clear(Sync *sync)
{
Expand All @@ -87,20 +219,6 @@ void run_wait_clear(Sync *sync)
TEST_ASSERT_EQUAL(test_val, ret);
}

template <int32_t signals1, int32_t signals2, int32_t test_val1, int32_t test_val2>
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;
Expand All @@ -114,6 +232,19 @@ void run_loop_wait_clear(Sync *sync)
}
}

template <int32_t signals1, int32_t signals2, int32_t test_val1, int32_t test_val2>
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

Expand Down Expand Up @@ -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<ALL_SIGNALS, 0, 0>),
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<ALL_SIGNALS, 1, 0>),
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),
Expand 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);
Expand All @@ -398,4 +542,3 @@ int main()
}

#endif // !DEVICE_USTICKER
#endif // defined(MBED_RTOS_SINGLE_THREAD) || !defined(MBED_CONF_RTOS_PRESENT)