Skip to content

Commit

Permalink
Greentea: events: Remove deprecated APIs and use chrono
Browse files Browse the repository at this point in the history
References to time should do so using std::chrono. We reworked events
tests to use std::chrono and new APIs in order to remove deprecation
warnings resulting from deprecated API calls. This required addition of
a macro for test assertions using std::chrono values.

Calls to wait_us() (not deprecated) are replaced with
ThisThread::sleep_for() as there is no reason to wait without sleeping.

Certain API calls that involve UserAllocatedEvents and do not have
std::chrono versions are left unchanged, for example
EventQueue.time_left().
  • Loading branch information
hazzlim committed Sep 27, 2021
1 parent aad68c7 commit 9ec2585
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 33 deletions.
10 changes: 6 additions & 4 deletions events/tests/TESTS/events/equeue/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

using namespace utest::v1;

using namespace std::chrono_literals;

#define TEST_EQUEUE_SIZE (4*EVENTS_EVENT_SIZE)
#define TEST_THREAD_STACK_SIZE 512
#define DISPATCH_INFINITE -1
Expand All @@ -43,7 +45,7 @@ static void simple_func(void *p)

static void sloth_func(void *p)
{
ThisThread::sleep_for(10);
ThisThread::sleep_for(10ms);
(*(reinterpret_cast<uint8_t *>(p)))++;
}

Expand Down Expand Up @@ -118,7 +120,7 @@ static void nest_func(void *p)
struct nest *nst = reinterpret_cast<struct nest *>(p);
equeue_call(nst->q, nst->cb, nst->data);

ThisThread::sleep_for(10);
ThisThread::sleep_for(10ms);
}

static void multithread_thread(equeue_t *p)
Expand Down Expand Up @@ -151,7 +153,7 @@ static void simple_breaker(void *p)
{
struct count_and_queue *caq = reinterpret_cast<struct count_and_queue *>(p);
equeue_break(caq->q);
ThisThread::sleep_for(10);
ThisThread::sleep_for(10ms);
caq->p++;
}

Expand Down Expand Up @@ -646,7 +648,7 @@ static void test_equeue_multithread()

Thread t1(osPriorityNormal, TEST_THREAD_STACK_SIZE);
t1.start(callback(multithread_thread, &q));
ThisThread::sleep_for(10);
ThisThread::sleep_for(10ms);
equeue_break(&q);
err = t1.join();
TEST_ASSERT_EQUAL_INT(0, err);
Expand Down
25 changes: 17 additions & 8 deletions events/tests/TESTS/events/queue/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@

using namespace utest::v1;

using namespace std::chrono;

// Macro for test assertions between std::chrono values
#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)

// Assume that tolerance is 5% of measured time.
#define DELTA(ms) (ms / 20)

Expand Down Expand Up @@ -111,9 +120,9 @@ SIMPLE_POSTS_TEST(1, 0x01)
SIMPLE_POSTS_TEST(0)


void time_func(Timer *t, int ms)
void time_func(Timer *t, milliseconds time)
{
TEST_ASSERT_INT_WITHIN(DELTA(ms), ms, t->read_ms());
TEST_ASSERT_DURATION_WITHIN(DELTA(time), time, t->elapsed_time());
t->reset();
}

Expand All @@ -126,7 +135,7 @@ void call_in_test()

for (int i = 0; i < N; i++) {
tickers[i].start();
queue.call_in((i + 1) * 100ms, time_func, &tickers[i], (i + 1) * 100);
queue.call_in((i + 1) * 100ms, time_func, &tickers[i], (i + 1) * 100ms);
}

queue.dispatch_for(N * 100ms);
Expand All @@ -141,7 +150,7 @@ void call_every_test()

for (int i = 0; i < N; i++) {
tickers[i].start();
queue.call_every((i + 1) * 100ms, time_func, &tickers[i], (i + 1) * 100);
queue.call_every((i + 1) * 100ms, time_func, &tickers[i], (i + 1) * 100ms);
}

queue.dispatch_for(N * 100ms);
Expand Down Expand Up @@ -528,7 +537,7 @@ void event_period_tests()
period_tests_queue.dispatch_for(80ms);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);
ThisThread::sleep_for(100ms);

// Event should only have been dispatched once and thus counter
// should be 1
Expand All @@ -546,7 +555,7 @@ void event_period_tests()
period_tests_queue.dispatch_for(80ms);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);
ThisThread::sleep_for(100ms);

// Event should default to non_periodic and thus only have been
// dispatched once. Counter should be 1.
Expand All @@ -564,7 +573,7 @@ void event_period_tests()
period_tests_queue.dispatch_for(80ms);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);
ThisThread::sleep_for(100ms);

// Event should default to non_periodic and thus only have been
// dispatched once. Counter should be 1.
Expand All @@ -581,7 +590,7 @@ void event_period_tests()
period_tests_queue.dispatch_for(80ms);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);
ThisThread::sleep_for(100ms);

