Skip to content

Commit

Permalink
[tests] Always parse LTP output
Browse files Browse the repository at this point in the history
Some LTP tests (e.g. `pwrite02`) do not exit with non-zero code when
failing.

Signed-off-by: Paweł Marczewski <pawel@invisiblethingslab.com>
  • Loading branch information
pwmarcz authored and dimakuv committed Sep 14, 2021
1 parent 0012183 commit 3c3b522
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions LibOS/shim/test/ltp/runltp_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,12 @@ async def execute(self):
returncode = await self._run_cmd()

must_pass = self.cfgsection.getintset('must-pass')
if must_pass is not None:
self._parse_test_output(must_pass)
elif returncode != 0:
if not must_pass and returncode != 0:
raise Fail('returncode={}'.format(returncode))
# Parse output regardless of whether `must_pass` is specified: unfortunately some tests
# do not exit with non-zero code when failing, because they rely on `MAP_SHARED` (which
# we do not support correctly) for collecting test results.
self._parse_test_output(must_pass)

except AbnormalTestResult as result:
result.apply_to(self)
Expand All @@ -325,19 +327,17 @@ async def execute(self):
self.success()

def _parse_test_output(self, must_pass):
'''Parse the output
'''Parse and process test output'''

if must_pass is None:
must_pass = set()

This is normally done only for a test that has non-empty ``must-pass``
config directive.
'''
notfound = must_pass.copy()
passed = set()
failed = set()
skipped = set()
dontcare = set()

# on empty must_pass, it is always needed
maybe_unneeded_must_pass = bool(must_pass)
unspecified = set()

subtest = 0
for line in self.stdout.split('\n'):
Expand Down Expand Up @@ -366,20 +366,21 @@ def _parse_test_output(self, must_pass):
notfound.remove(subtest)
except KeyError:
# subtest is not in must-pass
maybe_unneeded_must_pass = False
unspecified.add(subtest)

if 'TPASS' in line or 'PASS:' in line:
if subtest in must_pass:
# On empty must_pass, assume all tests must pass
if subtest in must_pass or not must_pass:
passed.add(subtest)
else:
dontcare.add(subtest)
continue

if any(t in line for t in (
'TFAIL', 'FAIL:', 'TCONF', 'CONF:', 'TBROK', 'BROK:')):
if subtest in must_pass:
# On empty must_pass, assume all tests must pass
if subtest in must_pass or not must_pass:
failed.add(subtest)
maybe_unneeded_must_pass = False
else:
skipped.add(subtest)
continue
Expand All @@ -395,6 +396,7 @@ def _parse_test_output(self, must_pass):
skipped=', '.join(str(i) for i in sorted(skipped)),
notfound=', '.join(str(i) for i in sorted(notfound)),
dontcare=', '.join(str(i) for i in sorted(dontcare)),
unspecified=', '.join(str(i) for i in sorted(unspecified)),
)

stat = (
Expand All @@ -403,6 +405,7 @@ def _parse_test_output(self, must_pass):
'passed=[{passed}] '
'dontcare=[{dontcare}] '
'skipped=[{skipped}] '
'unspecified=[{unspecified}] '
'returncode={returncode}'
).format(**self.props)

Expand All @@ -414,7 +417,7 @@ def _parse_test_output(self, must_pass):
raise Skip('binary without subtests, see stdout '
'(returncode={returncode})'.format(**self.props))

if maybe_unneeded_must_pass and not notfound:
if must_pass and not notfound and not unspecified:
# all subtests passed and must-pass specified exactly all subtests
raise Error(
'must-pass is unneeded, remove it from config ({})'.format(stat)
Expand Down

0 comments on commit 3c3b522

Please sign in to comment.