From 027426793cc7b9fd4e721d436722284e110767bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Sat, 23 Mar 2019 14:20:18 +0100 Subject: [PATCH 1/7] test_utils_interactive_sync: add a helper for synchronizing tests Add an implementation that waits for 's' to print 'START' and return. If 'r' is given is prints 'READY' to allow querying for state. The help and answered string have to be different to not match the other. Using puts/getchar was smaller than using `stdio_read/stdio_write` on the example I tested with `esp32`. --- sys/Makefile | 3 ++ sys/Makefile.dep | 2 + sys/include/test_utils/interactive_sync.h | 42 +++++++++++++++++++ sys/test_utils/Makefile.dep | 3 ++ sys/test_utils/interactive_sync/Makefile | 3 ++ .../interactive_sync/interactive_sync.c | 20 +++++++++ 6 files changed, 73 insertions(+) create mode 100644 sys/include/test_utils/interactive_sync.h create mode 100644 sys/test_utils/Makefile.dep create mode 100644 sys/test_utils/interactive_sync/Makefile create mode 100644 sys/test_utils/interactive_sync/interactive_sync.c 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"); +} From e5e9d81cce20141181f446885070f73c251f275c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Sat, 23 Mar 2019 14:46:37 +0100 Subject: [PATCH 2/7] testrunner/utils: add helper for test_utils_interactive_sync Add helper to do the synchronisation. --- dist/pythonlibs/testrunner/__init__.py | 1 + dist/pythonlibs/testrunner/utils.py | 27 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 dist/pythonlibs/testrunner/utils.py 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') From f193ffd604d8e1e1aa2b253c0036eea7e023d343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Fri, 19 Jul 2019 15:39:10 +0200 Subject: [PATCH 3/7] tests/cond_order: use test_utils_interactive_sync Use test_utils_interactive_sync for synchronizing some case treat the output before `reset` as the start of the test, which fails for some boards/configurations. --- tests/cond_order/Makefile | 2 ++ tests/cond_order/main.c | 3 +++ tests/cond_order/tests/01-run.py | 4 ++++ 3 files changed, 9 insertions(+) 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])) From 1172ca9f93590c93208166d580e13c746defd18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Mon, 12 Aug 2019 16:42:21 +0200 Subject: [PATCH 4/7] tests/xtimer_usleep: use test_utils_interactive_sync Use test_utils_interactive_sync for synchronizing test instead of the custom 'getchar' handling. --- tests/xtimer_usleep/Makefile | 3 +-- tests/xtimer_usleep/main.c | 4 ++-- tests/xtimer_usleep/tests/01-run.py | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) 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): From ed27d3b68b8e688c0e62738f478a62b2302ff05f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Mon, 12 Aug 2019 16:42:21 +0200 Subject: [PATCH 5/7] tests/posix_time: use test_utils_interactive_sync Use test_utils_interactive_sync for synchronizing test instead of the custom 'getchar' handling. --- tests/posix_time/Makefile | 3 +-- tests/posix_time/main.c | 4 ++-- tests/posix_time/tests/01-run.py | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) 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): From 4c209ab8d7efec038c8800b3fd8c3f68025967bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Mon, 12 Aug 2019 16:42:21 +0200 Subject: [PATCH 6/7] tests/libfixmath: explicitly import ARRAY_SIZE definition ARRAY_SIZE is implicitly imported by "xtimer.h" which will be removed of this file. --- tests/libfixmath/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/libfixmath/main.c b/tests/libfixmath/main.c index bf775239a4..52f12f530c 100644 --- a/tests/libfixmath/main.c +++ b/tests/libfixmath/main.c @@ -30,6 +30,7 @@ #include +#include "kernel_defines.h" #include "xtimer.h" #include "fix16.h" From ac8a6cf3a30df10dca537e0db5329f72879c7f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Mon, 12 Aug 2019 16:42:21 +0200 Subject: [PATCH 7/7] tests/libfixmath: use test_utils_interactive_sync Replace the 'xtimer_sleep' hack to prevent flooding at startup to use test_utils_interactive_sync for synchronizing. --- tests/libfixmath/Makefile | 2 +- tests/libfixmath/main.c | 7 ++++--- tests/libfixmath/tests/01-run.py | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) 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 52f12f530c..48094637e1 100644 --- a/tests/libfixmath/main.c +++ b/tests/libfixmath/main.c @@ -31,8 +31,8 @@ #include #include "kernel_defines.h" -#include "xtimer.h" #include "fix16.h" +#include "test_utils/interactive_sync.h" #ifndef M_PI # define M_PI 3.14159265359 @@ -186,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.')