Skip to content

Commit 343403f

Browse files
matttbekuba-moo
authored andcommitted
contest: vmksft-p: support parsing nested tests
Some selftests are executing a lot of different subtests. On the other hand, the kselftests infrastructure only supports TAP 13 format, which doesn't support subtests. If one subtest fails, the whole selftest is marked as failed. It starts to be really annoying when one subtest starts to be unstable and marked as "ignored": all the other subtests are then ignored as well. It is then important to parse subtests to be able to track each subtest individually, and not loose info about the others when one is unstable. A workaround to support subtests with TAP 13 is to embed the subtests result in the comments. This is what is done with MPTCP selftests. That's not specific to MPTCP, because TC and others written in C and using kselftest_harness.h are also doing that. The output to parse looks like that: TAP version 13 1..1 # timeout set to (...) # selftests: (...) # <comment> # (...) # <comment> # # TAP version 13 | # 1..X | # ok 1 (...) | # nok 2 (...) | <== That's what we want to parse # ok 3 (...) # SKIP | # (...) | # ok X (...) | ok 1 selftests: {target}: {prog} The last line is not parsed, this is handled by the existing code, also checking for VM crash, etc. This means that in case of crash, the kselftest will be marked as 'fail', but subtests (if any) will be parsed: the ones previous to the crash are still valid. It might help to know what was OK, and what was not. Because it will increase the number of tests, there is a new option, disabled by default, to enable this feature or not per target, where it makes sense: [ksft] nested_tests = on Signed-off-by: Matthieu Baerts (NGI0) <[email protected]>
1 parent a51de88 commit 343403f

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

contest/remote/vmksft-p.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
boot_timeout=45
4848
[ksft]
4949
targets=net
50+
nested_tests=off / on
5051
5152
5253
Expected:
@@ -73,6 +74,42 @@ def get_prog_list(vm, target):
7374
return [e.split(":")[1].strip() for e in targets]
7475

7576

77+
def _parse_nested_tests(full_run):
78+
tests = []
79+
nested_tests = False
80+
81+
result_re = re.compile(r"(not )?ok (\d+)( -)? ([^#]*[^ ])( # )?([^ ].*)?$")
82+
83+
for line in full_run.split('\n'):
84+
# nested subtests support: we parse the comments from 'TAP version'
85+
if nested_tests:
86+
if line.startswith("# "):
87+
line = line[2:]
88+
else:
89+
nested_tests = False
90+
elif line.startswith("# TAP version "):
91+
nested_tests = True
92+
continue
93+
94+
if not nested_tests:
95+
continue
96+
97+
if line.startswith("ok "):
98+
result = "pass"
99+
elif line.startswith("not ok "):
100+
result = "fail"
101+
else:
102+
continue
103+
104+
v = result_re.match(line).groups()
105+
name = v[3]
106+
if len(v) > 5 and v[5]:
107+
if v[5].lower().startswith('skip') and result == "pass":
108+
result = "skip"
109+
tests.append((name, result))
110+
111+
return tests
112+
76113
def _vm_thread(config, results_path, thr_id, in_queue, out_queue):
77114
target = config.get('ksft', 'target')
78115
vm = None
@@ -136,6 +173,14 @@ def _vm_thread(config, results_path, thr_id, in_queue, out_queue):
136173
out_queue.put({'prog': prog, 'test': test_name, 'file_name': file_name,
137174
'result': result, 'time': (t2 - t1).seconds})
138175

176+
if config.getboolean('ksft', 'nested_tests', fallback=False):
177+
# this will only parse nested tests inside the TAP comments
178+
tests = _parse_nested_tests(vm.log_out)
179+
180+
for r_name, r_result in tests:
181+
out_queue.put({'prog': prog, 'test': namify(r_name),
182+
'file_name': file_name, 'result': r_result})
183+
139184
if vm.fail_state:
140185
print(f"INFO: thr-{thr_id} VM kernel crashed, destroying it")
141186
vm.stop()
@@ -214,7 +259,8 @@ def test(binfo, rinfo, cbarg):
214259
cases = []
215260
while not out_queue.empty():
216261
r = out_queue.get()
217-
cbarg.prev_runtime[r["prog"]] = r["time"]
262+
if 'time' in r:
263+
cbarg.prev_runtime[r["prog"]] = r["time"]
218264
cases.append({'test': r['test'], 'group': grp_name, 'result': r["result"],
219265
'link': link + '/' + r['file_name']})
220266
if not in_queue.empty():

0 commit comments

Comments
 (0)