mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge #20011
20011: tests/unittests: add a unit test for ztimer r=benpicco a=maribu ### Contribution description This adds test coverage for removing ztimers with focus on ensuring that offsets are correctly updated on subsequent timers (e.g. not having timers fire too early). ### Testing procedure Run the unit tests (will be done by the CI as well). Maybe also introduce a random bug in `ztimer_remove()` and check if this is indeed caught by the unit tests. ### Issues/PRs references Prompted by https://github.com/RIOT-OS/RIOT/pull/18977#issuecomment-1764258356 Co-authored-by: Marian Buschsieweke <marian.buschsieweke@posteo.net>
This commit is contained in:
commit
d8b8f4e066
@ -288,6 +288,98 @@ static void test_ztimer_mock_is_set(void)
|
||||
TEST_ASSERT(!ztimer_is_set(z, &alarm2));
|
||||
}
|
||||
|
||||
static uint32_t calc_target_time(ztimer_mock_t *mock, ztimer_t *t)
|
||||
{
|
||||
ztimer_base_t *target = &t->base;
|
||||
ztimer_base_t *head = mock->super.list.next;
|
||||
|
||||
uint32_t timeout = mock->now + mock->target;
|
||||
|
||||
if (target == head) {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
for (ztimer_base_t *i = head->next; i != NULL; i = i->next) {
|
||||
timeout += i->offset;
|
||||
if (i == target) {
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Testing that removing timers has no unintended site effects on unrelated
|
||||
* timers (e.g. that offsets are correctly updated).
|
||||
*/
|
||||
static void test_ztimer_mock_remove(void)
|
||||
{
|
||||
ztimer_mock_t zmock;
|
||||
ztimer_clock_t *z = &zmock.super;
|
||||
|
||||
/* Basic sanity test of the mock implementation */
|
||||
ztimer_mock_init(&zmock, 32);
|
||||
|
||||
uint32_t count = 0;
|
||||
const uint32_t offset = 1000;
|
||||
ztimer_t alarms[] = {
|
||||
{ .callback = cb_incr, .arg = &count },
|
||||
{ .callback = cb_incr, .arg = &count },
|
||||
{ .callback = cb_incr, .arg = &count },
|
||||
{ .callback = cb_incr, .arg = &count },
|
||||
};
|
||||
uint32_t abs_targets[ARRAY_SIZE(alarms)];
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(alarms); i++) {
|
||||
ztimer_set(z, &alarms[i], (i + 1) * offset);
|
||||
}
|
||||
|
||||
/* target of first timer should be `offset` and it should be armed */
|
||||
TEST_ASSERT(zmock.armed);
|
||||
TEST_ASSERT_EQUAL_INT(offset, zmock.target - zmock.now);
|
||||
|
||||
/* relative offset from previous timer to alarm should always be `offset` */
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(alarms); i++) {
|
||||
TEST_ASSERT_EQUAL_INT(offset, alarms[i].base.offset);
|
||||
abs_targets[i] = zmock.now + (i + 1) * offset;
|
||||
}
|
||||
|
||||
/* check order is correct */
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(alarms) - 1; i++) {
|
||||
TEST_ASSERT(alarms[i].base.next == &alarms[i + 1].base);
|
||||
}
|
||||
|
||||
/* ensure target time for 3rd and 4th timer are correct */
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[2], calc_target_time(&zmock, &alarms[2]));
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[3], calc_target_time(&zmock, &alarms[3]));
|
||||
|
||||
/* ensure target times are still correct after 2nd timer is removed */
|
||||
ztimer_remove(z, &alarms[1]);
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[2], calc_target_time(&zmock, &alarms[2]));
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[3], calc_target_time(&zmock, &alarms[3]));
|
||||
|
||||
/* ensure target times are still correct after 1st timer fired */
|
||||
ztimer_mock_advance(&zmock, offset);
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[2], calc_target_time(&zmock, &alarms[2]));
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[3], calc_target_time(&zmock, &alarms[3]));
|
||||
TEST_ASSERT_EQUAL_INT(1, count);
|
||||
|
||||
/* ensure that removing an already fired time does not break things */
|
||||
ztimer_remove(z, &alarms[0]);
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[2], calc_target_time(&zmock, &alarms[2]));
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[3], calc_target_time(&zmock, &alarms[3]));
|
||||
TEST_ASSERT_EQUAL_INT(1, count);
|
||||
|
||||
/* ensure target time of 3rd timer is still correct after 4th timer is removed */
|
||||
ztimer_remove(z, &alarms[3]);
|
||||
TEST_ASSERT_EQUAL_INT(abs_targets[2], calc_target_time(&zmock, &alarms[2]));
|
||||
|
||||
/* ensure remaining timer still fires */
|
||||
ztimer_mock_advance(&zmock, 3 * offset);
|
||||
TEST_ASSERT_EQUAL_INT(2, count);
|
||||
}
|
||||
|
||||
Test *tests_ztimer_mock_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
@ -298,6 +390,7 @@ Test *tests_ztimer_mock_tests(void)
|
||||
new_TestFixture(test_ztimer_mock_set32),
|
||||
new_TestFixture(test_ztimer_mock_set16),
|
||||
new_TestFixture(test_ztimer_mock_is_set),
|
||||
new_TestFixture(test_ztimer_mock_remove),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(ztimer_tests, NULL, NULL, fixtures);
|
||||
|
Loading…
Reference in New Issue
Block a user