OLD | NEW |
1 """ | 1 """ |
2 TestCommon.py: a testing framework for commands and scripts | 2 TestCommon.py: a testing framework for commands and scripts |
3 with commonly useful error handling | 3 with commonly useful error handling |
4 | 4 |
5 The TestCommon module provides a simple, high-level interface for writing | 5 The TestCommon module provides a simple, high-level interface for writing |
6 tests of executable commands and scripts, especially commands and scripts | 6 tests of executable commands and scripts, especially commands and scripts |
7 that interact with the file system. All methods throw exceptions and | 7 that interact with the file system. All methods throw exceptions and |
8 exit on failure, with useful error messages. This makes a number of | 8 exit on failure, with useful error messages. This makes a number of |
9 explicit checks unnecessary, making the test scripts themselves simpler | 9 explicit checks unnecessary, making the test scripts themselves simpler |
10 to write and easier to read. | 10 to write and easier to read. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 # SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF | 81 # SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF |
82 # THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 82 # THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
83 # DAMAGE. | 83 # DAMAGE. |
84 # | 84 # |
85 # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT | 85 # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
86 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | 86 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
87 # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, | 87 # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, |
88 # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, | 88 # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, |
89 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 89 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
90 | 90 |
| 91 from __future__ import print_function |
| 92 |
91 __author__ = "Steven Knight <knight at baldmt dot com>" | 93 __author__ = "Steven Knight <knight at baldmt dot com>" |
92 __revision__ = "TestCommon.py 0.37.D001 2010/01/11 16:55:50 knight" | 94 __revision__ = "TestCommon.py 0.37.D001 2010/01/11 16:55:50 knight" |
93 __version__ = "0.37" | 95 __version__ = "0.37" |
94 | 96 |
95 import copy | 97 import copy |
96 import os | 98 import os |
97 import os.path | 99 import os.path |
98 import stat | 100 import stat |
99 import string | |
100 import sys | 101 import sys |
101 import types | 102 try: |
102 import UserList | 103 from UserList import UserList |
| 104 except ImportError: |
| 105 from collections import UserList |
103 | 106 |
104 from TestCmd import * | 107 from TestCmd import * |
105 from TestCmd import __all__ | 108 from TestCmd import __all__ |
106 | 109 |
107 __all__.extend([ 'TestCommon', | 110 __all__.extend([ 'TestCommon', |
108 'exe_suffix', | 111 'exe_suffix', |
109 'obj_suffix', | 112 'obj_suffix', |
110 'shobj_prefix', | 113 'shobj_prefix', |
111 'shobj_suffix', | 114 'shobj_suffix', |
112 'lib_prefix', | 115 'lib_prefix', |
(...skipping 18 matching lines...) Expand all Loading... |
131 exe_suffix = '.exe' | 134 exe_suffix = '.exe' |
132 obj_suffix = '.o' | 135 obj_suffix = '.o' |
133 shobj_suffix = '.os' | 136 shobj_suffix = '.os' |
134 shobj_prefix = '' | 137 shobj_prefix = '' |
135 lib_prefix = 'lib' | 138 lib_prefix = 'lib' |
136 lib_suffix = '.a' | 139 lib_suffix = '.a' |
137 dll_prefix = '' | 140 dll_prefix = '' |
138 dll_suffix = '.dll' | 141 dll_suffix = '.dll' |
139 module_prefix = '' | 142 module_prefix = '' |
140 module_suffix = '.dll' | 143 module_suffix = '.dll' |
141 elif string.find(sys.platform, 'irix') != -1: | 144 elif sys.platform.find('irix') != -1: |
142 exe_suffix = '' | 145 exe_suffix = '' |
143 obj_suffix = '.o' | 146 obj_suffix = '.o' |
144 shobj_suffix = '.o' | 147 shobj_suffix = '.o' |
145 shobj_prefix = '' | 148 shobj_prefix = '' |
146 lib_prefix = 'lib' | 149 lib_prefix = 'lib' |
147 lib_suffix = '.a' | 150 lib_suffix = '.a' |
148 dll_prefix = 'lib' | 151 dll_prefix = 'lib' |
149 dll_suffix = '.so' | 152 dll_suffix = '.so' |
150 module_prefix = 'lib' | 153 module_prefix = 'lib' |
151 module_prefix = '.so' | 154 module_prefix = '.so' |
152 elif string.find(sys.platform, 'darwin') != -1: | 155 elif sys.platform.find('darwin') != -1: |
153 exe_suffix = '' | 156 exe_suffix = '' |
154 obj_suffix = '.o' | 157 obj_suffix = '.o' |
155 shobj_suffix = '.os' | 158 shobj_suffix = '.os' |
156 shobj_prefix = '' | 159 shobj_prefix = '' |
157 lib_prefix = 'lib' | 160 lib_prefix = 'lib' |
158 lib_suffix = '.a' | 161 lib_suffix = '.a' |
159 dll_prefix = 'lib' | 162 dll_prefix = 'lib' |
160 dll_suffix = '.dylib' | 163 dll_suffix = '.dylib' |
161 module_prefix = '' | 164 module_prefix = '' |
162 module_suffix = '.so' | 165 module_suffix = '.so' |
163 elif string.find(sys.platform, 'sunos') != -1: | 166 elif sys.platform.find('sunos') != -1: |
164 exe_suffix = '' | 167 exe_suffix = '' |
165 obj_suffix = '.o' | 168 obj_suffix = '.o' |
166 shobj_suffix = '.os' | 169 shobj_suffix = '.os' |
167 shobj_prefix = 'so_' | 170 shobj_prefix = 'so_' |
168 lib_prefix = 'lib' | 171 lib_prefix = 'lib' |
169 lib_suffix = '.a' | 172 lib_suffix = '.a' |
170 dll_prefix = 'lib' | 173 dll_prefix = 'lib' |
171 dll_suffix = '.dylib' | 174 dll_suffix = '.dylib' |
172 module_prefix = '' | 175 module_prefix = '' |
173 module_suffix = '.so' | 176 module_suffix = '.so' |
174 else: | 177 else: |
175 exe_suffix = '' | 178 exe_suffix = '' |
176 obj_suffix = '.o' | 179 obj_suffix = '.o' |
177 shobj_suffix = '.os' | 180 shobj_suffix = '.os' |
178 shobj_prefix = '' | 181 shobj_prefix = '' |
179 lib_prefix = 'lib' | 182 lib_prefix = 'lib' |
180 lib_suffix = '.a' | 183 lib_suffix = '.a' |
181 dll_prefix = 'lib' | 184 dll_prefix = 'lib' |
182 dll_suffix = '.so' | 185 dll_suffix = '.so' |
183 module_prefix = 'lib' | 186 module_prefix = 'lib' |
184 module_suffix = '.so' | 187 module_suffix = '.so' |
185 | 188 |
186 def is_List(e): | 189 def is_List(e): |
187 return type(e) is types.ListType \ | 190 return type(e) is list \ |
188 or isinstance(e, UserList.UserList) | 191 or isinstance(e, UserList) |
189 | 192 |
190 def is_writable(f): | 193 def is_writable(f): |
191 mode = os.stat(f)[stat.ST_MODE] | 194 mode = os.stat(f)[stat.ST_MODE] |
192 return mode & stat.S_IWUSR | 195 return mode & stat.S_IWUSR |
193 | 196 |
194 def separate_files(flist): | 197 def separate_files(flist): |
195 existing = [] | 198 existing = [] |
196 missing = [] | 199 missing = [] |
197 for f in flist: | 200 for f in flist: |
198 if os.path.exists(f): | 201 if os.path.exists(f): |
(...skipping 21 matching lines...) Expand all Loading... |
220 # | 223 # |
221 # $test->subdir('subdir', ...); | 224 # $test->subdir('subdir', ...); |
222 # | 225 # |
223 # $test->copy('src_file', 'dst_file'); | 226 # $test->copy('src_file', 'dst_file'); |
224 | 227 |
225 def __init__(self, **kw): | 228 def __init__(self, **kw): |
226 """Initialize a new TestCommon instance. This involves just | 229 """Initialize a new TestCommon instance. This involves just |
227 calling the base class initialization, and then changing directory | 230 calling the base class initialization, and then changing directory |
228 to the workdir. | 231 to the workdir. |
229 """ | 232 """ |
230 apply(TestCmd.__init__, [self], kw) | 233 TestCmd.__init__(self, **kw) |
231 os.chdir(self.workdir) | 234 os.chdir(self.workdir) |
232 | 235 |
233 def must_be_writable(self, *files): | 236 def must_be_writable(self, *files): |
234 """Ensures that the specified file(s) exist and are writable. | 237 """Ensures that the specified file(s) exist and are writable. |
235 An individual file can be specified as a list of directory names, | 238 An individual file can be specified as a list of directory names, |
236 in which case the pathname will be constructed by concatenating | 239 in which case the pathname will be constructed by concatenating |
237 them. Exits FAILED if any of the files does not exist or is | 240 them. Exits FAILED if any of the files does not exist or is |
238 not writable. | 241 not writable. |
239 """ | 242 """ |
240 files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) | 243 files = map((lambda x: os.path.join(*x) if is_List(x) else x), files) |
241 existing, missing = separate_files(files) | 244 existing, missing = separate_files(files) |
242 unwritable = filter(lambda x, iw=is_writable: not iw(x), existing) | 245 unwritable = [x for x in existing if not is_writable(x)] |
243 if missing: | 246 if missing: |
244 print "Missing files: `%s'" % string.join(missing, "', `") | 247 print("Missing files: `%s'" % "', `".join(missing)) |
245 if unwritable: | 248 if unwritable: |
246 print "Unwritable files: `%s'" % string.join(unwritable, "', `") | 249 print("Unwritable files: `%s'" % "', `".join(unwritable)) |
247 self.fail_test(missing + unwritable) | 250 self.fail_test(missing + unwritable) |
248 | 251 |
249 def must_contain(self, file, required, mode = 'rb'): | 252 def must_contain(self, file, required, mode = 'r'): |
250 """Ensures that the specified file contains the required text. | 253 """Ensures that the specified file contains the required text. |
251 """ | 254 """ |
252 file_contents = self.read(file, mode) | 255 file_contents = self.read(file, mode) |
253 contains = (string.find(file_contents, required) != -1) | 256 contains = (file_contents.find(required) != -1) |
254 if not contains: | 257 if not contains: |
255 print "File `%s' does not contain required string." % file | 258 print("File `%s' does not contain required string." % file) |
256 print self.banner('Required string ') | 259 print(self.banner('Required string ')) |
257 print required | 260 print(required) |
258 print self.banner('%s contents ' % file) | 261 print(self.banner('%s contents ' % file)) |
259 print file_contents | 262 print(file_contents) |
260 self.fail_test(not contains) | 263 self.fail_test(not contains) |
261 | 264 |
262 def must_contain_all_lines(self, output, lines, title=None, find=None): | 265 def must_contain_all_lines(self, output, lines, title=None, find=None): |
263 """Ensures that the specified output string (first argument) | 266 """Ensures that the specified output string (first argument) |
264 contains all of the specified lines (second argument). | 267 contains all of the specified lines (second argument). |
265 | 268 |
266 An optional third argument can be used to describe the type | 269 An optional third argument can be used to describe the type |
267 of output being searched, and only shows up in failure output. | 270 of output being searched, and only shows up in failure output. |
268 | 271 |
269 An optional fourth argument can be used to supply a different | 272 An optional fourth argument can be used to supply a different |
270 function, of the form "find(line, output), to use when searching | 273 function, of the form "find(line, output), to use when searching |
271 for lines in the output. | 274 for lines in the output. |
272 """ | 275 """ |
273 if find is None: | 276 if find is None: |
274 find = lambda o, l: string.find(o, l) != -1 | 277 find = lambda o, l: o.find(l) != -1 |
275 missing = [] | 278 missing = [] |
276 for line in lines: | 279 for line in lines: |
277 if not find(output, line): | 280 if not find(output, line): |
278 missing.append(line) | 281 missing.append(line) |
279 | 282 |
280 if missing: | 283 if missing: |
281 if title is None: | 284 if title is None: |
282 title = 'output' | 285 title = 'output' |
283 sys.stdout.write("Missing expected lines from %s:\n" % title) | 286 sys.stdout.write("Missing expected lines from %s:\n" % title) |
284 for line in missing: | 287 for line in missing: |
285 sys.stdout.write(' ' + repr(line) + '\n') | 288 sys.stdout.write(' ' + repr(line) + '\n') |
286 sys.stdout.write(self.banner(title + ' ')) | 289 sys.stdout.write(self.banner(title + ' ')) |
287 sys.stdout.write(output) | 290 sys.stdout.write(output) |
288 self.fail_test() | 291 self.fail_test() |
289 | 292 |
290 def must_contain_any_line(self, output, lines, title=None, find=None): | 293 def must_contain_any_line(self, output, lines, title=None, find=None): |
291 """Ensures that the specified output string (first argument) | 294 """Ensures that the specified output string (first argument) |
292 contains at least one of the specified lines (second argument). | 295 contains at least one of the specified lines (second argument). |
293 | 296 |
294 An optional third argument can be used to describe the type | 297 An optional third argument can be used to describe the type |
295 of output being searched, and only shows up in failure output. | 298 of output being searched, and only shows up in failure output. |
296 | 299 |
297 An optional fourth argument can be used to supply a different | 300 An optional fourth argument can be used to supply a different |
298 function, of the form "find(line, output), to use when searching | 301 function, of the form "find(line, output), to use when searching |
299 for lines in the output. | 302 for lines in the output. |
300 """ | 303 """ |
301 if find is None: | 304 if find is None: |
302 find = lambda o, l: string.find(o, l) != -1 | 305 find = lambda o, l: o.find(l) != -1 |
303 for line in lines: | 306 for line in lines: |
304 if find(output, line): | 307 if find(output, line): |
305 return | 308 return |
306 | 309 |
307 if title is None: | 310 if title is None: |
308 title = 'output' | 311 title = 'output' |
309 sys.stdout.write("Missing any expected line from %s:\n" % title) | 312 sys.stdout.write("Missing any expected line from %s:\n" % title) |
310 for line in lines: | 313 for line in lines: |
311 sys.stdout.write(' ' + repr(line) + '\n') | 314 sys.stdout.write(' ' + repr(line) + '\n') |
312 sys.stdout.write(self.banner(title + ' ')) | 315 sys.stdout.write(self.banner(title + ' ')) |
313 sys.stdout.write(output) | 316 sys.stdout.write(output) |
314 self.fail_test() | 317 self.fail_test() |
315 | 318 |
316 def must_contain_lines(self, lines, output, title=None): | 319 def must_contain_lines(self, lines, output, title=None): |
317 # Deprecated; retain for backwards compatibility. | 320 # Deprecated; retain for backwards compatibility. |
318 return self.must_contain_all_lines(output, lines, title) | 321 return self.must_contain_all_lines(output, lines, title) |
319 | 322 |
320 def must_exist(self, *files): | 323 def must_exist(self, *files): |
321 """Ensures that the specified file(s) must exist. An individual | 324 """Ensures that the specified file(s) must exist. An individual |
322 file be specified as a list of directory names, in which case the | 325 file be specified as a list of directory names, in which case the |
323 pathname will be constructed by concatenating them. Exits FAILED | 326 pathname will be constructed by concatenating them. Exits FAILED |
324 if any of the files does not exist. | 327 if any of the files does not exist. |
325 """ | 328 """ |
326 files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) | 329 files = map((lambda x: os.path.join(*x) if is_List(x) else x), files) |
327 missing = filter(lambda x: not os.path.exists(x), files) | 330 missing = [f for f in files if not os.path.exists(f)] |
328 if missing: | 331 if missing: |
329 print "Missing files: `%s'" % string.join(missing, "', `") | 332 print("Missing files: `%s'" % "', `".join(missing)) |
330 self.fail_test(missing) | 333 self.fail_test(missing) |
331 | 334 |
332 def must_match(self, file, expect, mode = 'rb'): | 335 def must_match(self, file, expect, mode = 'r'): |
333 """Matches the contents of the specified file (first argument) | 336 """Matches the contents of the specified file (first argument) |
334 against the expected contents (second argument). The expected | 337 against the expected contents (second argument). The expected |
335 contents are a list of lines or a string which will be split | 338 contents are a list of lines or a string which will be split |
336 on newlines. | 339 on newlines. |
337 """ | 340 """ |
338 file_contents = self.read(file, mode) | 341 file_contents = self.read(file, mode) |
339 try: | 342 try: |
340 self.fail_test(not self.match(file_contents, expect)) | 343 self.fail_test(not self.match(file_contents, expect)) |
341 except KeyboardInterrupt: | 344 except KeyboardInterrupt: |
342 raise | 345 raise |
343 except: | 346 except: |
344 print "Unexpected contents of `%s'" % file | 347 print("Unexpected contents of `%s'" % file) |
345 self.diff(expect, file_contents, 'contents ') | 348 self.diff(expect, file_contents, 'contents ') |
346 raise | 349 raise |
347 | 350 |
348 def must_not_contain(self, file, banned, mode = 'rb'): | 351 def must_not_contain(self, file, banned, mode = 'r'): |
349 """Ensures that the specified file doesn't contain the banned text. | 352 """Ensures that the specified file doesn't contain the banned text. |
350 """ | 353 """ |
351 file_contents = self.read(file, mode) | 354 file_contents = self.read(file, mode) |
352 contains = (string.find(file_contents, banned) != -1) | 355 contains = (file_contents.find(banned) != -1) |
353 if contains: | 356 if contains: |
354 print "File `%s' contains banned string." % file | 357 print("File `%s' contains banned string." % file) |
355 print self.banner('Banned string ') | 358 print(self.banner('Banned string ')) |
356 print banned | 359 print(banned) |
357 print self.banner('%s contents ' % file) | 360 print(self.banner('%s contents ' % file)) |
358 print file_contents | 361 print(file_contents) |
359 self.fail_test(contains) | 362 self.fail_test(contains) |
360 | 363 |
361 def must_not_contain_any_line(self, output, lines, title=None, find=None): | 364 def must_not_contain_any_line(self, output, lines, title=None, find=None): |
362 """Ensures that the specified output string (first argument) | 365 """Ensures that the specified output string (first argument) |
363 does not contain any of the specified lines (second argument). | 366 does not contain any of the specified lines (second argument). |
364 | 367 |
365 An optional third argument can be used to describe the type | 368 An optional third argument can be used to describe the type |
366 of output being searched, and only shows up in failure output. | 369 of output being searched, and only shows up in failure output. |
367 | 370 |
368 An optional fourth argument can be used to supply a different | 371 An optional fourth argument can be used to supply a different |
369 function, of the form "find(line, output), to use when searching | 372 function, of the form "find(line, output), to use when searching |
370 for lines in the output. | 373 for lines in the output. |
371 """ | 374 """ |
372 if find is None: | 375 if find is None: |
373 find = lambda o, l: string.find(o, l) != -1 | 376 find = lambda o, l: o.find(l) != -1 |
374 unexpected = [] | 377 unexpected = [] |
375 for line in lines: | 378 for line in lines: |
376 if find(output, line): | 379 if find(output, line): |
377 unexpected.append(line) | 380 unexpected.append(line) |
378 | 381 |
379 if unexpected: | 382 if unexpected: |
380 if title is None: | 383 if title is None: |
381 title = 'output' | 384 title = 'output' |
382 sys.stdout.write("Unexpected lines in %s:\n" % title) | 385 sys.stdout.write("Unexpected lines in %s:\n" % title) |
383 for line in unexpected: | 386 for line in unexpected: |
384 sys.stdout.write(' ' + repr(line) + '\n') | 387 sys.stdout.write(' ' + repr(line) + '\n') |
385 sys.stdout.write(self.banner(title + ' ')) | 388 sys.stdout.write(self.banner(title + ' ')) |
386 sys.stdout.write(output) | 389 sys.stdout.write(output) |
387 self.fail_test() | 390 self.fail_test() |
388 | 391 |
389 def must_not_contain_lines(self, lines, output, title=None): | 392 def must_not_contain_lines(self, lines, output, title=None): |
390 return self.must_not_contain_any_line(output, lines, title) | 393 return self.must_not_contain_any_line(output, lines, title) |
391 | 394 |
392 def must_not_exist(self, *files): | 395 def must_not_exist(self, *files): |
393 """Ensures that the specified file(s) must not exist. | 396 """Ensures that the specified file(s) must not exist. |
394 An individual file be specified as a list of directory names, in | 397 An individual file be specified as a list of directory names, in |
395 which case the pathname will be constructed by concatenating them. | 398 which case the pathname will be constructed by concatenating them. |
396 Exits FAILED if any of the files exists. | 399 Exits FAILED if any of the files exists. |
397 """ | 400 """ |
398 files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) | 401 files = map((lambda x: os.path.join(*x) if is_List(x) else x), files) |
399 existing = filter(os.path.exists, files) | 402 existing = [f for f in files if os.path.exists(f)] |
400 if existing: | 403 if existing: |
401 print "Unexpected files exist: `%s'" % string.join(existing, "', `") | 404 print("Unexpected files exist: `%s'" % "', `".join(existing)) |
402 self.fail_test(existing) | 405 self.fail_test(existing) |
403 | 406 |
404 def must_not_be_writable(self, *files): | 407 def must_not_be_writable(self, *files): |
405 """Ensures that the specified file(s) exist and are not writable. | 408 """Ensures that the specified file(s) exist and are not writable. |
406 An individual file can be specified as a list of directory names, | 409 An individual file can be specified as a list of directory names, |
407 in which case the pathname will be constructed by concatenating | 410 in which case the pathname will be constructed by concatenating |
408 them. Exits FAILED if any of the files does not exist or is | 411 them. Exits FAILED if any of the files does not exist or is |
409 writable. | 412 writable. |
410 """ | 413 """ |
411 files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) | 414 files = map((lambda x: os.path.join(*x) if is_List(x) else x), files) |
412 existing, missing = separate_files(files) | 415 existing, missing = separate_files(files) |
413 writable = filter(is_writable, existing) | 416 writable = [x for x in existing if is_writable(x)] |
414 if missing: | 417 if missing: |
415 print "Missing files: `%s'" % string.join(missing, "', `") | 418 print("Missing files: `%s'" % "', `".join(missing)) |
416 if writable: | 419 if writable: |
417 print "Writable files: `%s'" % string.join(writable, "', `") | 420 print("Writable files: `%s'" % "', `".join(writable)) |
418 self.fail_test(missing + writable) | 421 self.fail_test(missing + writable) |
419 | 422 |
420 def _complete(self, actual_stdout, expected_stdout, | 423 def _complete(self, actual_stdout, expected_stdout, |
421 actual_stderr, expected_stderr, status, match): | 424 actual_stderr, expected_stderr, status, match): |
422 """ | 425 """ |
423 Post-processes running a subcommand, checking for failure | 426 Post-processes running a subcommand, checking for failure |
424 status and displaying output appropriately. | 427 status and displaying output appropriately. |
425 """ | 428 """ |
426 if _failed(self, status): | 429 if _failed(self, status): |
427 expect = '' | 430 expect = '' |
428 if status != 0: | 431 if status != 0: |
429 expect = " (expected %s)" % str(status) | 432 expect = " (expected %s)" % str(status) |
430 print "%s returned %s%s" % (self.program, str(_status(self)), expect
) | 433 print("%s returned %s%s" % (self.program, str(_status(self)), expect
)) |
431 print self.banner('STDOUT ') | 434 print(self.banner('STDOUT ')) |
432 print actual_stdout | 435 print(actual_stdout) |
433 print self.banner('STDERR ') | 436 print(self.banner('STDERR ')) |
434 print actual_stderr | 437 print(actual_stderr) |
435 self.fail_test() | 438 self.fail_test() |
436 if not expected_stdout is None and not match(actual_stdout, expected_std
out): | 439 if not expected_stdout is None and not match(actual_stdout, expected_std
out): |
437 self.diff(expected_stdout, actual_stdout, 'STDOUT ') | 440 self.diff(expected_stdout, actual_stdout, 'STDOUT ') |
438 if actual_stderr: | 441 if actual_stderr: |
439 print self.banner('STDERR ') | 442 print(self.banner('STDERR ')) |
440 print actual_stderr | 443 print(actual_stderr) |
441 self.fail_test() | 444 self.fail_test() |
442 if not expected_stderr is None and not match(actual_stderr, expected_std
err): | 445 if not expected_stderr is None and not match(actual_stderr, expected_std
err): |
443 print self.banner('STDOUT ') | 446 print(self.banner('STDOUT ')) |
444 print actual_stdout | 447 print(actual_stdout) |
445 self.diff(expected_stderr, actual_stderr, 'STDERR ') | 448 self.diff(expected_stderr, actual_stderr, 'STDERR ') |
446 self.fail_test() | 449 self.fail_test() |
447 | 450 |
448 def start(self, program = None, | 451 def start(self, program = None, |
449 interpreter = None, | 452 interpreter = None, |
450 arguments = None, | 453 arguments = None, |
451 universal_newlines = None, | 454 universal_newlines = None, |
452 **kw): | 455 **kw): |
453 """ | 456 """ |
454 Starts a program or script for the test environment. | 457 Starts a program or script for the test environment. |
455 | 458 |
456 This handles the "options" keyword argument and exceptions. | 459 This handles the "options" keyword argument and exceptions. |
457 """ | 460 """ |
458 options = kw.pop('options', None) | 461 options = kw.pop('options', None) |
459 if options: | 462 if options: |
460 if arguments is None: | 463 if arguments is None: |
461 arguments = options | 464 arguments = options |
462 else: | 465 else: |
463 arguments = options + " " + arguments | 466 arguments = options + " " + arguments |
464 | 467 |
465 try: | 468 try: |
466 return apply(TestCmd.start, | 469 return TestCmd.start(self, program, interpreter, arguments, |
467 (self, program, interpreter, arguments, universal_newli
nes), | 470 universal_newlines, **kw) |
468 kw) | |
469 except KeyboardInterrupt: | 471 except KeyboardInterrupt: |
470 raise | 472 raise |
471 except Exception, e: | 473 except Exception as e: |
472 print self.banner('STDOUT ') | 474 print(self.banner('STDOUT ')) |
473 try: | 475 try: |
474 print self.stdout() | 476 print(self.stdout()) |
475 except IndexError: | 477 except IndexError: |
476 pass | 478 pass |
477 print self.banner('STDERR ') | 479 print(self.banner('STDERR ')) |
478 try: | 480 try: |
479 print self.stderr() | 481 print(self.stderr()) |
480 except IndexError: | 482 except IndexError: |
481 pass | 483 pass |
482 cmd_args = self.command_args(program, interpreter, arguments) | 484 cmd_args = self.command_args(program, interpreter, arguments) |
483 sys.stderr.write('Exception trying to execute: %s\n' % cmd_args) | 485 sys.stderr.write('Exception trying to execute: %s\n' % cmd_args) |
484 raise e | 486 raise e |
485 | 487 |
486 def finish(self, popen, stdout = None, stderr = '', status = 0, **kw): | 488 def finish(self, popen, stdout = None, stderr = '', status = 0, **kw): |
487 """ | 489 """ |
488 Finishes and waits for the process being run under control of | 490 Finishes and waits for the process being run under control of |
489 the specified popen argument. Additional arguments are similar | 491 the specified popen argument. Additional arguments are similar |
490 to those of the run() method: | 492 to those of the run() method: |
491 | 493 |
492 stdout The expected standard output from | 494 stdout The expected standard output from |
493 the command. A value of None means | 495 the command. A value of None means |
494 don't test standard output. | 496 don't test standard output. |
495 | 497 |
496 stderr The expected error output from | 498 stderr The expected error output from |
497 the command. A value of None means | 499 the command. A value of None means |
498 don't test error output. | 500 don't test error output. |
499 | 501 |
500 status The expected exit status from the | 502 status The expected exit status from the |
501 command. A value of None means don't | 503 command. A value of None means don't |
502 test exit status. | 504 test exit status. |
503 """ | 505 """ |
504 apply(TestCmd.finish, (self, popen,), kw) | 506 TestCmd.finish(self, popen, **kw) |
505 match = kw.get('match', self.match) | 507 match = kw.get('match', self.match) |
506 self._complete(self.stdout(), stdout, | 508 self._complete(self.stdout(), stdout, |
507 self.stderr(), stderr, status, match) | 509 self.stderr(), stderr, status, match) |
508 | 510 |
509 def run(self, options = None, arguments = None, | 511 def run(self, options = None, arguments = None, |
510 stdout = None, stderr = '', status = 0, **kw): | 512 stdout = None, stderr = '', status = 0, **kw): |
511 """Runs the program under test, checking that the test succeeded. | 513 """Runs the program under test, checking that the test succeeded. |
512 | 514 |
513 The arguments are the same as the base TestCmd.run() method, | 515 The arguments are the same as the base TestCmd.run() method, |
514 with the addition of: | 516 with the addition of: |
(...skipping 17 matching lines...) Expand all Loading... |
532 not test standard output (stdout = None), and expects that error | 534 not test standard output (stdout = None), and expects that error |
533 output is empty (stderr = ""). | 535 output is empty (stderr = ""). |
534 """ | 536 """ |
535 if options: | 537 if options: |
536 if arguments is None: | 538 if arguments is None: |
537 arguments = options | 539 arguments = options |
538 else: | 540 else: |
539 arguments = options + " " + arguments | 541 arguments = options + " " + arguments |
540 kw['arguments'] = arguments | 542 kw['arguments'] = arguments |
541 match = kw.pop('match', self.match) | 543 match = kw.pop('match', self.match) |
542 apply(TestCmd.run, [self], kw) | 544 TestCmd.run(self, **kw) |
543 self._complete(self.stdout(), stdout, | 545 self._complete(self.stdout(), stdout, |
544 self.stderr(), stderr, status, match) | 546 self.stderr(), stderr, status, match) |
545 | 547 |
546 def skip_test(self, message="Skipping test.\n"): | 548 def skip_test(self, message="Skipping test.\n"): |
547 """Skips a test. | 549 """Skips a test. |
548 | 550 |
549 Proper test-skipping behavior is dependent on the external | 551 Proper test-skipping behavior is dependent on the external |
550 TESTCOMMON_PASS_SKIPS environment variable. If set, we treat | 552 TESTCOMMON_PASS_SKIPS environment variable. If set, we treat |
551 the skip as a PASS (exit 0), and otherwise treat it as NO RESULT. | 553 the skip as a PASS (exit 0), and otherwise treat it as NO RESULT. |
552 In either case, we print the specified message as an indication | 554 In either case, we print the specified message as an indication |
(...skipping 20 matching lines...) Expand all Loading... |
573 else: | 575 else: |
574 # We're under the development directory for this change, | 576 # We're under the development directory for this change, |
575 # so this is an Aegis invocation; pass the test (exit 0). | 577 # so this is an Aegis invocation; pass the test (exit 0). |
576 self.pass_test() | 578 self.pass_test() |
577 | 579 |
578 # Local Variables: | 580 # Local Variables: |
579 # tab-width:4 | 581 # tab-width:4 |
580 # indent-tabs-mode:nil | 582 # indent-tabs-mode:nil |
581 # End: | 583 # End: |
582 # vim: set expandtab tabstop=4 shiftwidth=4: | 584 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |