diff --git a/makefiles/tests/tests.inc.mk b/makefiles/tests/tests.inc.mk index fcfe348fa68e1..8aaaa723872b0 100644 --- a/makefiles/tests/tests.inc.mk +++ b/makefiles/tests/tests.inc.mk @@ -28,6 +28,16 @@ test: $(TEST_DEPS) done test/available: +ifneq (,$(TEST_ON_CI_WHITELIST)) + ifeq (,$(filter $(BOARD),$(TEST_ON_CI_WHITELIST))) + @echo "Board $(BOARD) not in TEST_ON_CI_WHITELIST" + $(Q)false + endif +endif +ifneq (,$(filter $(BOARD) all,$(TEST_ON_CI_BLACKLIST))) + @echo "Board $(BOARD) is in TEST_ON_CI_BLACKLIST" + $(Q)false +endif $(Q)test -n "$(strip $(TESTS))" # Tests that require root privileges diff --git a/tests/periph_timer_short_relative_set/main.c b/tests/periph_timer_short_relative_set/main.c index c48da445ad7d7..1731ae7aa57e5 100644 --- a/tests/periph_timer_short_relative_set/main.c +++ b/tests/periph_timer_short_relative_set/main.c @@ -75,33 +75,36 @@ int main(void) puts("\nTest for peripheral TIMER short timer_set()\n"); printf("This test tries timer_set() with decreasing intervals down to 0.\n" - "You should see lines like 'interval ok', followed by a success" + "You should see lines like 'interval : OK', followed by a success" " message.\n" "On failure, this test prints an error message.\n\n"); - printf("testing periph_timer %u, freq %lu\n", TEST_TIMER_DEV, TEST_TIMER_FREQ); + printf("testing periph_timer %u, freq %lu, bits = %u\n", + TEST_TIMER_DEV, TEST_TIMER_FREQ, TEST_TIMER_WIDTH); timer_init(TEST_TIMER_DEV, TEST_TIMER_FREQ, cb, thread_get_active()); - uint32_t interval = 100; + uint32_t interval = 16; + const unsigned max_repetitions = 128; while (interval--) { - uint32_t before = timer_read(TEST_TIMER_DEV); - timer_set(TEST_TIMER_DEV, 0, interval); - while(!thread_flags_clear(1)) { - uint32_t diff = (timer_read(TEST_TIMER_DEV) - before) - & TEST_TIMER_MAX; - if (diff > TEST_MAX_DIFF) { - printf("ERROR: too long delay, aborted after %" PRIu32 - " (TEST_MAX_DIFF=%lu)\n" - "TEST FAILED\n" - "Note: This is currently expected to fail on most boards.\n", - diff, TEST_MAX_DIFF); - while(1) {} + for (unsigned rep = 0; rep < max_repetitions; rep++) { + uint32_t before = timer_read(TEST_TIMER_DEV); + timer_set(TEST_TIMER_DEV, 0, interval); + while (!thread_flags_clear(1)) { + uint32_t diff = (timer_read(TEST_TIMER_DEV) - before) + & TEST_TIMER_MAX; + if (diff > TEST_MAX_DIFF) { + printf("ERROR: too long delay, aborted after %" PRIu32 + " (TEST_MAX_DIFF=%lu) on repetition %u\n" + "TEST FAILED\n", + diff, TEST_MAX_DIFF, rep); + return EXIT_FAILURE; + } } } - printf("interval %" PRIu32 " ok\n", interval); + printf("interval %" PRIu32 ": OK\n", interval); } puts("\nTEST SUCCEEDED"); - return 0; + return EXIT_SUCCESS; } diff --git a/tests/thread_float/main.c b/tests/thread_float/main.c index 12eb44f559020..60363be7fea74 100644 --- a/tests/thread_float/main.c +++ b/tests/thread_float/main.c @@ -23,10 +23,13 @@ #include #include -#include "thread.h" +#include "board.h" +#include "macros/units.h" #include "msg.h" +#include "periph_conf.h" +#include "thread.h" +#include "time_units.h" #include "ztimer.h" -#include "timex.h" static char t1_stack[THREAD_STACKSIZE_MAIN]; static char t2_stack[THREAD_STACKSIZE_MAIN]; @@ -36,15 +39,19 @@ static kernel_pid_t p1, p2, p3; static ztimer_t timer; -#define OFFSET (100) +#ifndef CLOCK_CORECLOCK +/* native is missing access to the CPU clock frequency, let's provide a + * conservative fallback */ +#define CLOCK_CORECLOCK MHZ(100) +#endif static mutex_t lock = MUTEX_INIT; static void timer_cb(void *arg) { - (void)arg; + uint32_t *timeout = arg; thread_yield(); - ztimer_set(ZTIMER_USEC, &timer, OFFSET); + ztimer_set(ZTIMER_USEC, &timer, *timeout); } static void *thread_1_2_3(void *_arg) @@ -81,6 +88,13 @@ int main(void) const char *t2_name = "t2"; const char *t3_name = "t3"; + /* Let's not overwhelm boards by firing IRQs faster than they can handle and + * give them 50 billion CPU cycles per timeout. + * + * (Note: The `static` is required as this variable will be accessed from + * the ISR, which will occur even after the main thread has exited.) */ + static uint32_t timeout = 50000000000U / CLOCK_CORECLOCK; + p1 = thread_create(t1_stack, sizeof(t1_stack), THREAD_PRIORITY_MAIN + 1, THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, thread_1_2_3, (void *)t1_name, t1_name); @@ -92,8 +106,11 @@ int main(void) thread_1_2_3, (void *)t3_name, t3_name); puts("THREADS CREATED\n"); + printf("Context switch every %" PRIu32 " µs\n", timeout); + timer.callback = timer_cb; - ztimer_set(ZTIMER_USEC, &timer, OFFSET); + timer.arg = &timeout; + ztimer_set(ZTIMER_USEC, &timer, timeout); return 0; } diff --git a/tests/unittests/tests-core/Makefile.include b/tests/unittests/tests-core/Makefile.include new file mode 100644 index 0000000000000..d661c0df415a5 --- /dev/null +++ b/tests/unittests/tests-core/Makefile.include @@ -0,0 +1 @@ +USEMODULE += core_mbox diff --git a/tests/unittests/tests-core/tests-core-mbox.c b/tests/unittests/tests-core/tests-core-mbox.c new file mode 100644 index 0000000000000..87e041c7ee072 --- /dev/null +++ b/tests/unittests/tests-core/tests-core-mbox.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 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. + */ + +#include + +#include "embUnit.h" + +#include "mbox.h" + +#include "tests-core.h" + +#define QUEUE_SIZE 8 + +static unsigned gen_val(unsigned i) { + return i + 1337; +} + +static void test_mbox_put_get(void) +{ + mbox_t mbox; + msg_t queue[QUEUE_SIZE]; + msg_t msg = { .type = 0 }; + mbox_init(&mbox, queue, ARRAY_SIZE(queue)); + TEST_ASSERT_EQUAL_INT(0, mbox_avail(&mbox)); + + /* Filling the queue up to capacity one item at a time. This should + * succeed every single time. */ + for (unsigned i = 0; i < ARRAY_SIZE(queue); i++) { + msg.type = i; + msg.content.value = gen_val(i); + TEST_ASSERT_EQUAL_INT(1, mbox_try_put(&mbox, &msg)); + } + + /* Adding one item over capacity must fail. */ + msg.type = 4242; + msg.content.value = 4242; + TEST_ASSERT_EQUAL_INT(0, mbox_try_put(&mbox, &msg)); + + /* The queue must contain the items we filled in and in that order. */ + for (unsigned i = 0; i < ARRAY_SIZE(queue); i++) { + TEST_ASSERT_EQUAL_INT(i, queue[i].type); + TEST_ASSERT_EQUAL_INT(gen_val(i), queue[i].content.value); + } + + /* Now we drain the queue one item at a time. We expect to get the exact + * items we filled in and in that order. */ + for (unsigned i = 0; i < ARRAY_SIZE(queue); i++) { + TEST_ASSERT_EQUAL_INT(1, mbox_try_get(&mbox, &msg)); + TEST_ASSERT_EQUAL_INT(i, msg.type); + TEST_ASSERT_EQUAL_INT(gen_val(i), msg.content.value); + } + + /* The queue is now empty. Getting one more item (non-blocking) must fail */ + TEST_ASSERT_EQUAL_INT(0, mbox_try_get(&mbox, &msg)); +} + +Test *tests_core_mbox_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_mbox_put_get), + }; + + EMB_UNIT_TESTCALLER(core_mbox_tests, NULL, NULL, fixtures); + + return (Test *)&core_mbox_tests; +} diff --git a/tests/unittests/tests-core/tests-core.c b/tests/unittests/tests-core/tests-core.c index cdd6689655e97..6e58a738d6356 100644 --- a/tests/unittests/tests-core/tests-core.c +++ b/tests/unittests/tests-core/tests-core.c @@ -15,6 +15,7 @@ void tests_core(void) TESTS_RUN(tests_core_cib_tests()); TESTS_RUN(tests_core_clist_tests()); TESTS_RUN(tests_core_list_tests()); + TESTS_RUN(tests_core_mbox_tests()); TESTS_RUN(tests_core_priority_queue_tests()); TESTS_RUN(tests_core_byteorder_tests()); TESTS_RUN(tests_core_ringbuffer_tests()); diff --git a/tests/unittests/tests-core/tests-core.h b/tests/unittests/tests-core/tests-core.h index 29326b51956a2..1b4df59f1c379 100644 --- a/tests/unittests/tests-core/tests-core.h +++ b/tests/unittests/tests-core/tests-core.h @@ -64,6 +64,13 @@ Test *tests_core_clist_tests(void); */ Test *tests_core_list_tests(void); +/** + * @brief Generates tests for mbox.h + * + * @return embUnit tests if successful, NULL if not. + */ +Test *tests_core_mbox_tests(void); + /** * @brief Generates tests for priority_queue.h *