More Chrono test fixes

* Timer test - handle removal of Timer(ticker_data_t *)
* Timer test - use Chrono, don't test deprecated methods
* Kernel tick count test - TEST_ASSERT_WITHIN -> TEST_ASSERT_INT_WITHIN
* Mutex test - fix up Chrono changes
* SysTimer test - adapt to SysTimer Chrono changes
* Thread test - use Chrono
* SysTimer - devirtualize destructor
pull/12425/head
Kevin Bracey 2020-04-02 16:48:38 +03:00
parent e5e45d83e7
commit 8e3e19837a
7 changed files with 197 additions and 251 deletions

View File

@ -26,12 +26,21 @@
#else
using namespace utest::v1;
using namespace std::chrono;
extern uint32_t SystemCoreClock;
#define US_PER_SEC 1000000
#define US_PER_MSEC 1000
#define MSEC_PER_SEC 1000
#define TEST_ASSERT_EQUAL_DURATION(expected, actual) \
do { \
using ct = std::common_type_t<decltype(expected), decltype(actual)>; \
TEST_ASSERT_EQUAL(ct(expected).count(), ct(actual).count()); \
} while (0)
#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \
do { \
using ct = std::common_type_t<decltype(delta), decltype(expected), decltype(actual)>; \
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
} while (0)
/*
* Define tolerance as follows:
@ -50,14 +59,16 @@ extern uint32_t SystemCoreClock;
#define TOLERANCE 2
#endif
#define DELTA_US(delay_ms) (500 + (delay_ms) * US_PER_MSEC * TOLERANCE / 100)
#define DELTA_MS(delay_ms) (1 + (delay_ms) * TOLERANCE / 100)
#define DELTA_S(delay_ms) (0.000500f + ((float)(delay_ms)) * ((float)(TOLERANCE) / 100.f) / MSEC_PER_SEC)
template <class Duration>
static inline microseconds delta(Duration delay)
{
return 500us + duration_cast<microseconds>(delay) * TOLERANCE / 100;
}
#define TICKER_FREQ_1MHZ 1000000
#define TICKER_BITS 32
static Timer *p_timer = NULL;
static TimerBase *p_timer = NULL;
/* Global variable used to simulate passage of time
* in case when timer which uses user ticker is tested.
@ -66,16 +77,11 @@ static uint32_t curr_ticker_ticks_val;
/* Replacement for generic wait functions to avoid invoking OS scheduling stuff. */
void busy_wait_us(int us)
void busy_wait(duration<int, std::micro> us)
{
const ticker_data_t *const ticker = get_us_ticker_data();
uint32_t start = ticker_read(ticker);
while ((ticker_read(ticker) - start) < (uint32_t)us);
}
void busy_wait_ms(int ms)
{
busy_wait_us(ms * US_PER_MSEC);
while ((ticker_read(ticker) - start) < (uint32_t)us.count());
}
/* User ticker interface function. */
@ -157,13 +163,18 @@ const ticker_data_t *get_user_ticker_data(void)
return &us_data;
}
class UserTimer : public TimerBase {
public:
UserTimer() : TimerBase(get_user_ticker_data()) { }
};
/* Initialisation of the Timer object which uses
* ticker data provided by the user.
*
* */
utest::v1::status_t timer_user_ticker_setup_handler(const Case *const source, const size_t index_of_case)
{
p_timer = new Timer(get_user_ticker_data());
p_timer = new UserTimer();
/* Check if Timer object has been created. */
TEST_ASSERT_NOT_NULL(p_timer);
@ -185,12 +196,24 @@ utest::v1::status_t timer_os_ticker_setup_handler(const Case *const source, cons
return greentea_case_setup_handler(source, index_of_case);
}
/* Test finalisation.
*
* */
utest::v1::status_t cleanup_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
/* Test finalisation of the Timer object which uses
* ticker data provided by the user.
*/
utest::v1::status_t timer_user_ticker_cleanup_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
{
delete p_timer;
delete static_cast<UserTimer *>(p_timer);
p_timer = NULL;
return greentea_case_teardown_handler(source, passed, failed, reason);
}
/* Test finalisation of the Timer object which uses
* default os ticker data.
*/
utest::v1::status_t timer_os_ticker_cleanup_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
{
delete static_cast<Timer *>(p_timer);
p_timer = NULL;
@ -209,20 +232,14 @@ utest::v1::status_t cleanup_handler(const Case *const source, const size_t passe
void test_timer_creation_os_ticker()
{
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time());
/* Wait 10 ms.
* After that operation timer read routines should still return 0. */
busy_wait_ms(10);
busy_wait(10ms);
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time());
}
/* This test verifies if timer is stopped after
@ -243,20 +260,14 @@ void test_timer_creation_user_ticker()
curr_ticker_ticks_val = 10000;
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time());
/* Simulate that 10 ms has elapsed.
* After that operation timer read routines should still return 0. */
curr_ticker_ticks_val += 10000;
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(0s, p_timer->elapsed_time());
}
/* This test verifies verifies if read(), read_us(), read_ms(),
@ -287,10 +298,7 @@ void test_timer_time_accumulation_user_ticker()
p_timer->stop();
/* Check results - 1 us has elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.000001f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(1, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(1, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(1us, p_timer->elapsed_time());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_ticks_val = 101;
@ -305,10 +313,7 @@ void test_timer_time_accumulation_user_ticker()
p_timer->stop();
/* Check results - 125 us have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.000125f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(125, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(125, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(125us, p_timer->elapsed_time());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_ticks_val = 325;
@ -323,10 +328,7 @@ void test_timer_time_accumulation_user_ticker()
p_timer->stop();
/* Check results - 1 ms has elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.001000f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(1, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(1000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(1000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(1ms, p_timer->elapsed_time());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_ticks_val = 1300;
@ -341,10 +343,7 @@ void test_timer_time_accumulation_user_ticker()
p_timer->stop();
/* Check results - 125 ms have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.125000f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(125, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(125000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(125000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(125ms, p_timer->elapsed_time());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_ticks_val = 125400;
@ -359,10 +358,7 @@ void test_timer_time_accumulation_user_ticker()
p_timer->stop();
/* Check results - 1 s has elapsed. */
TEST_ASSERT_EQUAL_FLOAT(1.000000f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(1000, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(1000000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(1000000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(1s, p_timer->elapsed_time());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_ticks_val = 1000500;
@ -377,10 +373,7 @@ void test_timer_time_accumulation_user_ticker()
p_timer->stop();
/* Check results - 125 s have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(125.000000f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(125000, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(125000000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(125000000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(125s, p_timer->elapsed_time());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_ticks_val = 125000600;
@ -401,10 +394,7 @@ void test_timer_time_accumulation_user_ticker()
p_timer->stop();
/* Check results - 2147483647 (MAX_INT_32) us have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(2147.483647f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(2147483, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(2147483647, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(2147483647, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_DURATION(2147483647us, p_timer->elapsed_time());
}
/* This test verifies if read(), read_us(), read_ms(),
@ -426,21 +416,18 @@ void test_timer_time_accumulation_os_ticker()
p_timer->start();
/* Wait 10 ms. */
busy_wait_ms(10);
busy_wait(10ms);
/* Stop the timer. */
p_timer->stop();
/* Check results - totally 10 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(10ms), 10ms, p_timer->elapsed_time());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
* timer counted time. */
busy_wait_ms(50);
busy_wait(50ms);
/* ------ */
@ -448,16 +435,13 @@ void test_timer_time_accumulation_os_ticker()
p_timer->start();
/* Wait 20 ms. */
busy_wait_ms(20);
busy_wait(20ms);
/* Stop the timer. */
p_timer->stop();
/* Check results - totally 30 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(30ms), 30ms, p_timer->elapsed_time());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
@ -469,21 +453,18 @@ void test_timer_time_accumulation_os_ticker()
p_timer->start();
/* Wait 30 ms. */
busy_wait_ms(30);
busy_wait(30ms);
/* Stop the timer. */
p_timer->stop();
/* Check results - totally 60 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(60), 0.060f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(60), 60, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(60), 60000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(60), 60000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(60ms), 60ms, p_timer->elapsed_time());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
* timer time. */
busy_wait_ms(50);
busy_wait(50ms);
/* ------ */
@ -491,16 +472,13 @@ void test_timer_time_accumulation_os_ticker()
p_timer->start();
/* Wait 1 sec. */
busy_wait_ms(1000);
busy_wait(1s);
/* Stop the timer. */
p_timer->stop();
/* Check results - totally 1060 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1060), 1.060f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1060), 1060, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1060), 1060000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1060), 1060000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(1060ms), 1060ms, p_timer->elapsed_time());
}
/* This test verifies if reset() function resets the timer
@ -520,16 +498,13 @@ void test_timer_reset_os_ticker()
p_timer->start();
/* Wait 10 ms. */
busy_wait_ms(10);
busy_wait(10ms);
/* Stop the timer. */
p_timer->stop();
/* Check results - totally 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(10ms), 10ms, p_timer->elapsed_time());
/* Reset the timer - previous measured time should be lost now. */
p_timer->reset();
@ -538,16 +513,13 @@ void test_timer_reset_os_ticker()
p_timer->start();
/* Wait 20 ms. */
busy_wait_ms(20);
busy_wait(20ms);
/* Stop the timer. */
p_timer->stop();
/* Check results - 20 ms elapsed since the reset. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(20), 0.020f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(20), 20, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(20), 20000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(20), 20000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(20ms), 20ms, p_timer->elapsed_time());
}
/* This test verifies if reset() function resets the timer
@ -577,10 +549,7 @@ void test_timer_reset_user_ticker()
p_timer->stop();
/* Check results - totally 10 ms elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.010f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(10, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(10000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(10000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(10ms), 10ms, p_timer->elapsed_time());
/* Reset the timer - previous measured time should be lost now. */
p_timer->reset();
@ -595,10 +564,7 @@ void test_timer_reset_user_ticker()
p_timer->stop();
/* Check results - 20 ms elapsed since the reset. */
TEST_ASSERT_EQUAL_FLOAT(0.020f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(20, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(20000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(20000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(20ms), 20ms, p_timer->elapsed_time());
}
/* This test verifies if calling start() for already
@ -616,22 +582,19 @@ void test_timer_start_started_timer_os_ticker()
p_timer->start();
/* Wait 10 ms. */
busy_wait_ms(10);
busy_wait(10ms);
/* Now start timer again. */
p_timer->start();
/* Wait 20 ms. */
busy_wait_ms(20);
busy_wait(20ms);
/* Stop the timer. */
p_timer->stop();
/* Check results - 30 ms have elapsed since the first start. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(30ms), 30ms, p_timer->elapsed_time());
}
/* This test verifies if calling start() for already
@ -665,62 +628,7 @@ void test_timer_start_started_timer_user_ticker()
p_timer->stop();
/* Check results - 30 ms have elapsed since the first start. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us());
}
/* This test verifies Timer float operator.
*
* Note this function assumes that Timer uses os ticker.
*
* Given timer is created and a time period time is counted.
* When timer object is casted on float type.
* Then counted type in seconds is returned by means of
* read() function.
*/
void test_timer_float_operator_os_ticker()
{
/* Start the timer. */
p_timer->start();
/* Wait 10 ms. */
busy_wait_ms(10);
/* Stop the timer. */
p_timer->stop();
/* Check result - 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, (float)(*p_timer));
}
/* This test verifies Timer float operator.
*
* Note this function assumes that Timer uses user ticker.
*
* Given timer is created and a time period time is counted.
* When timer object is casted on float type.
* Then counted type in seconds is returned by means of
* read() function.
*/
void test_timer_float_operator_user_ticker()
{
/* For timer which is using user ticker set current
* time (irrelevant in case of os ticker). */
curr_ticker_ticks_val = 0;
/* Start the timer. */
p_timer->start();
/* Simulate that 10 ms have elapsed. */
curr_ticker_ticks_val = 10000;
/* Stop the timer. */
p_timer->stop();
/* Check result - 10 ms elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.010f, (float)(*p_timer));
TEST_ASSERT_DURATION_WITHIN(delta(30ms), 30ms, p_timer->elapsed_time());
}
/* This test verifies if time counted by the timer is
@ -737,20 +645,19 @@ void test_timer_float_operator_user_ticker()
template<int wait_val_us>
void test_timer_time_measurement()
{
microseconds wait_val(wait_val_us);
/* Start the timer. */
p_timer->start();
/* Wait <wait_val_us> us. */
busy_wait_us(wait_val_us);
busy_wait(wait_val);
/* Stop the timer. */
p_timer->stop();
/* Check results. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(wait_val_us / US_PER_MSEC), (float)wait_val_us / US_PER_SEC, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(wait_val_us / US_PER_MSEC), wait_val_us / US_PER_MSEC, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(wait_val_us / US_PER_MSEC), wait_val_us, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(wait_val_us / US_PER_MSEC), wait_val_us, p_timer->read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(delta(wait_val), wait_val, p_timer->elapsed_time());
}
utest::v1::status_t test_setup(const size_t number_of_cases)
@ -760,25 +667,22 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
}
Case cases[] = {
Case("Test: Timer (based on os ticker) is stopped after creation.", timer_os_ticker_setup_handler, test_timer_creation_os_ticker, cleanup_handler),
Case("Test: Timer (based on user ticker) is stopped after creation.", timer_user_ticker_setup_handler, test_timer_creation_user_ticker, cleanup_handler),
Case("Test: Timer (based on os ticker) is stopped after creation.", timer_os_ticker_setup_handler, test_timer_creation_os_ticker, timer_os_ticker_cleanup_handler),
Case("Test: Timer (based on user ticker) is stopped after creation.", timer_user_ticker_setup_handler, test_timer_creation_user_ticker, timer_user_ticker_cleanup_handler),
Case("Test: Timer (based on os ticker) - measured time accumulation.", timer_os_ticker_setup_handler, test_timer_time_accumulation_os_ticker, cleanup_handler),
Case("Test: Timer (based on user ticker) measured time accumulation.", timer_user_ticker_setup_handler, test_timer_time_accumulation_user_ticker, cleanup_handler),
Case("Test: Timer (based on os ticker) - measured time accumulation.", timer_os_ticker_setup_handler, test_timer_time_accumulation_os_ticker, timer_os_ticker_cleanup_handler),
Case("Test: Timer (based on user ticker) measured time accumulation.", timer_user_ticker_setup_handler, test_timer_time_accumulation_user_ticker, timer_user_ticker_cleanup_handler),
Case("Test: Timer (based on os ticker) - reset.", timer_os_ticker_setup_handler, test_timer_reset_os_ticker, cleanup_handler),
Case("Test: Timer (based on user ticker) - reset.", timer_user_ticker_setup_handler, test_timer_reset_user_ticker, cleanup_handler),
Case("Test: Timer (based on os ticker) - reset.", timer_os_ticker_setup_handler, test_timer_reset_os_ticker, timer_os_ticker_cleanup_handler),
Case("Test: Timer (based on user ticker) - reset.", timer_user_ticker_setup_handler, test_timer_reset_user_ticker, timer_user_ticker_cleanup_handler),
Case("Test: Timer (based on os ticker) - start started timer.", timer_os_ticker_setup_handler, test_timer_start_started_timer_os_ticker, cleanup_handler),
Case("Test: Timer (based on user ticker) - start started timer.", timer_user_ticker_setup_handler, test_timer_start_started_timer_user_ticker, cleanup_handler),
Case("Test: Timer (based on os ticker) - start started timer.", timer_os_ticker_setup_handler, test_timer_start_started_timer_os_ticker, timer_os_ticker_cleanup_handler),
Case("Test: Timer (based on user ticker) - start started timer.", timer_user_ticker_setup_handler, test_timer_start_started_timer_user_ticker, timer_user_ticker_cleanup_handler),
Case("Test: Timer (based on os ticker) - float operator.", timer_os_ticker_setup_handler, test_timer_float_operator_os_ticker, cleanup_handler),
Case("Test: Timer (based on user ticker) - float operator.", timer_user_ticker_setup_handler, test_timer_float_operator_user_ticker, cleanup_handler),
Case("Test: Timer - time measurement 1 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000>, cleanup_handler),
Case("Test: Timer - time measurement 10 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<10000>, cleanup_handler),
Case("Test: Timer - time measurement 100 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<100000>, cleanup_handler),
Case("Test: Timer - time measurement 1 s.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000000>, cleanup_handler),
Case("Test: Timer - time measurement 1 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000>, timer_os_ticker_cleanup_handler),
Case("Test: Timer - time measurement 10 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<10000>, timer_os_ticker_cleanup_handler),
Case("Test: Timer - time measurement 100 ms.", timer_os_ticker_setup_handler, test_timer_time_measurement<100000>, timer_os_ticker_cleanup_handler),
Case("Test: Timer - time measurement 1 s.", timer_os_ticker_setup_handler, test_timer_time_measurement<1000000>, timer_os_ticker_cleanup_handler),
};
Specification specification(test_setup, cases);

View File

@ -48,7 +48,7 @@ using utest::v1::Case;
#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \
do { \
using ct = std::common_type_t<decltype(delta), decltype(expected), decltype(actual)>; \
TEST_ASSERT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
} while (0)
/** Test if declared kernel ticker frequency is 1kHz

View File

@ -27,6 +27,14 @@
#include "unity.h"
#include "utest.h"
#include "rtos.h"
#include <type_traits>
#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \
do { \
using ct = std::common_type_t<decltype(delta), decltype(expected), decltype(actual)>; \
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
} while (0)
using namespace utest::v1;
using namespace std::chrono;
@ -47,7 +55,7 @@ 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 Kernel::Clock::duration thread_delay)
{
bool result = true;
osStatus stat;
@ -75,7 +83,7 @@ bool manipulate_protected_zone(const int thread_delay)
return result;
}
void test_thread(int const *thread_delay)
void test_thread(Kernel::Clock::duration const *thread_delay)
{
while (true) {
manipulate_protected_zone(*thread_delay);
@ -201,7 +209,7 @@ void test_dual_thread_lock_lock_thread(Mutex *mutex)
bool stat = mutex->trylock_for(TEST_DELAY);
TEST_ASSERT_EQUAL(false, stat);
TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY * 1000, timer.read_us());
TEST_ASSERT_DURATION_WITHIN(5ms, TEST_DELAY, timer.elapsed_time());
}
/** Test dual thread lock

View File

@ -23,42 +23,63 @@
#include "platform/source/SysTimer.h"
using namespace std::chrono;
#define TEST_TICKS 42
#define TEST_TICK_US (TEST_TICKS * 1000)
#define DELAY_DELTA_US 2500ULL
#define TEST_TICK_PERIOD std::ratio<TEST_TICKS, 1000>::type
#define TEST_TICK_DURATION duration<long long, TEST_TICK_PERIOD>
#define DELAY TEST_TICK_DURATION(1)
#define DELAY_DELTA 2500us
#define TEST_ASSERT_EQUAL_DURATION(expected, actual) \
do { \
using ct = std::common_type_t<decltype(expected), decltype(actual)>; \
TEST_ASSERT_EQUAL(ct(expected).count(), ct(actual).count()); \
} while (0)
#define TEST_ASSERT_EQUAL_TIME_POINT(expected, actual) \
do { \
using ct = std::common_type_t<decltype(expected), decltype(actual)>; \
TEST_ASSERT_EQUAL(ct(expected).time_since_epoch().count(), ct(actual).time_since_epoch().count()); \
} while (0)
#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \
do { \
using ct = std::common_type_t<decltype(delta), decltype(expected), decltype(actual)>; \
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
} while (0)
/* Use a specific delta value for deep sleep, as entry/exit adds up extra latency.
* Use deep sleep latency if defined and add 1ms extra delta */
#if defined MBED_CONF_TARGET_DEEP_SLEEP_LATENCY
#define DEEP_SLEEP_DELAY_DELTA_US ((MBED_CONF_TARGET_DEEP_SLEEP_LATENCY * 1000ULL) + 1000ULL)
#define DEEP_SLEEP_DELAY_DELTA milliseconds(MBED_CONF_TARGET_DEEP_SLEEP_LATENCY + 1)
#else
#define DEEP_SLEEP_DELAY_DELTA_US 2500ULL
#define DEEP_SLEEP_DELAY_DELTA 2500us
#endif
using namespace utest::v1;
using mbed::internal::SysTimer;
const us_timestamp_t DELAY_US = TEST_TICK_US;
// The SysTick interrupt must not be set as pending by the test code.
template <uint32_t US_IN_TICK>
class SysTimerTest: public SysTimer<US_IN_TICK, false> {
template <class Period>
class SysTimerTest: public SysTimer<Period, false> {
private:
Semaphore _sem;
virtual void handler()
{
_sem.release();
SysTimer<US_IN_TICK, false>::handler();
SysTimer<Period, false>::handler();
}
public:
SysTimerTest() :
SysTimer<US_IN_TICK, false>(), _sem(0, 1)
SysTimer<Period, false>(), _sem(0, 1)
{
}
SysTimerTest(const ticker_data_t *data) :
SysTimer<US_IN_TICK, false>(data), _sem(0, 1)
SysTimer<Period, false>(data), _sem(0, 1)
{
}
@ -66,7 +87,7 @@ public:
{
}
bool sem_try_acquire(uint32_t millisec)
bool sem_try_acquire(rtos::Kernel::Clock::duration_u32 millisec)
{
return _sem.try_acquire_for(millisec);
}
@ -77,7 +98,7 @@ public:
}
};
timestamp_t mock_ticker_timestamp;
duration<timestamp_t, std::micro> mock_ticker_timestamp;
void mock_ticker_init()
{
@ -85,7 +106,7 @@ void mock_ticker_init()
uint32_t mock_ticker_read()
{
return mock_ticker_timestamp;
return mock_ticker_timestamp.count();
}
void mock_ticker_disable_interrupt()
@ -137,7 +158,7 @@ const ticker_data_t mock_ticker_data = {
void mock_ticker_reset()
{
mock_ticker_timestamp = 0;
mock_ticker_timestamp = 0s;
memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue);
}
@ -149,8 +170,9 @@ void mock_ticker_reset()
*/
void test_created_with_zero_tick_count(void)
{
SysTimerTest<1000> st;
TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
SysTimerTest<std::milli> st;
using time_point = decltype(st)::time_point;
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(0)), st.get_tick());
}
/** Test tick count is updated correctly
@ -167,20 +189,21 @@ void test_created_with_zero_tick_count(void)
void test_update_tick(void)
{
mock_ticker_reset();
SysTimerTest<1000> st(&mock_ticker_data);
st.set_wake_time(st.get_tick() + TEST_TICKS * 2);
SysTimerTest<std::milli> st(&mock_ticker_data);
using time_point = decltype(st)::time_point;
st.set_wake_time(st.get_tick() + TEST_TICK_DURATION(2));
st.cancel_wake();
TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(0)), st.get_tick());
st.set_wake_time(st.get_tick() + TEST_TICKS * 2);
mock_ticker_timestamp = DELAY_US;
st.set_wake_time(st.get_tick() + TEST_TICK_DURATION(2));
mock_ticker_timestamp = TEST_TICK_DURATION(1);
st.cancel_wake();
TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.update_and_get_tick());
TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.get_tick());
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.update_and_get_tick());
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.get_tick());
st.set_wake_time(st.get_tick() + TEST_TICKS * 2);
st.set_wake_time(st.get_tick() + TEST_TICK_DURATION(2));
st.cancel_wake();
TEST_ASSERT_EQUAL_UINT32(TEST_TICKS, st.get_tick());
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.get_tick());
}
/** Test get_time returns correct time
@ -192,12 +215,12 @@ void test_update_tick(void)
void test_get_time(void)
{
mock_ticker_reset();
SysTimerTest<1000> st(&mock_ticker_data);
us_timestamp_t t1 = st.get_time();
SysTimerTest<std::milli> st(&mock_ticker_data);
auto t1 = st.get_time();
mock_ticker_timestamp = DELAY_US;
us_timestamp_t t2 = st.get_time();
TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1);
mock_ticker_timestamp = TEST_TICK_DURATION(1);
auto t2 = st.get_time();
TEST_ASSERT_EQUAL_DURATION(TEST_TICK_DURATION(1), t2 - t1);
}
/** Test cancel_tick
@ -209,14 +232,15 @@ void test_get_time(void)
*/
void test_cancel_tick(void)
{
SysTimerTest<TEST_TICK_US> st;
SysTimerTest<TEST_TICK_PERIOD> st;
using time_point = decltype(st)::time_point;
st.cancel_tick();
st.start_tick();
st.cancel_tick();
bool acquired = st.sem_try_acquire((DELAY_US + DELAY_DELTA_US) / 1000ULL);
bool acquired = st.sem_try_acquire(duration_cast<Kernel::Clock::duration>(TEST_TICK_DURATION(1) + DELAY_DELTA));
TEST_ASSERT_FALSE(acquired);
TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(0)), st.get_tick());
}
/** Test handler called twice
@ -230,29 +254,30 @@ void test_cancel_tick(void)
*/
void test_handler_called_twice(void)
{
SysTimerTest<TEST_TICK_US> st;
us_timestamp_t t1 = st.get_time();
bool acquired = st.sem_try_acquire(0);
SysTimerTest<TEST_TICK_PERIOD> st;
using time_point = decltype(st)::time_point;
auto t1 = st.get_time();
bool acquired = st.sem_try_acquire(0s);
TEST_ASSERT_FALSE(acquired);
st.start_tick();
// Wait in a busy loop to prevent entering sleep or deepsleep modes.
do {
acquired = st.sem_try_acquire(0);
acquired = st.sem_try_acquire(0s);
} while (!acquired);
us_timestamp_t t2 = st.get_time();
auto t2 = st.get_time();
TEST_ASSERT_TRUE(acquired);
TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(1)), st.get_tick());
TEST_ASSERT_DURATION_WITHIN(DELAY_DELTA, TEST_TICK_DURATION(1), t2 - t1);
// Wait in a busy loop to prevent entering sleep or deepsleep modes.
do {
acquired = st.sem_try_acquire(0);
acquired = st.sem_try_acquire(0s);
} while (!acquired);
t2 = st.get_time();
TEST_ASSERT_TRUE(acquired);
TEST_ASSERT_EQUAL_UINT32(2, st.get_tick());
TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US * 2, t2 - t1);
TEST_ASSERT_EQUAL_TIME_POINT(time_point(TEST_TICK_DURATION(2)), st.get_tick());
TEST_ASSERT_DURATION_WITHIN(DELAY_DELTA, TEST_TICK_DURATION(2), t2 - t1);
st.cancel_tick();
}
@ -269,7 +294,7 @@ void test_handler_called_twice(void)
void test_sleep(void)
{
Timer timer;
SysTimerTest<TEST_TICK_US> st;
SysTimerTest<TEST_TICK_PERIOD> st;
sleep_manager_lock_deep_sleep();
timer.start();
@ -282,7 +307,7 @@ void test_sleep(void)
st.cancel_tick();
sleep_manager_unlock_deep_sleep();
TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(DELAY_DELTA, TEST_TICK_DURATION(1), timer.elapsed_time());
}
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER
@ -305,10 +330,10 @@ void test_deepsleep(void)
* hardware buffers are empty. However, such an API does not exist now,
* so we'll use the ThisThread::sleep_for() function for now.
*/
ThisThread::sleep_for(10);
ThisThread::sleep_for(10ms);
// Regular Timer might be disabled during deepsleep.
LowPowerTimer lptimer;
SysTimerTest<TEST_TICK_US> st;
SysTimerTest<TEST_TICK_PERIOD> st;
lptimer.start();
st.start_tick();
@ -317,7 +342,7 @@ void test_deepsleep(void)
lptimer.stop();
st.cancel_tick();
TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us());
TEST_ASSERT_DURATION_WITHIN(DEEP_SLEEP_DELAY_DELTA, TEST_TICK_DURATION(1), lptimer.elapsed_time());
}
#endif
#endif

