Skip to content

Commit b0245e3

Browse files
authored
Fix lit / taef integration (#7870)
* TAEF writes everything to stdout, so don't worry about separate out/err streams * Use a single regex match for the Summary string * TAEF's exit code doesn't reliably indicate skipped tests, so look for these explicitly in the summary * Always return the output with the result - so that `--show-all` will work correctly and we can see the output from tests regardless of their final result.
1 parent fa3fe95 commit b0245e3

File tree

1 file changed

+70
-40
lines changed

1 file changed

+70
-40
lines changed

utils/lit/lit/formats/taef.py

Lines changed: 70 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
from __future__ import absolute_import
22
import os
3-
import sys
43
import signal
54
import subprocess
5+
import re
66

77
import lit.Test
8-
import lit.TestRunner
98
import lit.util
109
from .base import TestFormat
1110

1211
# TAEF must be run with custom command line string and shell=True
1312
# because of the way it manually processes quoted arguments in a
1413
# non-standard way.
14+
15+
1516
def executeCommandForTaef(command, cwd=None, env=None):
16-
p = subprocess.Popen(command, cwd=cwd,
17-
shell=True,
18-
stdin=subprocess.PIPE,
19-
stdout=subprocess.PIPE,
20-
stderr=subprocess.PIPE,
21-
env=env,
22-
# Close extra file handles on UNIX (on Windows this cannot be done while
23-
# also redirecting input). Taef only run on windows.
24-
close_fds=False)
25-
out,err = p.communicate()
17+
p = subprocess.Popen(
18+
command,
19+
cwd=cwd,
20+
shell=True,
21+
stdin=subprocess.PIPE,
22+
stdout=subprocess.PIPE,
23+
# TAEF doesn't seem to really use stderr, so we just
24+
# deal with stdout
25+
stderr=subprocess.STDOUT,
26+
env=env,
27+
# Close extra file handles on UNIX (on Windows this cannot be done while
28+
# also redirecting input). Taef only run on windows.
29+
close_fds=False,
30+
)
31+
out, _ = p.communicate()
2632
exitCode = p.wait()
2733

2834
# Detect Ctrl-C in subprocess.
@@ -31,9 +37,9 @@ def executeCommandForTaef(command, cwd=None, env=None):
3137

3238
# Ensure the resulting output is always of string type.
3339
out = lit.util.convert_string(out)
34-
err = lit.util.convert_string(err)
3540

36-
return out, err, exitCode
41+
return out, exitCode
42+
3743

3844
class TaefTest(TestFormat):
3945
def __init__(self, te_path, test_dll, test_path, select_filter, extra_params):
@@ -63,21 +69,27 @@ def getTaefTests(self, dll_path, litConfig, localConfig):
6369

6470
if litConfig.debug:
6571
litConfig.note('searching taef test in %r' % dll_path)
66-
72+
6773
cmd = [self.te, dll_path, "/list", "/select:", self.select_filter]
6874

6975
try:
70-
lines,err,exitCode = executeCommandForTaef(cmd)
76+
lines, exitCode = executeCommandForTaef(cmd)
7177
# this is for windows
7278
lines = lines.replace('\r', '')
7379
lines = lines.split('\n')
7480

7581
except:
76-
litConfig.error("unable to discover taef tests in %r, using %s. exeption encountered." % (dll_path, self.te))
82+
litConfig.error(
83+
"unable to discover taef tests in %r, using %s. exception encountered."
84+
% (dll_path, self.te)
85+
)
7786
raise StopIteration
7887

7988
if exitCode:
80-
litConfig.error("unable to discover taef tests in %r, using %s. error: %s." % (dll_path, self.te, err))
89+
litConfig.error(
90+
"unable to discover taef tests in %r, using %s. error: %s."
91+
% (dll_path, self.te, lines)
92+
)
8193
raise StopIteration
8294

8395
for ln in lines:
@@ -118,7 +130,7 @@ def getTestsInDirectory(self, testSuite, path_in_suite,
118130
def execute(self, test, litConfig):
119131
test_dll = test.getFilePath()
120132

121-
testPath,testName = os.path.split(test.getSourcePath())
133+
testPath, testName = os.path.split(test.getSourcePath())
122134

123135
select_filter = str.format("@Name='{}'", testName)
124136

@@ -141,30 +153,48 @@ def execute(self, test, litConfig):
141153
if litConfig.noExecute:
142154
return lit.Test.PASS, ''
143155

144-
out, err, exitCode = executeCommandForTaef(
145-
cmd, env = test.config.environment)
156+
out, exitCode = executeCommandForTaef(cmd, env=test.config.environment)
146157

147-
if exitCode:
148-
skipped = 'Failed=0, Blocked=0, Not Run=0, Skipped=1'
149-
if skipped in out:
150-
return lit.Test.UNSUPPORTED, ''
158+
return getTestResult(out, exitCode), out
159+
160+
161+
def getTestResult(out, exitCode):
162+
unselected = "The selection criteria did not match any tests."
163+
if unselected in out:
164+
return lit.Test.UNSUPPORTED
165+
166+
# TAEF's exit code cannot reliably indicate if a test was skipped, failed or
167+
# passed. The summary string instead is used to determine this.
168+
169+
# Example summary string:
170+
# Summary: Total=1, Passed=1, Failed=0, Blocked=0, Not Run=0, Skipped=0
171+
regex = r"Summary: Total=\d+, Passed=(\d+), Failed=(\d+), Blocked=(\d+), Not Run=(\d+), Skipped=(\d+)"
172+
173+
# Get the last occurance of the summary in the output
174+
match = None
175+
for m in re.finditer(regex, out):
176+
match = m
177+
178+
if not match:
179+
return lit.Test.UNRESOLVED
151180

152-
unselected = 'The selection criteria did not match any tests.'
153-
if unselected in out:
154-
return lit.Test.UNSUPPORTED, ''
181+
passed = int(match.group(1))
182+
failed = int(match.group(2))
183+
blocked = int(match.group(3))
184+
not_run = int(match.group(4))
185+
skipped = int(match.group(5))
155186

156-
return lit.Test.FAIL, out + err
187+
# TAEF docs claim that exitCode should be non-zero if a test is skipped,
188+
# but that doesn't seem to be the case with at least v10.88k. So we
189+
# explicitly look for skipped in the summary - and any other non-zero exit
190+
# codes after this are some kind of failure.
191+
if skipped > 0 or blocked > 0 or not_run > 0:
192+
return lit.Test.UNSUPPORTED
157193

158-
summary = 'Summary: Total='
159-
if summary not in out:
160-
msg = ('Unable to find %r in taef output:\n\n%s%s' %
161-
(summary, out, err))
162-
return lit.Test.UNRESOLVED, msg
163-
no_fail = 'Failed=0, Blocked=0, Not Run=0, Skipped=0'
164-
if no_fail not in out == -1:
165-
msg = ('Unable to find %r in taef output:\n\n%s%s' %
166-
(no_fail, out, err))
167-
return lit.Test.UNRESOLVED, msg
194+
if exitCode or failed > 0:
195+
return lit.Test.FAIL
168196

169-
return lit.Test.PASS,''
197+
if passed > 0:
198+
return lit.Test.PASS
170199

200+
return lit.Test.UNRESOLVED

0 commit comments

Comments
 (0)