From a514c9bc12e2f0d4e32448351a39d8dbc538e549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Wed, 28 Aug 2019 17:32:29 +0200 Subject: [PATCH 1/7] jlink.sh: use PYTERMFLAGS Use PYTERMFLAGS for configuring the terminal. --- dist/tools/jlink/jlink.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/tools/jlink/jlink.sh b/dist/tools/jlink/jlink.sh index 8783f529af..03edba36e3 100755 --- a/dist/tools/jlink/jlink.sh +++ b/dist/tools/jlink/jlink.sh @@ -68,7 +68,7 @@ _JLINK_IF=SWD _JLINK_SPEED=2000 # default terminal frontend _JLINK_TERMPROG=${RIOTTOOLS}/pyterm/pyterm -_JLINK_TERMFLAGS="-ts 19021" +_JLINK_TERMFLAGS="-ts 19021 ${PYTERMFLAGS}" # # a couple of tests for certain configuration options From d27a43f89a93cc3edadd7a73e44dbee0ea3cede1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Wed, 28 Aug 2019 17:27:53 +0200 Subject: [PATCH 2/7] Makefile.include: add cleanterm target It is similar to 'term' but with removing possible additional behaviors from pyterm. It currently removes the logging prefix. --- Makefile.include | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile.include b/Makefile.include index 1a7607ad5b..e4e10acb0c 100644 --- a/Makefile.include +++ b/Makefile.include @@ -630,6 +630,13 @@ term: $(filter flash flash-only, $(MAKECMDGOALS)) $(TERMDEPS) $(call check_cmd,$(TERMPROG),Terminal program) $(TERMPROG) $(TERMFLAGS) +# Term without the pyterm added logging +# TERMFLAGS must be exported for `jlink.sh term_rtt`. +cleanterm: export PYTERMFLAGS += --noprefix +cleanterm: $(filter flash, $(MAKECMDGOALS)) $(TERMDEPS) + $(call check_cmd,$(TERMPROG),Terminal program) + $(TERMPROG) $(TERMFLAGS) + list-ttys: $(Q)$(RIOTTOOLS)/usb-serial/list-ttys.sh From c75d5120b49e1fd33610efe7e9b806087459616d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Wed, 28 Aug 2019 17:29:13 +0200 Subject: [PATCH 3/7] testrunner: use 'cleanterm' for testing Use a clean terminal without added decoration on the output for testing. --- dist/pythonlibs/testrunner/spawn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/pythonlibs/testrunner/spawn.py b/dist/pythonlibs/testrunner/spawn.py index 84164d1a1d..34859b1f61 100644 --- a/dist/pythonlibs/testrunner/spawn.py +++ b/dist/pythonlibs/testrunner/spawn.py @@ -36,7 +36,7 @@ def find_exc_origin(exc_info): def setup_child(timeout=10, spawnclass=pexpect.spawnu, env=None, logfile=None): - child = spawnclass("make term", env=env, timeout=timeout, + child = spawnclass("make cleanterm", env=env, timeout=timeout, codec_errors='replace', echo=False) # on many platforms, the termprog needs a short while to be ready... From d33e2d215e1140ac303b700c55c417a554595313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Thu, 21 Feb 2019 17:48:00 +0100 Subject: [PATCH 4/7] tests/test_tools: test to get a command return value Get the output of a one line command without other garbage messages. --- tests/test_tools/main.c | 35 ++++++++++++++++++++++++++++++++ tests/test_tools/tests/01-run.py | 11 ++++++++++ 2 files changed, 46 insertions(+) diff --git a/tests/test_tools/main.c b/tests/test_tools/main.c index cb3927f243..c7fdbcd61f 100644 --- a/tests/test_tools/main.c +++ b/tests/test_tools/main.c @@ -15,6 +15,8 @@ */ #include +#include +#include #include "shell_commands.h" #include "shell.h" @@ -65,9 +67,42 @@ static int cmd_shellping(int argc, char **argv) } +/** + * @brief Uppercase the first word + * + * First argument is read, converted to uppercase and printed with a newline. + * + * @param[in] argc Number of arguments + * @param[in] argv Array of arguments + * + * @return 0 on success + * + */ +static int cmd_toupper(int argc, char **argv) +{ + if (argc != 2) { + puts("Invalid number of argument"); + printf("Usage: %s \n", argv[0]); + return 1; + } + + size_t len = strlen(argv[1]); + for (size_t i = 0; i < len; i++) { + /* Cast to 'int' as llvm and some compilers complain about + * array subscript has type 'char' */ + char c = toupper((int)argv[1][i]); + putchar(c); + } + putchar('\n'); + + return 0; +} + + static const shell_command_t shell_commands[] = { { "shellping", "Just print 'shellpong'", cmd_shellping }, { "true", "do nothing, successfully", cmd_true }, + { "toupper", "uppercase first argument", cmd_toupper }, { NULL, NULL, NULL } }; diff --git a/tests/test_tools/tests/01-run.py b/tests/test_tools/tests/01-run.py index ced29379ed..1b2dbec982 100755 --- a/tests/test_tools/tests/01-run.py +++ b/tests/test_tools/tests/01-run.py @@ -38,12 +38,20 @@ def _test_no_local_echo(child): assert res == 0, "There should have been a timeout and not match stdin" +def _test_clean_output(child): + """Verify that only what the node sends is received.""" + child.sendline('toupper lowercase') + retline = child.readline() + assert retline.strip() == 'LOWERCASE' + + def testfunc(child): """Run some tests to verify the board under test behaves correctly. It currently tests: * local echo + * getting some test output without other messages """ child.expect_exact("Running 'tests_tools' application") @@ -55,6 +63,9 @@ def testfunc(child): # The node should still answer after the previous one _shellping(child) + # Check that the output is clean without extra terminal output + _test_clean_output(child) + if __name__ == "__main__": sys.exit(run(testfunc)) From baad72c44a296a0f9ed862fadff5cc4705476423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Thu, 29 Aug 2019 15:31:39 +0200 Subject: [PATCH 5/7] Makefile.include: allow sending newline with cleanterm Disable repeating the command on empty line to allow sending empty lines. --- Makefile.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.include b/Makefile.include index e4e10acb0c..befb9d8647 100644 --- a/Makefile.include +++ b/Makefile.include @@ -632,7 +632,7 @@ term: $(filter flash flash-only, $(MAKECMDGOALS)) $(TERMDEPS) # Term without the pyterm added logging # TERMFLAGS must be exported for `jlink.sh term_rtt`. -cleanterm: export PYTERMFLAGS += --noprefix +cleanterm: export PYTERMFLAGS += --noprefix --no-repeat-command-on-empty-line cleanterm: $(filter flash, $(MAKECMDGOALS)) $(TERMDEPS) $(call check_cmd,$(TERMPROG),Terminal program) $(TERMPROG) $(TERMFLAGS) From 1fce298441df349a1bc3ef72d38b03227727ee64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Tue, 27 Aug 2019 15:09:49 +0200 Subject: [PATCH 6/7] tests/test_tools: test receiving an empty line Test receiving an empty line. It was before not possible with `pyterm` but is fixed by previous commit. --- tests/test_tools/main.c | 21 ++++++++++++++++++++- tests/test_tools/tests/01-run.py | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/tests/test_tools/main.c b/tests/test_tools/main.c index c7fdbcd61f..1051930c1b 100644 --- a/tests/test_tools/main.c +++ b/tests/test_tools/main.c @@ -66,7 +66,6 @@ static int cmd_shellping(int argc, char **argv) return 0; } - /** * @brief Uppercase the first word * @@ -98,11 +97,31 @@ static int cmd_toupper(int argc, char **argv) return 0; } +/** + * @brief getchar, read one character + * + * Read one character and print its hex value + * + * @param[in] argc Number of arguments + * @param[in] argv Array of arguments + * + * @return 0 + * + */ +static int cmd_getchar(int argc, char **argv) +{ + (void)argc; + (void)argv; + printf("%s 0x%02x\n", argv[0], getchar()); + return 0; +} + static const shell_command_t shell_commands[] = { { "shellping", "Just print 'shellpong'", cmd_shellping }, { "true", "do nothing, successfully", cmd_true }, { "toupper", "uppercase first argument", cmd_toupper }, + { "getchar", "Get one character and print the hex value", cmd_getchar }, { NULL, NULL, NULL } }; diff --git a/tests/test_tools/tests/01-run.py b/tests/test_tools/tests/01-run.py index 1b2dbec982..ca278074a8 100755 --- a/tests/test_tools/tests/01-run.py +++ b/tests/test_tools/tests/01-run.py @@ -38,6 +38,16 @@ def _test_no_local_echo(child): assert res == 0, "There should have been a timeout and not match stdin" +def _test_sending_newline(child): + """Verify that a empty line can be send to the node. + + The local terminal must NOT repeat the previous command. + """ + child.sendline('getchar') + child.sendline('') # send only one newline character + child.expect_exact('getchar 0x0a\r\n') + + def _test_clean_output(child): """Verify that only what the node sends is received.""" child.sendline('toupper lowercase') @@ -52,6 +62,7 @@ def testfunc(child): * local echo * getting some test output without other messages + * sending empty lines """ child.expect_exact("Running 'tests_tools' application") @@ -66,6 +77,9 @@ def testfunc(child): # Check that the output is clean without extra terminal output _test_clean_output(child) + # It is possible to send an empty newline + _test_sending_newline(child) + if __name__ == "__main__": sys.exit(run(testfunc)) From 66300b2f72b480b6fe564b4d808e27d46b2c613f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Mon, 30 Sep 2019 16:38:30 +0200 Subject: [PATCH 7/7] tests/README.md: add documentation about uart interaction Add some documentation about tests using `cleanterm` and what guarantees it gives. --- tests/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/README.md b/tests/README.md index e0e3b1f5f9..62d6644485 100644 --- a/tests/README.md +++ b/tests/README.md @@ -27,3 +27,18 @@ An automated way of knowing if a test is available is to execute the It executes without error if tests run by 'make test' are present. make test/available + + +Interaction through the uart +---------------------------- + +Tests implemented with `testrunner` use the `cleanterm` target that +provides an interaction without adding extra text output or input handling. +It can currently be expected to have unmodified line based interaction with the +board. + +The expected behavior is verified with the test in `tests/test_tools`. + +Tests cannot rely on having on all boards and terminal programs: +* unbuffered input +* allowing sending special characters like `ctrl+c/ctrl+d`