View File

@ -35,35 +35,35 @@ public:
// preincrement operator
T operator++()
{
lock_guard lock(_mutex);
lock_guard<rtos::Mutex> lock(_mutex);
return ++_value;
}
// predecrement operator
T operator--()
{
lock_guard lock(_mutex);
lock_guard<rtos::Mutex> lock(_mutex);
return --_value;
}
// post increment operator
T operator++(int)
{
lock_guard lock(_mutex);
lock_guard<rtos::Mutex> lock(_mutex);
return _value++;
}
// post decrement operator
T operator--(int)
{
lock_guard lock(_mutex);
lock_guard<rtos::Mutex> lock(_mutex);
return _value--;
}
// conversion operator, used also for <,>,<=,>=,== and !=
operator T() const
{
lock_guard lock(_mutex);
lock_guard<rtos::Mutex> lock(_mutex);
return _value;
}

View File

@ -29,6 +29,7 @@
#include "rtos.h"
#include "SynchronizedIntegral.h"
#include <mstd_mutex>
#include <type_traits>
#define THREAD_STACK_SIZE 512
#if defined(__CORTEX_A9) || defined(__CORTEX_M23) || defined(__CORTEX_M33) || defined(TARGET_ARM_FM) || defined(TARGET_CY8CKIT_062_WIFI_BT_PSA)
@ -39,6 +40,12 @@
#define CHILD_THREAD_STACK_SIZE 384
#endif
#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \
do { \
using ct = std::common_type_t<decltype(delta), decltype(expected), decltype(actual)>; \
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
} while (0)
using namespace utest::v1;
using mstd::lock_guard;
@ -67,7 +74,7 @@ void increment_with_yield(counter_t *counter)
void increment_with_wait(counter_t *counter)
{
ThisThread::sleep_for(100);
ThisThread::sleep_for(100ms);
(*counter)++;
}
@ -93,7 +100,7 @@ void increment_with_murder(counter_t *counter)
{
// take ownership of the counter mutex so it prevent the child to
// modify counter.
lock_guard lock(counter->internal_mutex());
lock_guard<rtos::Mutex> lock(counter->internal_mutex());
Thread *child = new (std::nothrow) Thread(osPriorityNormal, CHILD_THREAD_STACK_SIZE);
char *dummy = new (std::nothrow) char[CHILD_THREAD_STACK_SIZE];
delete[] dummy;
@ -476,7 +483,7 @@ void test_thread_wait()
ThisThread::sleep_for(150ms);
TEST_ASSERT_UINT32_WITHIN(50000, 150000, timer.read_us());
TEST_ASSERT_DURATION_WITHIN(50ms, 150ms, timer.elapsed_time());
}
/** Testing thread name
@ -703,7 +710,7 @@ void test_msg_get()
void test_msg_put_thread(Queue<int32_t, 1> *queue)
{
queue->put((int32_t *)0xDEADBEEF, osWaitForever);
queue->put((int32_t *)0xDEADBEEF, Kernel::wait_for_u32_forever);
}

View File

@ -74,8 +74,10 @@ public:
SysTimer(const ticker_data_t *data);
virtual ~SysTimer();
protected:
~SysTimer();
public:
/**
* Get the interrupt number for the tick
*
@ -237,7 +239,7 @@ public:
protected:
using highres_duration_u32 = std::chrono::duration<uint32_t, highres_period>;
virtual void handler();
void handler() override;
void _increment_tick();
void _schedule_tick();
duration _elapsed_ticks() const;