diff --git a/dist/pythonlibs/testrunner/__init__.py b/dist/pythonlibs/testrunner/__init__.py index 3a372e5136..31fa260eb4 100755 --- a/dist/pythonlibs/testrunner/__init__.py +++ b/dist/pythonlibs/testrunner/__init__.py @@ -14,6 +14,7 @@ import pexpect from .spawn import find_exc_origin, setup_child, teardown_child from .unittest import PexpectTestCase # noqa, F401 expose to users +from .utils import test_utils_interactive_sync # noqa, F401 expose to users # Timeout for tests can be changed by setting RIOT_TEST_TIMEOUT to the desired # value in the environment variables diff --git a/dist/pythonlibs/testrunner/utils.py b/dist/pythonlibs/testrunner/utils.py new file mode 100644 index 0000000000..faee374235 --- /dev/null +++ b/dist/pythonlibs/testrunner/utils.py @@ -0,0 +1,27 @@ +# Copyright (C) 2019 Freie Universität Berlin +# +# 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. + +"""Utility functions for writing tests.""" + +import pexpect + + +def test_utils_interactive_sync(child, retries=5, delay=1): + """Synchronisation for 'test_utils_interactive_sync' function. + + Interacts through input to wait for node being ready. + """ + for _ in range(0, retries): + child.sendline('r') + ret = child.expect_exact(['READY', pexpect.TIMEOUT], timeout=delay) + if ret == 0: + break + else: + # Last call to make it fail her, + child.expect_exact('READY', timeout=0) + + child.sendline('s') + child.expect_exact('START') diff --git a/sys/Makefile b/sys/Makefile index 058697f249..1926dabe36 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -25,6 +25,9 @@ endif ifneq (,$(filter shell_commands,$(USEMODULE))) DIRS += shell/commands endif +ifneq (,$(filter test_utils_interactive_sync,$(USEMODULE))) + DIRS += test_utils/interactive_sync +endif ifneq (,$(filter net_help,$(USEMODULE))) DIRS += net/crosslayer/net_help endif diff --git a/sys/Makefile.dep b/sys/Makefile.dep index f9afc587e3..dcddeac2bc 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -9,3 +9,5 @@ endif ifneq (,$(filter prng_fortuna,$(USEMODULE))) CFLAGS += -DCRYPTO_AES endif + +include $(RIOTBASE)/sys/test_utils/Makefile.dep diff --git a/sys/include/test_utils/interactive_sync.h b/sys/include/test_utils/interactive_sync.h new file mode 100644 index 0000000000..b27a571f2d --- /dev/null +++ b/sys/include/test_utils/interactive_sync.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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. + */ + +/** + * @defgroup test_utils_interactive_sync Test interactive synchronization + * @ingroup sys + * @brief Utility function for synchronizing before a test + * + * @{ + * @file + * @brief Synchronization for normally non interactive tests + * + * @author Gaëtan Harter + */ + +#ifndef TEST_UTILS_INTERACTIVE_SYNC_H +#define TEST_UTILS_INTERACTIVE_SYNC_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Wait for the tester to start test + * + * @details Wait for a 's' character to return + * + */ +void test_utils_interactive_sync(void); + + +#ifdef __cplusplus +} +#endif +#endif /* TEST_UTILS_INTERACTIVE_SYNC_H */ +/** @} */ diff --git a/sys/test_utils/Makefile.dep b/sys/test_utils/Makefile.dep new file mode 100644 index 0000000000..4bafa543b8 --- /dev/null +++ b/sys/test_utils/Makefile.dep @@ -0,0 +1,3 @@ +ifneq (,$(filter test_utils_interactive_sync,$(USEMODULE))) + USEMODULE += stdin +endif diff --git a/sys/test_utils/interactive_sync/Makefile b/sys/test_utils/interactive_sync/Makefile new file mode 100644 index 0000000000..e22cec26b0 --- /dev/null +++ b/sys/test_utils/interactive_sync/Makefile @@ -0,0 +1,3 @@ +MODULE = test_utils_interactive_sync + +include $(RIOTBASE)/Makefile.base diff --git a/sys/test_utils/interactive_sync/interactive_sync.c b/sys/test_utils/interactive_sync/interactive_sync.c new file mode 100644 index 0000000000..6dba6ed425 --- /dev/null +++ b/sys/test_utils/interactive_sync/interactive_sync.c @@ -0,0 +1,20 @@ +#include +#include "test_utils/interactive_sync.h" + +void test_utils_interactive_sync(void) +{ + char c = '\0'; /* Print help on first loop */ + do { + if (c == 'r') { + /* This one should have a different case than the help message + * otherwise we match it when using 'expect' */ + puts("READY"); + } + else if (c != '\n' && c != '\r') { + puts("Help: Press s to start test, r to print it is ready"); + } + c = getchar(); + } while (c != 's'); + + puts("START"); +} diff --git a/tests/cond_order/Makefile b/tests/cond_order/Makefile index 8795a8226e..f138bec203 100644 --- a/tests/cond_order/Makefile +++ b/tests/cond_order/Makefile @@ -7,4 +7,6 @@ BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-leonardo arduino-nano \ nucleo-l031k6 nucleo-l053 nucleo-l053r8 \ stm32f0discovery stm32l0538-disco +USEMODULE += test_utils_interactive_sync + include $(RIOTBASE)/Makefile.include diff --git a/tests/cond_order/main.c b/tests/cond_order/main.c index 249c776af9..e0b0f8bf7f 100644 --- a/tests/cond_order/main.c +++ b/tests/cond_order/main.c @@ -24,6 +24,7 @@ #include "cond.h" #include "mutex.h" #include "thread.h" +#include "test_utils/interactive_sync.h" #define THREAD_NUMOF (5U) #define THREAD_FIRSTGROUP_NUMOF (3U) @@ -62,6 +63,8 @@ int main(void) puts("Condition variable order test"); puts("Please refer to the README.md for more information\n"); + test_utils_interactive_sync(); + mutex_init(&testlock); cond_init(&testcond); diff --git a/tests/cond_order/tests/01-run.py b/tests/cond_order/tests/01-run.py index 106a9cf9f2..4d7ccd315a 100755 --- a/tests/cond_order/tests/01-run.py +++ b/tests/cond_order/tests/01-run.py @@ -10,6 +10,8 @@ import os import sys +from testrunner import test_utils_interactive_sync + thread_prio = { 3: 6, 4: 4, @@ -21,6 +23,8 @@ first_group_size = 3 def testfunc(child): + test_utils_interactive_sync(child) + for k in thread_prio.keys(): child.expect(u"T%i \(prio %i\): waiting on condition variable now" % (k, thread_prio[k])) diff --git a/tests/libfixmath/Makefile b/tests/libfixmath/Makefile index ce035be05c..4fa74dcc92 100644 --- a/tests/libfixmath/Makefile +++ b/tests/libfixmath/Makefile @@ -2,7 +2,7 @@ include ../Makefile.tests_common USEPKG += libfixmath USEMODULE += libfixmath -USEMODULE += xtimer +USEMODULE += test_utils_interactive_sync TEST_ON_CI_WHITELIST += all diff --git a/tests/libfixmath/main.c b/tests/libfixmath/main.c index bf775239a4..48094637e1 100644 --- a/tests/libfixmath/main.c +++ b/tests/libfixmath/main.c @@ -30,8 +30,9 @@ #include -#include "xtimer.h" +#include "kernel_defines.h" #include "fix16.h" +#include "test_utils/interactive_sync.h" #ifndef M_PI # define M_PI 3.14159265359 @@ -185,8 +186,9 @@ static void unary_ops(void) int main(void) { - /* Delay output to prevent flooding of buffer */ - xtimer_sleep(1); + /* Sync to prevent flooding of buffer */ + test_utils_interactive_sync(); + puts("Unary."); unary_ops(); diff --git a/tests/libfixmath/tests/01-run.py b/tests/libfixmath/tests/01-run.py index 29213751f7..21e42d95fa 100755 --- a/tests/libfixmath/tests/01-run.py +++ b/tests/libfixmath/tests/01-run.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import sys -from testrunner import run +from testrunner import run, test_utils_interactive_sync def expect_unary(child): @@ -31,6 +31,7 @@ def expect_binary(child): def testfunc(child): + test_utils_interactive_sync(child) child.expect_exact('Unary.') expect_unary(child) child.expect_exact('Binary.') diff --git a/tests/posix_time/Makefile b/tests/posix_time/Makefile index d1a1ee9bb8..80171ab760 100644 --- a/tests/posix_time/Makefile +++ b/tests/posix_time/Makefile @@ -2,8 +2,7 @@ include ../Makefile.tests_common USEMODULE += posix_time -# This application uses getchar and thus expects input from stdio -USEMODULE += stdin +USEMODULE += test_utils_interactive_sync TEST_ON_CI_WHITELIST += all diff --git a/tests/posix_time/main.c b/tests/posix_time/main.c index e79fbced2b..670838ca14 100644 --- a/tests/posix_time/main.c +++ b/tests/posix_time/main.c @@ -26,11 +26,11 @@ #include #include +#include "test_utils/interactive_sync.h" int main(void) { - puts("Please hit any key and then ENTER to continue"); - getchar(); + test_utils_interactive_sync(); puts("5 x usleep(i++ * 500000)"); for (unsigned i = 0; i < 5; i++) { useconds_t us = i * 500000u; diff --git a/tests/posix_time/tests/01-run.py b/tests/posix_time/tests/01-run.py index 2f4dab0d66..8a2d57433a 100755 --- a/tests/posix_time/tests/01-run.py +++ b/tests/posix_time/tests/01-run.py @@ -10,7 +10,7 @@ import sys import time -from testrunner import run +from testrunner import run, test_utils_interactive_sync US_PER_SEC = 1000000 EXTERNAL_JITTER = 0.15 @@ -22,8 +22,7 @@ class InvalidTimeout(Exception): def testfunc(child): try: - child.expect_exact("Please hit any key and then ENTER to continue") - child.sendline("a") + test_utils_interactive_sync(child) start_test = time.time() child.expect_exact("5 x usleep(i++ * 500000)") for i in range(5): diff --git a/tests/xtimer_usleep/Makefile b/tests/xtimer_usleep/Makefile index 48cf81df4e..db3f153186 100644 --- a/tests/xtimer_usleep/Makefile +++ b/tests/xtimer_usleep/Makefile @@ -6,8 +6,7 @@ TEST_ON_CI_WHITELIST += all # This test randomly fails on `native` so disable it from CI TEST_ON_CI_BLACKLIST += native -# This application uses getchar and thus expects input from stdio -USEMODULE += stdin +USEMODULE += test_utils_interactive_sync # Port and pin configuration for probing with oscilloscope # Port number should be found in port enum e.g in cpu/include/periph_cpu.h diff --git a/tests/xtimer_usleep/main.c b/tests/xtimer_usleep/main.c index 12949b7fa5..f54d5c450e 100644 --- a/tests/xtimer_usleep/main.c +++ b/tests/xtimer_usleep/main.c @@ -27,6 +27,7 @@ #include "xtimer.h" #include "timex.h" +#include "test_utils/interactive_sync.h" #define RUNS (5U) #define SLEEP_TIMES_NUMOF ARRAY_SIZE(sleep_times) @@ -61,8 +62,7 @@ int main(void) printf("Running test %u times with %u distinct sleep times\n", RUNS, (unsigned)SLEEP_TIMES_NUMOF); - puts("Please hit any key and then ENTER to continue"); - getchar(); + test_utils_interactive_sync(); start_test = xtimer_now_usec(); for (unsigned m = 0; m < RUNS; m++) { for (unsigned n = 0; diff --git a/tests/xtimer_usleep/tests/01-run.py b/tests/xtimer_usleep/tests/01-run.py index 3766be750a..bcf0927baf 100755 --- a/tests/xtimer_usleep/tests/01-run.py +++ b/tests/xtimer_usleep/tests/01-run.py @@ -11,7 +11,7 @@ import sys import time -from testrunner import run +from testrunner import run, test_utils_interactive_sync US_PER_SEC = 1000000 @@ -28,8 +28,7 @@ def testfunc(child): RUNS = int(child.match.group(1)) SLEEP_TIMES_NUMOF = int(child.match.group(2)) try: - child.expect_exact(u"Please hit any key and then ENTER to continue") - child.sendline(u"a") + test_utils_interactive_sync(child) start_test = time.time() for m in range(RUNS): for n in range(SLEEP_TIMES_NUMOF):