-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: add test for ztimer_mbox_get_timeout()
- Loading branch information
Showing
4 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
include ../Makefile.sys_common | ||
|
||
USEMODULE += ztimer_usec | ||
USEMODULE += core_thread_flags | ||
USEMODULE += core_mbox | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
BOARD_INSUFFICIENT_MEMORY := \ | ||
atmega8 \ | ||
nucleo-l011k4 \ | ||
# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* | ||
* Copyright (C) 2023 Otto-von-Guericke-Universität Magdeburg | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup tests | ||
* @{ | ||
* | ||
* @file | ||
* @brief testing ztimer_mbox_get_timeout function | ||
* | ||
* | ||
* @author Marian Buschsieweke <[email protected]> | ||
* | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <stdio.h> | ||
|
||
#include "mbox.h" | ||
#include "test_utils/expect.h" | ||
#include "time_units.h" | ||
#include "ztimer.h" | ||
|
||
#define MSG_TYPE 42 | ||
#define MSG_VAL 1337 | ||
|
||
static msg_t queue[4]; | ||
static mbox_t mbox = MBOX_INIT(queue, ARRAY_SIZE(queue)); | ||
|
||
static void cb_mbox_put(void *arg) | ||
{ | ||
mbox_try_put(&mbox, arg); | ||
} | ||
|
||
static void test_mbox_already_full(void) | ||
{ | ||
printf("testing mbox already full prior call: "); | ||
msg_t msg = { .type = MSG_TYPE, .content.value = MSG_VAL }; | ||
mbox_put(&mbox, &msg); | ||
uint32_t start = ztimer_now(ZTIMER_USEC); | ||
expect(ztimer_mbox_get_timeout(ZTIMER_USEC, &mbox, &msg, US_PER_SEC) == 0); | ||
uint32_t stop = ztimer_now(ZTIMER_USEC); | ||
/* Returning immediately should with nothing else running in this test app | ||
* should not take more than a millisecond */ | ||
expect(stop - start < US_PER_MS); | ||
printf("OK\n"); | ||
} | ||
|
||
static void test_timeout_reached(void) | ||
{ | ||
const uint32_t timeout_us = 10 * US_PER_MS; | ||
printf("testing timeout is reached: "); | ||
msg_t msg = { .type = MSG_TYPE - 1, .content.value = MSG_VAL - 1 }; | ||
uint32_t start = ztimer_now(ZTIMER_USEC); | ||
expect(ztimer_mbox_get_timeout(ZTIMER_USEC, &mbox, &msg, timeout_us) == -ETIMEDOUT); | ||
uint32_t stop = ztimer_now(ZTIMER_USEC); | ||
/* This may take longer than the timeout due to overhead, background tasks, | ||
* etc. But it MUST NOT return early. */ | ||
expect(stop - start >= timeout_us); | ||
/* But it should also not take way too long */ | ||
expect(stop - start < 2 * timeout_us); | ||
/* msg must not be changed */ | ||
expect((msg.type == MSG_TYPE - 1) && (msg.content.value == MSG_VAL - 1)); | ||
printf("OK\n"); | ||
} | ||
|
||
static void test_msg_prior_timeout(void) | ||
{ | ||
const uint32_t msg_timeout_us = 1 * US_PER_MS; | ||
#if defined(BOARD_NATIVE64) || defined(BOARD_NATIVE) | ||
/* relax timing on native, as background load can mess with timing */ | ||
const uint32_t wait_timeout_us = 100 * US_PER_MS; | ||
#else | ||
const uint32_t wait_timeout_us = 2 * US_PER_MS; | ||
#endif | ||
|
||
msg_t msg = { .type = MSG_TYPE, .content.value = MSG_VAL }; | ||
msg_t got = { .type = 0 }; | ||
ztimer_t t = { | ||
.callback = cb_mbox_put, | ||
.arg = &msg, | ||
}; | ||
|
||
ztimer_set(ZTIMER_USEC, &t, msg_timeout_us); | ||
uint32_t start = ztimer_now(ZTIMER_USEC); | ||
expect(ztimer_mbox_get_timeout(ZTIMER_USEC, &mbox, &got, wait_timeout_us) == 0); | ||
uint32_t stop = ztimer_now(ZTIMER_USEC); | ||
|
||
/* the function should return AFTER the message was send, but BEFORE the | ||
* timeout was triggered */ | ||
expect(stop - start >= msg_timeout_us); | ||
expect(stop - start < wait_timeout_us); | ||
|
||
/* we should have gotten the correct message */ | ||
expect((got.type == msg.type) && (got.content.value == msg.content.value)); | ||
} | ||
|
||
static WORD_ALIGNED char stack_high_prio_thread[THREAD_STACKSIZE_TINY]; | ||
static void * high_prio_thread(void *arg) | ||
{ | ||
uint32_t timeout = (uintptr_t)arg; | ||
|
||
{ | ||
msg_t msg = { .type = MSG_TYPE, .content.value = MSG_VAL }; | ||
mbox_put(&mbox, &msg); | ||
} | ||
|
||
ztimer_spin(ZTIMER_USEC, timeout); | ||
return NULL; | ||
} | ||
|
||
static void test_msg_race(void) | ||
{ | ||
printf("testing timeout is reached despite message received (race): "); | ||
const uint32_t wait_timeout_us = 2 * US_PER_MS; | ||
const uintptr_t spin_timeout_us = 2 * wait_timeout_us; | ||
|
||
msg_t msg = { .type = MSG_TYPE, .content.value = MSG_VAL }; | ||
msg_t got = { .type = 0 }; | ||
|
||
thread_create(stack_high_prio_thread, sizeof(stack_high_prio_thread), | ||
THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_WOUT_YIELD, | ||
high_prio_thread, (void *)spin_timeout_us, "high_prio"); | ||
uint32_t start = ztimer_now(ZTIMER_USEC); | ||
expect(ztimer_mbox_get_timeout(ZTIMER_USEC, &mbox, &got, wait_timeout_us) == 0); | ||
uint32_t stop = ztimer_now(ZTIMER_USEC); | ||
|
||
/* the high prio thread should prevent us from running while it spins. It | ||
* will even prevent us from cancelling the timout. We should still receive | ||
* the message (which was received prior to the timeout), even though | ||
* we get CPU time only way after the timeout. */ | ||
expect(stop - start > wait_timeout_us); | ||
|
||
/* we should have gotten the correct message */ | ||
expect((got.type == msg.type) && (got.content.value == msg.content.value)); | ||
printf("OK\n"); | ||
} | ||
|
||
int main(void) | ||
{ | ||
const unsigned repetitions = 1000; | ||
printf("Testing ztimer_mbox_get_timeout()\n" | ||
"=================================\n"); | ||
test_mbox_already_full(); | ||
test_timeout_reached(); | ||
test_msg_race(); | ||
|
||
printf("Running test for reception prior timeout %u times: ", repetitions); | ||
for (unsigned i = 0; i < repetitions; i++) { | ||
test_msg_prior_timeout(); | ||
} | ||
|
||
printf("OK\n"); | ||
|
||
printf("\nALL TESTS SUCCEEDED\n"); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Copyright (C) 2023 Otto-von-Guericke-Universität Magdeburg | ||
# | ||
# This file is subject to the terms and conditions of the GNU Lesser | ||
# General Public License v2.1. See the file LICENSE in the top level | ||
# directory for more details. | ||
|
||
# @author Marian Buschsieweke <[email protected]> | ||
|
||
import sys | ||
from testrunner import run | ||
|
||
|
||
def testfunc(child): | ||
child.expect("Testing ztimer_mbox_get_timeout()") | ||
child.expect("ALL TESTS SUCCEEDED") | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(run(testfunc)) |