Skip to content

Commit 3e08d6c

Browse files
committed
tests/sys/shell: make test more robust
This changes the behavior of the test script for verifying the `help` command: It no longer assumes a specific order for the list of commands. Making the test robust is a bit tricky, as the module `shell_cmds_default` that is used here may add commands specific to a set of board. We use `help_json` to get the list of commands actually provided, so that we know how many rows the command table printed by `help` need to be parsed. A minimum set of commands that *must* be present for all boards is hard-coded in the test script and the actually provided commands are tested against this. Otherwise e.g. an empty list of commands presented by `help` and `help_json` would also pass.
1 parent 5a342e8 commit 3e08d6c

File tree

2 files changed

+60
-19
lines changed

2 files changed

+60
-19
lines changed

tests/sys/shell/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ USEMODULE += shell_cmds_default
66
USEMODULE += ps
77
USEMODULE += ztimer_msec
88

9+
# JSON help is needed by test script
10+
USEMODULE += shell_builtin_cmd_help_json
11+
912
# Use a terminal that does not introduce extra characters into the stream.
1013
RIOT_TERMINAL ?= socat
1114

tests/sys/shell/tests/01-run.py

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,30 @@
66
# General Public License v2.1. See the file LICENSE in the top level
77
# directory for more details.
88

9-
import sys
9+
import json
1010
import os
11+
import sys
1112
from testrunner import run
1213

1314

14-
EXPECTED_HELP = (
15-
'Command Description',
16-
'---------------------------------------',
17-
'bufsize Get the shell\'s buffer size',
18-
'start_test starts a test',
19-
'end_test ends a test',
20-
'echo prints the input command',
21-
'empty print nothing on command',
22-
'periodic periodically print command',
23-
'app_metadata Returns application metadata',
24-
'pm interact with layered PM subsystem',
25-
'ps Prints information about running threads.',
26-
'reboot Reboot the node',
27-
'version Prints current RIOT_VERSION',
28-
'xfa_test1 xfa test command 1',
29-
'xfa_test2 xfa test command 2'
30-
)
15+
# This is the minimum subset of commands expected to be available on all
16+
# boards. The test will still pass if additional commands are present, as
17+
# `shell_cmds_default` may pull in board specific commands.
18+
EXPECTED_CMDS = {
19+
'bufsize': 'Get the shell\'s buffer size',
20+
'start_test': 'starts a test',
21+
'end_test': 'ends a test',
22+
'echo': 'prints the input command',
23+
'empty': 'print nothing on command',
24+
'periodic': 'periodically print command',
25+
'app_metadata': 'Returns application metadata',
26+
'pm': 'interact with layered PM subsystem',
27+
'ps': 'Prints information about running threads.',
28+
'reboot': 'Reboot the node',
29+
'version': 'Prints current RIOT_VERSION',
30+
'xfa_test1': 'xfa test command 1',
31+
'xfa_test2': 'xfa test command 2',
32+
}
3133

3234
EXPECTED_PS = (
3335
'\tpid | state Q | pri',
@@ -103,7 +105,6 @@
103105

104106
# test default commands
105107
('ps', EXPECTED_PS),
106-
('help', EXPECTED_HELP),
107108

108109
# test commands added to shell_commands_xfa
109110
('xfa_test1', '[XFA TEST 1 OK]'),
@@ -151,6 +152,41 @@ def check_cmd(child, cmd, expected):
151152
child.expect_exact(line)
152153

153154

155+
def check_help(child):
156+
# First: use help_json to get the list of supported commands and do some
157+
# checking for this (e.g. are all expected cmds present)
158+
child.expect(PROMPT)
159+
child.sendline('help_json')
160+
child.expect(r"(\{[^\n\r]*\})\r\n")
161+
cmdlist = json.loads(child.match.group(1))["cmds"]
162+
cmds_expected = set(EXPECTED_CMDS)
163+
cmds_actual = set()
164+
desc_actual = {}
165+
for item in cmdlist:
166+
if item['cmd'] in EXPECTED_CMDS:
167+
assert item['cmd'] in cmds_expected, f"command {item['cmd']} listed twice"
168+
assert item['desc'] == EXPECTED_CMDS[item['cmd']], f"description of {item['cmd']} not expected"
169+
cmds_expected.remove(item['cmd'])
170+
171+
cmds_actual.add(item['cmd'])
172+
desc_actual[item['cmd']] = item['desc']
173+
174+
assert len(cmds_expected) == 0, f"commands {cmds_expected} missing"
175+
176+
# Now: Run regular help and expect the same commands as help_json
177+
child.expect(PROMPT)
178+
child.sendline('help')
179+
child.expect_exact('Command Description\r\n')
180+
child.expect_exact('---------------------------------------\r\n')
181+
while len(cmds_actual) > 0:
182+
child.expect(r"([a-z0-9_-]*)[ \t]*(.*)\r\n")
183+
cmd = child.match.group(1)
184+
desc = child.match.group(2)
185+
assert cmd in cmds_actual, f"Command \"{cmd}\" unexpected or listed twice in help"
186+
cmds_actual.remove(cmd)
187+
assert desc == desc_actual[cmd], f"Description for \"{cmd}\" not matching"
188+
189+
154190
def check_startup(child):
155191
child.sendline(CONTROL_C)
156192
child.expect_exact(PROMPT)
@@ -247,6 +283,8 @@ def testfunc(child):
247283

248284
check_cmd(child, cmd, expected)
249285

286+
check_help(child)
287+
250288
if RIOT_TERMINAL in CLEANTERMS:
251289
for cmd, expected in CMDS_CLEANTERM:
252290
check_cmd(child, cmd, expected)

0 commit comments

Comments
 (0)