Merge pull request #5425 from fkjagodzinski/test-rtostimer-update

RtosTimer tests update
pull/5160/merge
Martin Kojtal 2017-11-09 16:31:39 +00:00 committed by GitHub
commit adfe004303
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 151 additions and 169 deletions

View File

@ -21,18 +21,55 @@
using namespace utest::v1; using namespace utest::v1;
#define TEST_DELAY_MS 50 #define DELAY_MS 50
#define TEST_DELAY2_MS 30 #define DELTA_MS 5
#define TEST_DELAY_MS_DELTA 1 #define RESTART_DELAY_MS 10
#define TEST_RESTART_DELAY_MS 10 #define DELAY2_MS 30
#if TEST_RESTART_DELAY_MS >= TEST_DELAY_MS #if RESTART_DELAY_MS >= DELAY_MS
#error invalid TEST_RESTART_DELAY_MS value #error invalid RESTART_DELAY_MS value
#endif #endif
void timer_callback(void const *arg) class Stopwatch: public Timer {
private:
Semaphore _sem;
public:
Stopwatch() :
Timer(), _sem(1)
{
}
~Stopwatch()
{
}
void start(void)
{
_sem.wait(0);
Timer::start();
}
void stop(void)
{
Timer::stop();
_sem.release();
}
int32_t wait_until_stopped(uint32_t millisec = osWaitForever)
{
core_util_critical_section_enter();
int running = _running;
core_util_critical_section_exit();
if (!running) {
return 1;
}
return _sem.wait(millisec);
}
};
void sem_callback(Semaphore *sem)
{ {
Semaphore *sem = (Semaphore *) arg;
sem->release(); sem->release();
} }
@ -44,14 +81,15 @@ void timer_callback(void const *arg)
* which aborts test program. * which aborts test program.
*/ */
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
void error(const char* format, ...) { void error(const char* format, ...)
{
(void) format; (void) format;
} }
#endif #endif
/** Test one-shot not restarted when elapsed /** Test one-shot not restarted when elapsed
* *
* Given a one-shot timer * Given a one-shot RtosTimer
* When the timer is started * When the timer is started
* and given time elapses * and given time elapses
* Then timer stops * Then timer stops
@ -60,32 +98,27 @@ void error(const char* format, ...) {
*/ */
void test_oneshot_not_restarted() void test_oneshot_not_restarted()
{ {
Semaphore sem(1); Stopwatch stopwatch;
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce); RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Timer t; stopwatch.start();
sem.wait(0); osStatus status = rtostimer.start(DELAY_MS);
stat = timer.start(TEST_DELAY_MS); TEST_ASSERT_EQUAL(osOK, status);
t.start();
TEST_ASSERT_EQUAL(osOK, stat);
int32_t slots = sem.wait(TEST_DELAY_MS + 1); int32_t slots = stopwatch.wait_until_stopped();
t.stop();
TEST_ASSERT_EQUAL(1, slots); TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t.read_us()); TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms());
stopwatch.start();
slots = sem.wait(TEST_DELAY_MS + 1); slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots); TEST_ASSERT_EQUAL(0, slots);
status = rtostimer.stop();
stat = timer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status);
TEST_ASSERT_EQUAL(osErrorResource, stat);
} }
/** Test periodic repeats continuously /** Test periodic repeats continuously
* *
* Given a periodic timer * Given a periodic RtosTimer
* When timer is started * When timer is started
* and given time elapses * and given time elapses
* Then timer repeats its operation * Then timer repeats its operation
@ -94,77 +127,37 @@ void test_oneshot_not_restarted()
*/ */
void test_periodic_repeats() void test_periodic_repeats()
{ {
Semaphore sem(1); Stopwatch stopwatch;
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerPeriodic); RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerPeriodic);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Timer t; stopwatch.start();
sem.wait(0); osStatus status = rtostimer.start(DELAY_MS);
stat = timer.start(TEST_DELAY_MS); TEST_ASSERT_EQUAL(osOK, status);
t.start();
TEST_ASSERT_EQUAL(osOK, stat);
int32_t slots = sem.wait(TEST_DELAY_MS + 1); int32_t slots = stopwatch.wait_until_stopped();
int t1 = t.read_us(); int t1 = stopwatch.read_ms();
stopwatch.reset();
stopwatch.start();
TEST_ASSERT_EQUAL(1, slots); TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t1); TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, t1);
slots = sem.wait(TEST_DELAY_MS + 1); slots = stopwatch.wait_until_stopped();
t.stop();
TEST_ASSERT_EQUAL(1, slots); TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t.read_us() - t1); TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms());
stopwatch.start();
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osOK, stat); TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY_MS + 1); slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots); TEST_ASSERT_EQUAL(0, slots);
status = rtostimer.stop();
stat = timer.stop(); TEST_ASSERT_EQUAL(osErrorResource, status);
TEST_ASSERT_EQUAL(osErrorResource, stat);
}
/** Test timer can be restarted
*
* Given a one-shot timer
* When the timer is started
* and @a start is called again before given time elapses
* and given time elapses
* Then timer stops
* and elapsed time is greater than original delay
*/
void test_restart()
{
Semaphore sem(1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Timer t;
sem.wait(0);
stat = timer.start(TEST_DELAY_MS);
t.start();
TEST_ASSERT_EQUAL(osOK, stat);
int32_t slots = sem.wait(TEST_RESTART_DELAY_MS);
TEST_ASSERT_EQUAL(0, slots);
stat = timer.start(TEST_DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat);
slots = sem.wait(TEST_DELAY_MS + 1);
t.stop();
TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, (TEST_DELAY_MS + TEST_RESTART_DELAY_MS) * 1000, t.read_us());
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
} }
/** Test timer can be started again /** Test timer can be started again
* *
* Given a one-shot timer * Given a one-shot Rtosimer
* When the timer is started * When the timer is started
* and given time elapses * and given time elapses
* Then timer stops * Then timer stops
@ -174,34 +167,31 @@ void test_restart()
*/ */
void test_start_again() void test_start_again()
{ {
Semaphore sem(1); Semaphore sem(0, 1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce); RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
sem.wait(0); osStatus status = rtostimer.start(DELAY_MS);
stat = timer.start(TEST_DELAY_MS); TEST_ASSERT_EQUAL(osOK, status);
TEST_ASSERT_EQUAL(osOK, stat);
int32_t slots = sem.wait(TEST_DELAY_MS + 1); int32_t slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(1, slots); TEST_ASSERT_EQUAL(1, slots);
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat); TEST_ASSERT_EQUAL(osErrorResource, status);
stat = timer.start(TEST_DELAY_MS); status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat); TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY_MS + 1); slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(1, slots); TEST_ASSERT_EQUAL(1, slots);
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat); TEST_ASSERT_EQUAL(osErrorResource, status);
} }
/** Test timer restart updates delay /** Test timer restart updates delay
* *
* Given a one-shot timer * Given a one-shot RtosTimer
* When the timer is started * When the timer is started
* and @a start is called again with a different delay before given time elapses * and @a start is called again with a different delay before given time elapses
* and updated delay elapses * and updated delay elapses
@ -210,134 +200,127 @@ void test_start_again()
*/ */
void test_restart_updates_delay() void test_restart_updates_delay()
{ {
Semaphore sem(1); Stopwatch stopwatch;
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce); RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
sem.wait(0); stopwatch.start();
stat = timer.start(TEST_DELAY_MS); osStatus status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat); TEST_ASSERT_EQUAL(osOK, status);
int32_t slots = sem.wait(TEST_RESTART_DELAY_MS); int32_t slots = stopwatch.wait_until_stopped(RESTART_DELAY_MS);
TEST_ASSERT_EQUAL(0, slots); TEST_ASSERT_EQUAL(0, slots);
Timer t; stopwatch.reset();
stat = timer.start(TEST_DELAY2_MS); stopwatch.start();
t.start(); status = rtostimer.start(DELAY2_MS);
TEST_ASSERT_EQUAL(osOK, stat); TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY2_MS + 1); slots = stopwatch.wait_until_stopped();
t.stop();
TEST_ASSERT_EQUAL(1, slots); TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY2_MS * 1000, t.read_us()); TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY2_MS, stopwatch.read_ms());
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat); TEST_ASSERT_EQUAL(osErrorResource, status);
} }
/** Test timer is created in stopped state /** Test timer is created in stopped state
* *
* Given a one-shot timer * Given a one-shot RtosTimer
* When the timer has not been started * When the timer has not been started
* Then the timer is stopped * Then the timer is stopped
*/ */
void test_created_stopped() void test_created_stopped()
{ {
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce); RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
osStatus stat = timer.stop(); osStatus status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat); TEST_ASSERT_EQUAL(osErrorResource, status);
} }
/** Test one-shot can be stopped /** Test one-shot can be stopped
* *
* Given a one-shot timer * Given a one-shot RtosTimer
* When the timer is started * When the timer is started
* and timer is stopped while still running * and timer is stopped while still running
* Then timer stops operation * Then timer stops operation
*/ */
void test_stop() void test_stop()
{ {
Semaphore sem(1); Semaphore sem(0, 1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce); RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
sem.wait(0); osStatus status = rtostimer.start(DELAY_MS);
stat = timer.start(TEST_DELAY_MS); TEST_ASSERT_EQUAL(osOK, status);
TEST_ASSERT_EQUAL(osOK, stat);
int32_t slots = sem.wait(TEST_RESTART_DELAY_MS); int32_t slots = sem.wait(RESTART_DELAY_MS);
TEST_ASSERT_EQUAL(0, slots); TEST_ASSERT_EQUAL(0, slots);
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osOK, stat); TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY_MS + 1); slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots); TEST_ASSERT_EQUAL(0, slots);
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat); TEST_ASSERT_EQUAL(osErrorResource, status);
} }
/** Test timer started with infinite delay /** Test timer started with infinite delay
* *
* Given a one-shot timer * Given a one-shot RtosTimer
* When the timer is started with @a osWaitForever delay * When the timer is started with @a osWaitForever delay
* Then @a start return status is @a osOK * Then @a start return status is @a osOK
*/ */
void test_wait_forever() void test_wait_forever()
{ {
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce); RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
osStatus stat = timer.start(osWaitForever); osStatus status = rtostimer.start(osWaitForever);
TEST_ASSERT_EQUAL(osOK, stat); TEST_ASSERT_EQUAL(osOK, status);
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osOK, stat); TEST_ASSERT_EQUAL(osOK, status);
} }
/** Test timer started with zero delay /** Test timer started with zero delay
* *
* Given a one-shot timer * Given a one-shot RtosTimer
* When the timer is started with 0 delay * When the timer is started with 0 delay
* Then @a start return status is @a osErrorParameter * Then @a start return status is @a osErrorParameter
*/ */
void test_no_wait() void test_no_wait()
{ {
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce); RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
osStatus stat = timer.start(0); osStatus status = rtostimer.start(0);
TEST_ASSERT_EQUAL(osErrorParameter, stat); TEST_ASSERT_EQUAL(osErrorParameter, status);
stat = timer.stop(); status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat); TEST_ASSERT_EQUAL(osErrorResource, status);
} }
void timer_isr_call(void const *arg) void rtostimer_isr_call(RtosTimer *rtostimer)
{ {
RtosTimer *timer = (RtosTimer *) arg; osStatus status = rtostimer->start(DELAY_MS);
osStatus stat = timer->start(TEST_DELAY_MS); TEST_ASSERT_EQUAL(osErrorISR, status);
TEST_ASSERT_EQUAL(osErrorISR, stat);
stat = timer->stop(); status = rtostimer->stop();
TEST_ASSERT_EQUAL(osErrorISR, stat); TEST_ASSERT_EQUAL(osErrorISR, status);
} }
/** Test timer method calls from an ISR fail /** Test timer method calls from an ISR fail
* *
* Given a one-shot timer * Given a one-shot RtosTimer
* When a timer method is called from an ISR * When a timer method is called from an ISR
* Then method return status is @a osErrorISR * Then method return status is @a osErrorISR
*/ */
void test_isr_calls_fail() void test_isr_calls_fail()
{ {
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce); RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
Ticker ticker; Ticker ticker;
ticker.attach(mbed::callback(timer_isr_call, (void const *) &timer), (float) TEST_DELAY_MS / 1000.0); ticker.attach(mbed::callback(rtostimer_isr_call, &rtostimer), (float) DELAY_MS / 1000.0);
wait_ms(TEST_DELAY_MS + 1); wait_ms(DELAY_MS + DELTA_MS);
} }
utest::v1::status_t test_setup(const size_t number_of_cases) utest::v1::status_t test_setup(const size_t number_of_cases)
@ -347,16 +330,15 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
} }
Case cases[] = { Case cases[] = {
Case("Test one-shot not restarted when elapsed", test_oneshot_not_restarted), Case("One-shot not restarted when elapsed", test_oneshot_not_restarted),
Case("Test periodic repeats continuously", test_periodic_repeats), Case("Periodic repeats continuously", test_periodic_repeats),
Case("Test timer can be restarted while running", test_restart), Case("Stopped timer can be started again", test_start_again),
Case("Test stopped timer can be started again", test_start_again), Case("Restart changes timeout", test_restart_updates_delay),
Case("Test restart changes timeout", test_restart_updates_delay), Case("Timer can be stopped", test_stop),
Case("Test can be stopped", test_stop), Case("Timer is created in stopped state", test_created_stopped),
Case("Test timer is created in stopped state", test_created_stopped), Case("Timer started with infinite delay", test_wait_forever),
Case("Test timer started with infinite delay", test_wait_forever), Case("Timer started with zero delay", test_no_wait),
Case("Test timer started with zero delay", test_no_wait), Case("Calls from ISR fail", test_isr_calls_fail)
Case("Test calls from ISR fail", test_isr_calls_fail)
}; };
Specification specification(test_setup, cases); Specification specification(test_setup, cases);