Update events period method to check for invalid values

The period method currently allows any ms value positive, negative
and zero. A negative value means dispatch a non periodic event
ie just once. 0 is unspecified behaviour. This commit forces the
user to use either positive periods or a new constant non_periodic
and should any other value be provided will default to
non_periodic.

A Greentea test case is also provided to check this works as
expected.
pull/14087/head
adbridge 2020-12-23 17:29:13 +00:00
parent e917282d60
commit 6b2a0fe1d4
2 changed files with 89 additions and 4 deletions

11
events/include/events/Event.h Normal file → Executable file
View File

@ -47,6 +47,7 @@ template <typename... ArgTs>
class Event<void(ArgTs...)> {
public:
using duration = std::chrono::duration<int, std::milli>;
static constexpr duration non_periodic{-1};
/** Create an event
*
@ -67,7 +68,7 @@ public:
_event->equeue = &q->_equeue;
_event->id = 0;
_event->delay = duration(0);
_event->period = duration(-1);
_event->period = non_periodic;
_event->post = &Event::event_post<F>;
_event->dtor = &Event::event_dtor<F>;
@ -140,13 +141,21 @@ public:
/** Configure the period of an event
*
* @param p Period (in milliseconds) for repeatedly dispatching an event, expressed as a Chrono duration.
* Period must be either 'non_periodic' or > 0ms. If an invalid period is supplied then a
* default non_periodic value is used.
* E.g. period(200ms)
*/
void period(duration p)
{
MBED_ASSERT(p > duration(0) || p == non_periodic);
if (_event) {
if (p > duration(0)) {
_event->period = p;
}
else {
_event->period = non_periodic;
}
}
}
/** Configure the period of an event

78
events/tests/TESTS/events/queue/main.cpp Normal file → Executable file
View File

@ -508,6 +508,82 @@ void static_events_queue_test()
TEST_ASSERT_EQUAL(15, test4.counter);
}
static EventTest event_period;
void event_period_tests()
{
EventQueue queue;
// Test a non periodic event ie dispatched only once
Event<void(int)> event1(&queue, &event_period::f0);
event1.delay(100ms);
event1.period(Event::non_periodic);
event1.post()
queue.dispatch(800);
// Wait 1000ms and check the event execution status
wait_us(1000 * 1000)
// Event should only have been dispatched once and thus counter
// should be 1
TEST_ASSERT_EQUAL(1, event_period.counter);
// Test an event with an invalid -ve period.
event_period.counter = 0;
Event<void(int)> event2(&queue, &event_period::f0);
event2.delay(100ms);
event2.period(-10ms);
event2.post()
queue.dispatch(800);
// Wait 1000ms and check the event execution status
wait_us(1000 * 1000)
// Event should default to non_periodic and thus only have been
// dispatched once. Counter should be 1.
TEST_ASSERT_EQUAL(1, event_period.counter);
// Test an event with a zero period.
event_period.counter = 0;
Event<void(int)> event3(&queue, &event_period::f0);
event3.delay(100ms);
event3.period(0ms);
event3.post()
queue.dispatch(800);
// Wait 1000ms and check the event execution status
wait_us(1000 * 1000)
// Event should default to non_periodic and thus only have been
// dispatched once. Counter should be 1.
TEST_ASSERT_EQUAL(1, event_period.counter);
// Test a periodic event ie dispatched a number of times
event_period.counter = 0;
Event<void(int)> event4(&queue, &event_period::f0);
event4.delay(100ms);
event4.period(200ms);
event4.post()
queue.dispatch(800);
// Wait 1000ms and check the event execution status
wait_us(1000 * 1000)
// The event should be first dispatched after 100ms and then
// every subsequent 200ms until the dispatcher has completed.
// Thus the counter should be incremented after :
// 100ms, 300ms, 500ms and 700ms
TEST_ASSERT_EQUAL(4, event_period.counter);
}
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
@ -536,7 +612,7 @@ const Case cases[] = {
Case("Testing time_left", time_left_test),
Case("Testing mixed dynamic & static events queue", mixed_dynamic_static_events_queue_test),
Case("Testing static events queue", static_events_queue_test)
Case("Testing event period values", event_period_tests)
};
Specification specification(test_setup, cases);