11from __future__ import absolute_import
22import os
3- import sys
43import signal
54import subprocess
5+ import re
66
77import lit .Test
8- import lit .TestRunner
98import lit .util
109from .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+
1516def 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
3844class 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