Skip to content

Commit d3202a5

Browse files
committed
[lldb] Parse the dotest output to determine the most appropriate result code
Currently we look for keywords in the dotest.py output to determine the lit result code. This binary approach of a keyword being present works for PASS and FAIL, where having at least one test pass or fail respectively results in that exit code. Things are more complicated for tests that neither passed or failed, but report a combination of (un)expected failures, skips or unresolved tests. This patch changes the logic to parse the number of tests with a particular result from the dotest.py output. For tests that did not PASS or FAIL, we now report the lit result code for the one that occurred the most. For example, if we had a test with 3 skips and 4 expected failures, we report the test as XFAIL. We're still mapping multiple tests to one result code, so some loss of information is inevitable. Differential revision: https://reviews.llvm.org/D127258
1 parent 26053cd commit d3202a5

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

lldb/test/API/lldbtest.py

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
from __future__ import absolute_import
22
import os
3-
import tempfile
4-
import subprocess
5-
import sys
6-
import platform
3+
import re
4+
import operator
75

86
import lit.Test
97
import lit.TestRunner
@@ -88,20 +86,36 @@ def execute(self, test, litConfig):
8886
if timeoutInfo:
8987
return lit.Test.TIMEOUT, output
9088

91-
if exitCode:
92-
if 'XPASS:' in out or 'XPASS:' in err:
93-
return lit.Test.XPASS, output
94-
95-
# Otherwise this is just a failure.
96-
return lit.Test.FAIL, output
97-
98-
has_unsupported_tests = 'UNSUPPORTED:' in out or 'UNSUPPORTED:' in err
99-
has_passing_tests = 'PASS:' in out or 'PASS:' in err
100-
if has_unsupported_tests and not has_passing_tests:
101-
return lit.Test.UNSUPPORTED, output
89+
# Parse the dotest output from stderr.
90+
result_regex = r"\((\d+) passes, (\d+) failures, (\d+) errors, (\d+) skipped, (\d+) expected failures, (\d+) unexpected successes\)"
91+
results = re.search(result_regex, err)
10292

103-
passing_test_line = 'RESULT: PASSED'
104-
if passing_test_line not in out and passing_test_line not in err:
93+
# If parsing fails mark this test as unresolved.
94+
if not results:
10595
return lit.Test.UNRESOLVED, output
10696

107-
return lit.Test.PASS, output
97+
passes = int(results.group(1))
98+
failures = int(results.group(2))
99+
errors = int(results.group(3))
100+
skipped = int(results.group(4))
101+
expected_failures = int(results.group(5))
102+
unexpected_successes = int(results.group(6))
103+
104+
if exitCode:
105+
# Mark this test as FAIL if at least one test failed.
106+
if failures > 0:
107+
return lit.Test.FAIL, output
108+
lit_results = [(failures, lit.Test.FAIL),
109+
(errors, lit.Test.UNRESOLVED),
110+
(unexpected_successes, lit.Test.XPASS)]
111+
else:
112+
# Mark this test as PASS if at least one test passed.
113+
if passes > 0:
114+
return lit.Test.PASS, output
115+
lit_results = [(passes, lit.Test.PASS),
116+
(skipped, lit.Test.UNSUPPORTED),
117+
(expected_failures, lit.Test.XFAIL)]
118+
119+
# Return the lit result code with the maximum occurrence. Only look at
120+
# the first element and rely on the original order to break ties.
121+
return max(lit_results, key=operator.itemgetter(0))[1], output

0 commit comments

Comments
 (0)