// The event should be first dispatched after 10ms and then
// every subsequent 20ms until the dispatcher has completed.
Expand Down
68 changes: 47 additions & 21 deletions events/tests/TESTS/events/timing/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

using namespace utest::v1;

using namespace std::chrono;

#if !DEVICE_USTICKER
#error [NOT_SUPPORTED] test not supported
#else
Expand All @@ -37,6 +39,9 @@ using namespace utest::v1;
#define TEST_EVENTS_TIMING_MEAN 25
#endif

#define TEST_EVENTS_TIMING_TIME_DURATION milliseconds{TEST_EVENTS_TIMING_TIME}
#define TEST_EVENTS_TIMING_MEAN_DURATION milliseconds{TEST_EVENTS_TIMING_MEAN}

#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288
#endif
Expand All @@ -57,6 +62,17 @@ float chisq(float sigma)
return pow(gauss(0, sqrt(sigma)), 2);
}

milliseconds random_duration(milliseconds sigma)
{
milliseconds{static_cast<int>(chisq(sigma.count()))};
}

// Macro for test assertions between std::chrono values
#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)

Timer timer;

Expand All @@ -67,13 +83,16 @@ void timer_timing_test()
{
timer.reset();
timer.start();
int prev = timer.read_us();
auto prev = timer.elapsed_time();

while (prev < TEST_EVENTS_TIMING_TIME * 1000) {
int next = timer.read_us();
while (prev < TEST_EVENTS_TIMING_TIME_DURATION) {
const auto next = timer.elapsed_time();
if (next < prev) {
printf("backwards drift %d -> %d (%08x -> %08x)\r\n",
prev, next, prev, next);
printf("backwards drift %lldus -> %lldus (%08llx -> %08llx)\r\n",
duration_cast<microseconds>(prev).count(),
duration_cast<microseconds>(next).count(),
static_cast<uint64_t>(duration_cast<microseconds>(prev).count()),
static_cast<uint64_t>(duration_cast<microseconds>(next).count()));
}
TEST_ASSERT(next >= prev);
prev = next;
Expand All @@ -83,14 +102,18 @@ void timer_timing_test()
// equeue tick timing test
void tick_timing_test()
{
unsigned start = equeue_tick();
int prev = 0;
// equeue_tick() returns an integral millisecond value
const auto start = milliseconds{equeue_tick()};
auto prev = 0us;

while (prev < TEST_EVENTS_TIMING_TIME) {
int next = equeue_tick() - start;
while (prev < TEST_EVENTS_TIMING_TIME_DURATION) {
const auto next = milliseconds{equeue_tick()} - start;
if (next < prev) {
printf("backwards drift %d -> %d (%08x -> %08x)\r\n",
prev, next, prev, next);
printf("backwards drift %lldus -> %lldus (%08llx -> %08llx)\r\n",
duration_cast<microseconds>(prev).count(),
duration_cast<microseconds>(next).count(),
static_cast<uint64_t>(duration_cast<microseconds>(prev).count()),
static_cast<uint64_t>(duration_cast<microseconds>(next).count()));
}
TEST_ASSERT(next >= prev);
prev = next;
Expand All @@ -104,21 +127,23 @@ void semaphore_timing_test()
timer.reset();
timer.start();

int err = equeue_sema_create(&sema);
const int err = equeue_sema_create(&sema);
TEST_ASSERT_EQUAL(0, err);

while (timer.read_ms() < TEST_EVENTS_TIMING_TIME) {
int delay = chisq(TEST_EVENTS_TIMING_MEAN);
while (timer.elapsed_time() < TEST_EVENTS_TIMING_TIME_DURATION) {
const auto delay = random_duration(TEST_EVENTS_TIMING_MEAN_DURATION);

int start = timer.read_us();
equeue_sema_wait(&sema, delay);
int taken = timer.read_us() - start;
const auto start = timer.elapsed_time();
equeue_sema_wait(&sema, duration_cast<milliseconds>(delay).count());
const auto taken = timer.elapsed_time() - start;

if (taken < (delay * 1000 - 5000) || taken > (delay * 1000 + 5000)) {
printf("delay %dms => error %dus\r\n", delay, abs(1000 * delay - taken));
if (taken < (delay - 5000us) || taken > (delay + 5000us)) {
printf("delay %lldms => error %lldus\r\n",
duration_cast<milliseconds>(delay).count(),
abs(duration_cast<microseconds>(delay - taken).count()));
}

TEST_ASSERT_INT_WITHIN(5000, taken, delay * 1000);
TEST_ASSERT_DURATION_WITHIN(5000us, taken, delay);
}

equeue_sema_destroy(&sema);
Expand All @@ -128,7 +153,8 @@ void semaphore_timing_test()
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP((number_of_cases + 1)*TEST_EVENTS_TIMING_TIME / 1000, "default_auto");
GREENTEA_SETUP((number_of_cases + 1) * duration_cast<seconds>(TEST_EVENTS_TIMING_TIME_DURATION).count(),
"default_auto");
return verbose_test_setup_handler(number_of_cases);
}

Expand Down

0 comments on commit 9ec2585

Please sign in to comment.