RTOS: Mutex: Rework tests

Add descriptions, fix small issues and timings.
pull/4729/head
Bartek Szatkowski 2017-07-10 09:49:36 +01:00
parent aae62bd990
commit 01c0cfd4f8
1 changed files with 115 additions and 44 deletions

View File

@ -12,13 +12,9 @@ using namespace utest::v1;
#define TEST_STACK_SIZE 512
#define TEST_ONE_SEC_MS (1000)
#define TEST_HALF_SEC_MS (500)
#define TEST_HALF_SEC_US (500000)
#define TEST_ONE_MS_US (1000)
#define THREAD_DELAY 50
#define SIGNALS_TO_EMIT 100
#define TEST_LONG_DELAY 20
#define TEST_DELAY 10
#define SIGNALS_TO_EMIT 100
Mutex stdio_mutex;
@ -26,11 +22,14 @@ volatile int change_counter = 0;
volatile bool changing_counter = false;
volatile bool mutex_defect = false;
bool manipulate_protected_zone(const int thread_delay) {
bool manipulate_protected_zone(const int thread_delay)
{
bool result = true;
osStatus stat = stdio_mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
core_util_critical_section_enter();
if (changing_counter == true) {
result = false;
mutex_defect = true;
@ -38,25 +37,37 @@ bool manipulate_protected_zone(const int thread_delay) {
changing_counter = true;
change_counter++;
core_util_critical_section_exit();
Thread::wait(thread_delay);
core_util_critical_section_enter();
changing_counter = false;
core_util_critical_section_exit();
stat = stdio_mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
return result;
}
void test_thread(int const *thread_delay) {
void test_thread(int const *thread_delay)
{
while (true) {
manipulate_protected_zone(*thread_delay);
}
}
/** Test multiple thread
Given 3 threads started with different delays and a section protected with a mutex
when each thread runs it tries to lock the mutex
then no more than one thread should be able to access protected region
*/
void test_multiple_threads(void)
{
const int t1_delay = THREAD_DELAY * 1;
const int t2_delay = THREAD_DELAY * 2;
const int t3_delay = THREAD_DELAY * 3;
const int t1_delay = TEST_DELAY * 1;
const int t2_delay = TEST_DELAY * 2;
const int t3_delay = TEST_DELAY * 3;
Thread t2(osPriorityNormal, TEST_STACK_SIZE);
Thread t3(osPriorityNormal, TEST_STACK_SIZE);
@ -69,34 +80,51 @@ void test_multiple_threads(void)
Thread::wait(t1_delay);
manipulate_protected_zone(t1_delay);
core_util_critical_section_enter();
if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) {
core_util_critical_section_exit();
t2.terminate();
t3.terminate();
break;
}
core_util_critical_section_exit();
}
TEST_ASSERT_EQUAL(mutex_defect, false);
TEST_ASSERT_EQUAL(false, mutex_defect);
}
void test_dual_thread_nolock_lock_thread(Mutex *mutex)
{
bool stat_b = mutex->trylock();
TEST_ASSERT_EQUAL(stat_b, true);
osStatus stat = mutex->lock(osWaitForever);
TEST_ASSERT_EQUAL(osOK, stat);
osStatus stat = mutex->unlock();
TEST_ASSERT_EQUAL(stat, osOK);
stat = mutex->unlock();
TEST_ASSERT_EQUAL(osOK, stat);
}
void test_dual_thread_nolock_trylock_thread(Mutex *mutex)
{
bool stat_b = mutex->trylock();
TEST_ASSERT_EQUAL(stat_b, true);
TEST_ASSERT_EQUAL(true, stat_b);
osStatus stat = mutex->unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test dual thread no-lock
Test dual thread second thread lock
Given two threads A & B and a mutex
When thread A creates a mutex and starts thread B
and thread B calls @a lock and @a unlock
Then returned statuses are osOK
Test dual thread second thread trylock
Given two threads A & B and a mutex
When thread A creates a mutex and starts thread B
and thread B calls @a trylock and @a unlock
Then returned statuses are true and osOK
*/
template <void (*F)(Mutex *)>
void test_dual_thread_nolock(void)
{
@ -105,15 +133,24 @@ void test_dual_thread_nolock(void)
thread.start(callback(F, &mutex));
wait_us(TEST_HALF_SEC_MS);
wait_ms(TEST_DELAY);
}
void test_dual_thread_lock_unlock_thread(Mutex *mutex)
{
osStatus stat = mutex->lock(osWaitForever);
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test dual thread lock unlock
Given two threads and a lock
When thread A locks the lock and starts thread B
and thread B calls @a lock on the mutex
Then thread B waits for thread A to unlock the lock
When thread A calls @a unlock on the mutex
Then thread B acquires the lock
*/
void test_dual_thread_lock_unlock(void)
{
Mutex mutex;
@ -121,31 +158,45 @@ void test_dual_thread_lock_unlock(void)
Thread thread(osPriorityNormal, TEST_STACK_SIZE);
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
thread.start(callback(test_dual_thread_lock_unlock_thread, &mutex));
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
wait_us(TEST_HALF_SEC_MS);
wait_ms(TEST_DELAY);
}
void test_dual_thread_lock_trylock_thread(Mutex *mutex)
{
bool stat = mutex->trylock();
TEST_ASSERT_EQUAL(stat, false);
TEST_ASSERT_EQUAL(false, stat);
}
void test_dual_thread_lock_lock_thread(Mutex *mutex)
{
uint32_t start = us_ticker_read();
osStatus stat = mutex->lock(TEST_HALF_SEC_MS);
TEST_ASSERT_EQUAL(stat, osErrorTimeout);
TEST_ASSERT_UINT32_WITHIN(TEST_ONE_MS_US, TEST_HALF_SEC_US, us_ticker_read() - start);
osStatus stat = mutex->lock(TEST_DELAY);
TEST_ASSERT_EQUAL(osErrorTimeout, stat);
TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY*1000, us_ticker_read() - start);
}
/** Test dual thread lock
Test dual thread lock locked
Given a mutex and two threads A & B
When thread A calls @a lock and starts thread B
and thread B calls @a lock with 500ms timeout
Then thread B waits 500ms and timeouts
Test dual thread trylock locked
Given a mutex and two threads A & B
When thread A calls @a lock and starts thread B
Then thread B calls @a trylock
and thread B fails to acquire the lock
*/
template <void (*F)(Mutex *)>
void test_dual_thread_lock(void)
{
@ -154,59 +205,78 @@ void test_dual_thread_lock(void)
Thread thread(osPriorityNormal, TEST_STACK_SIZE);
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
thread.start(callback(F, &mutex));
wait_us(TEST_ONE_SEC_MS);
wait_ms(TEST_LONG_DELAY);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test single thread lock recursive
Given a mutex and a single running thread
When thread calls @a lock twice and @a unlock twice on the mutex
Then the returned statuses are osOK
*/
void test_single_thread_lock_recursive(void)
{
Mutex mutex;
osStatus stat;
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test single thread trylock
Given a mutex and a single running thread
When thread calls @a trylock and @a unlock on the mutex
Then the returned statuses are osOK
*/
void test_single_thread_trylock(void)
{
Mutex mutex;
bool stat_b = mutex.trylock();
TEST_ASSERT_EQUAL(stat_b, true);
TEST_ASSERT_EQUAL(true, stat_b);
osStatus stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test single thread lock
Given a mutex and a single running thread
When thread calls @a lock and @a unlock on the mutex
Then the returned statuses are osOK
*/
void test_single_thread_lock(void)
{
Mutex mutex;
osStatus stat;
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(15, "default_auto");
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
@ -224,6 +294,7 @@ Case cases[] = {
Specification specification(test_setup, cases);
int main() {
int main()
{
return !Harness::run(specification);
}