26
26
import subprocess
27
27
from xml .etree .ElementTree import ElementTree
28
28
from xml .etree .ElementTree import ParseError
29
+ from xml .sax .saxutils import quoteattr
29
30
30
31
31
32
def main (argv = sys .argv [1 :]):
@@ -74,66 +75,93 @@ def main(argv=sys.argv[1:]):
74
75
args .result_file ,
75
76
'The test did not generate a result file.'
76
77
)
77
- with open (args .result_file , 'w' ) as f :
78
- f .write (failure_result_file )
78
+ with open (args .result_file , 'w' ) as h :
79
+ h .write (failure_result_file )
79
80
80
- print ("-- run_test.py: invoke following command in '%s':\n - %s" %
81
+ print ("-- run_test.py: invoking following command in '%s':\n - %s" %
81
82
(os .getcwd (), ' ' .join (args .command )))
82
83
84
+ # collect output / exception to generate more detailed result file
85
+ # if the command fails to generate it
86
+ output = ''
83
87
h = None
84
88
if args .output_file :
85
89
h = open (args .output_file , 'wb' )
86
90
try :
87
91
proc = subprocess .Popen (args .command , stdout = subprocess .PIPE , stderr = subprocess .STDOUT )
88
92
for line in proc .stdout :
89
- print (line .decode (), end = '' )
93
+ decoded_line = line .decode ()
94
+ print (decoded_line , end = '' )
95
+ output += decoded_line
90
96
if h :
91
97
h .write (line )
98
+ proc .wait ()
92
99
rc = proc .returncode
100
+ print ('-- run_test.py: return code' , rc , file = sys .stderr if rc else sys .stdout )
101
+ except Exception as e :
102
+ print ('-- run_test.py: invocation failed:' , str (e ), file = sys .stderr )
103
+ output += str (e )
104
+ rc = 1
93
105
finally :
94
106
if h :
95
107
h .close ()
96
108
97
- print ("-- run_test.py: verify result file '%s'" % args .result_file )
98
-
99
- if os .path .exists (args .result_file ):
100
- # if result file exists ensure that it contains valid xml
101
- # unit test suites are not good about screening out
102
- # illegal unicode characters
103
- tree = None
104
- try :
105
- tree = ElementTree (None , args .result_file )
106
- except ParseError as e :
107
- modified = _tidy_xml (args .result_file )
108
- if not modified :
109
- print ("Invalid XML in result file '%s': %s" %
110
- (args .result_file , str (e )), file = sys .stderr )
111
- else :
112
- try :
113
- tree = ElementTree (None , args .result_file )
114
- except ParseError as e :
115
- print ("Invalid XML in result file '%s' "
116
- "(even after trying to tidy it): %s" %
117
- (args .result_file , str (e )), file = sys .stderr )
118
-
119
- if not tree :
120
- # set error code when result file is not parsable
121
- rc = 1
122
- else :
123
- # set error code when result file contains errors or failures
124
- root = tree .getroot ()
125
- num_errors = int (root .attrib .get ('errors' , 0 ))
126
- num_failures = int (root .attrib .get ('failures' , 0 ))
127
- if num_errors or num_failures :
128
- rc = 1
129
-
130
- elif not rc and args .generate_result_on_success :
109
+ if not rc and args .generate_result_on_success :
131
110
# generate result file with one passed test
132
111
# if it was expected that no result file was generated
133
112
# and the command returned with code zero
113
+ print ("-- run_test.py: generate result file '%s' with successful test" % args .result_file )
134
114
success_result_file = _generate_result (args .result_file )
135
- with open (args .result_file , 'w' ) as f :
136
- f .write (success_result_file )
115
+ with open (args .result_file , 'w' ) as h :
116
+ h .write (success_result_file )
117
+
118
+ elif os .path .exists (args .result_file ):
119
+ # check if content of result file has actually changed
120
+ with open (args .result_file , 'r' ) as h :
121
+ not_changed = h .read () == failure_result_file
122
+
123
+ if not_changed :
124
+ print ("-- run_test.py: generate result file '%s' with failed test" % args .result_file ,
125
+ file = sys .stderr )
126
+ # regenerate result file to include output / exception of the invoked command
127
+ failure_result_file = _generate_result (
128
+ args .result_file ,
129
+ 'The test did not generate a result file:\n \n ' + output
130
+ )
131
+ with open (args .result_file , 'w' ) as h :
132
+ h .write (failure_result_file )
133
+
134
+ else :
135
+ print ("-- run_test.py: verify result file '%s'" % args .result_file )
136
+ # if result file exists ensure that it contains valid xml
137
+ # unit test suites are not good about screening out
138
+ # illegal unicode characters
139
+ tree = None
140
+ try :
141
+ tree = ElementTree (None , args .result_file )
142
+ except ParseError as e :
143
+ modified = _tidy_xml (args .result_file )
144
+ if not modified :
145
+ print ("Invalid XML in result file '%s': %s" %
146
+ (args .result_file , str (e )), file = sys .stderr )
147
+ else :
148
+ try :
149
+ tree = ElementTree (None , args .result_file )
150
+ except ParseError as e :
151
+ print ("Invalid XML in result file '%s' "
152
+ "(even after trying to tidy it): %s" %
153
+ (args .result_file , str (e )), file = sys .stderr )
154
+
155
+ if not tree :
156
+ # set error code when result file is not parsable
157
+ rc = 1
158
+ else :
159
+ # set error code when result file contains errors or failures
160
+ root = tree .getroot ()
161
+ num_errors = int (root .attrib .get ('errors' , 0 ))
162
+ num_failures = int (root .attrib .get ('failures' , 0 ))
163
+ if num_errors or num_failures :
164
+ rc = 1
137
165
138
166
# ensure that a result file exists at the end
139
167
if not rc and not os .path .exists (args .result_file ):
@@ -147,24 +175,22 @@ def main(argv=sys.argv[1:]):
147
175
def _generate_result (result_file , failure_message = None ):
148
176
pkgname = os .path .basename (os .path .dirname (result_file ))
149
177
testname = os .path .splitext (os .path .basename (result_file ))[0 ]
150
- name = '%s__ %s' % (pkgname , testname )
151
- failure_message = '<failure message="%s" type="" />' % failure_message \
178
+ name = '%s. %s' % (pkgname , testname )
179
+ failure_message = '<failure message=%s />' % quoteattr ( failure_message ) \
152
180
if failure_message else ''
153
181
return '''<?xml version="1.0" encoding="UTF-8"?>
154
182
<testsuite tests="1" failures="%d" time="1" errors="0" name="%s">
155
- <testcase name="%s " status="run" time="1" classname="Results ">
183
+ <testcase name="missing_result " status="run" time="1" classname="%s ">
156
184
%s
157
185
</testcase>
158
- </testsuite>''' % (1 if failure_message else 0 ,
159
- name ,
160
- name ,
161
- failure_message )
186
+ </testsuite>\n ''' % \
187
+ (1 if failure_message else 0 , name , name , failure_message )
162
188
163
189
164
190
def _tidy_xml (filename ):
165
191
assert os .path .isfile (filename )
166
192
167
- # try reading utf-8 firth then iso
193
+ # try reading utf-8 first then iso
168
194
# this is ugly but the files in question do not declare a unicode type
169
195
data = None
170
196
for encoding in ['utf-8' , 'iso8859-1' ]:
@@ -200,8 +226,8 @@ def _tidy_xml(filename):
200
226
for match in SAFE_XML_REGEX .finditer (data ):
201
227
data = data [:match .start ()] + '?' + data [match .end ():]
202
228
203
- with open (filename , 'w' ) as f :
204
- f .write (data )
229
+ with open (filename , 'w' ) as h :
230
+ h .write (data )
205
231
return True
206
232
207
233
0 commit comments