blob: 2536a0d3becdf3d0a19fb5eb8a0adcce324f04de [file] [log] [blame]
Johnny Chen9707bb62010-06-25 21:14:08 +00001#!/usr/bin/env python
2
3"""
4A simple testing framework for lldb using python's unit testing framework.
5
6Tests for lldb are written as python scripts which take advantage of the script
7bridging provided by LLDB.framework to interact with lldb core.
8
9A specific naming pattern is followed by the .py script to be recognized as
10a module which implements a test scenario, namely, Test*.py.
11
12To specify the directories where "Test*.py" python test scripts are located,
13you need to pass in a list of directory names. By default, the current
14working directory is searched if nothing is specified on the command line.
Johnny Chen872aee12010-09-16 15:44:23 +000015
16Type:
17
18./dotest.py -h
19
20for available options.
Johnny Chen9707bb62010-06-25 21:14:08 +000021"""
22
Johnny Chen91960d32010-09-08 20:56:16 +000023import os, signal, sys, time
Johnny Chen75e28f92010-08-05 23:42:46 +000024import unittest2
Johnny Chen9707bb62010-06-25 21:14:08 +000025
Johnny Chen877c7e42010-08-07 00:16:07 +000026class _WritelnDecorator(object):
27 """Used to decorate file-like objects with a handy 'writeln' method"""
28 def __init__(self,stream):
29 self.stream = stream
30
31 def __getattr__(self, attr):
32 if attr in ('stream', '__getstate__'):
33 raise AttributeError(attr)
34 return getattr(self.stream,attr)
35
36 def writeln(self, arg=None):
37 if arg:
38 self.write(arg)
39 self.write('\n') # text-mode streams translate to \r\n if needed
40
Johnny Chen9707bb62010-06-25 21:14:08 +000041#
42# Global variables:
43#
44
45# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000046suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000047
Johnny Chen4f93bf12010-12-10 00:51:23 +000048# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000049# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
50# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000051dont_do_python_api_test = False
52
53# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000054just_do_python_api_test = False
55
Johnny Chen82e6b1e2010-12-01 22:47:54 +000056# The blacklist is optional (-b blacklistFile) and allows a central place to skip
57# testclass's and/or testclass.testmethod's.
58blacklist = None
59
60# The dictionary as a result of sourcing blacklistFile.
61blacklistConfig = {}
62
Johnny Chen9fdb0a92010-09-18 00:16:47 +000063# The config file is optional.
64configFile = None
65
Johnny Chend2acdb32010-11-16 22:42:58 +000066# Test suite repeat count. Can be overwritten with '-# count'.
67count = 1
68
Johnny Chenb40056b2010-09-21 00:09:27 +000069# The dictionary as a result of sourcing configFile.
70config = {}
71
Johnny Chen91960d32010-09-08 20:56:16 +000072# Delay startup in order for the debugger to attach.
73delay = False
74
Johnny Chend5362332011-01-29 01:21:04 +000075# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +000076dumpSysPath = False
77
Johnny Chen7d6d8442010-12-03 19:59:35 +000078# By default, failfast is False. Use '-F' to overwrite it.
79failfast = False
80
Johnny Chena224cd12010-11-08 01:21:03 +000081# The filter (testclass.testmethod) used to admit tests into our test suite.
Johnny Chenb62436b2010-10-06 20:40:56 +000082filterspec = None
83
Johnny Chena224cd12010-11-08 01:21:03 +000084# If '-g' is specified, the filterspec is not exclusive. If a test module does
85# not contain testclass.testmethod which matches the filterspec, the whole test
86# module is still admitted into our test suite. fs4all flag defaults to True.
87fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +000088
Johnny Chenaf149a02010-09-16 17:11:30 +000089# Ignore the build search path relative to this script to locate the lldb.py module.
90ignore = False
91
Johnny Chen548aefd2010-10-11 22:25:46 +000092# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen41998192010-10-01 22:59:49 +000093skipLongRunningTest = True
94
Johnny Chen7c52ff12010-09-27 23:29:54 +000095# The regular expression pattern to match against eligible filenames as our test cases.
96regexp = None
97
Johnny Chen548aefd2010-10-11 22:25:46 +000098# By default, tests are executed in place and cleanups are performed afterwards.
99# Use '-r dir' option to relocate the tests and their intermediate files to a
100# different directory and to forgo any cleanups. The directory specified must
101# not exist yet.
102rdir = None
103
Johnny Chen125fc2b2010-10-21 16:55:35 +0000104# By default, recorded session info for errored/failed test are dumped into its
105# own file under a session directory named after the timestamp of the test suite
106# run. Use '-s session-dir-name' to specify a specific dir name.
107sdir_name = None
108
Johnny Chen63c2cba2010-10-29 22:20:36 +0000109# Set this flag if there is any session info dumped during the test run.
110sdir_has_content = False
111
Johnny Chen9707bb62010-06-25 21:14:08 +0000112# Default verbosity is 0.
113verbose = 0
114
115# By default, search from the current working directory.
116testdirs = [ os.getcwd() ]
117
Johnny Chen877c7e42010-08-07 00:16:07 +0000118# Separator string.
119separator = '-' * 70
120
Johnny Chen9707bb62010-06-25 21:14:08 +0000121
122def usage():
123 print """
124Usage: dotest.py [option] [args]
125where options:
126-h : print this help message and exit (also --help)
Johnny Chen012cba12011-01-26 19:07:42 +0000127-A : specify the architecture to launch for the inferior process
128-C : specify the compiler used to build the inferior executable
Johnny Chen50bc6382011-01-29 01:16:52 +0000129-D : dump the Python sys.path variable
Johnny Chen4f93bf12010-12-10 00:51:23 +0000130-a : don't do lldb Python API tests
131 use @python_api_test to decorate a test case as lldb Python API test
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000132+a : just do lldb Python API tests
Johnny Chencc659ad2010-12-10 19:02:23 +0000133 do not specify both '-a' and '+a' at the same time
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000134-b : read a blacklist file specified after this option
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000135-c : read a config file specified after this option
Johnny Chenb40056b2010-09-21 00:09:27 +0000136 (see also lldb-trunk/example/test/usage-config)
Johnny Chen91960d32010-09-08 20:56:16 +0000137-d : delay startup for 10 seconds (in order for the debugger to attach)
Johnny Chen7d6d8442010-12-03 19:59:35 +0000138-F : failfast, stop the test suite on the first error/failure
Johnny Chen46be75d2010-10-11 16:19:48 +0000139-f : specify a filter, which consists of the test class name, a dot, followed by
Johnny Chen1a6e92a2010-11-08 20:17:04 +0000140 the test method, to only admit such test into the test suite
Johnny Chenb62436b2010-10-06 20:40:56 +0000141 e.g., -f 'ClassTypesTestCase.test_with_dwarf_and_python_api'
Johnny Chena224cd12010-11-08 01:21:03 +0000142-g : if specified, the filterspec by -f is not exclusive, i.e., if a test module
143 does not match the filterspec (testclass.testmethod), the whole module is
144 still admitted to the test suite
Johnny Chenaf149a02010-09-16 17:11:30 +0000145-i : ignore (don't bailout) if 'lldb.py' module cannot be located in the build
146 tree relative to this script; use PYTHONPATH to locate the module
Johnny Chen41998192010-10-01 22:59:49 +0000147-l : don't skip long running test
Johnny Chen7c52ff12010-09-27 23:29:54 +0000148-p : specify a regexp filename pattern for inclusion in the test suite
Johnny Chen548aefd2010-10-11 22:25:46 +0000149-r : specify a dir to relocate the tests and their intermediate files to;
150 the directory must not exist before running this test driver;
151 no cleanup of intermediate test files is performed in this case
Johnny Chen125fc2b2010-10-21 16:55:35 +0000152-s : specify the name of the dir created to store the session files of tests
153 with errored or failed status; if not specified, the test driver uses the
154 timestamp as the session dir name
Johnny Chend0c24b22010-08-23 17:10:44 +0000155-t : trace lldb command execution and result
Johnny Chen9707bb62010-06-25 21:14:08 +0000156-v : do verbose mode of unittest framework
Johnny Chene47649c2010-10-07 02:04:14 +0000157-w : insert some wait time (currently 0.5 sec) between consecutive test cases
Johnny Chend2acdb32010-11-16 22:42:58 +0000158-# : Repeat the test suite for a specified number of times
Johnny Chen9707bb62010-06-25 21:14:08 +0000159
160and:
Johnny Chen9656ab22010-10-22 19:00:18 +0000161args : specify a list of directory names to search for test modules named after
162 Test*.py (test discovery)
Johnny Chen9707bb62010-06-25 21:14:08 +0000163 if empty, search from the curret working directory, instead
Johnny Chen58f93922010-06-29 23:10:39 +0000164
Johnny Chen9656ab22010-10-22 19:00:18 +0000165Examples:
166
Johnny Chena224cd12010-11-08 01:21:03 +0000167This is an example of using the -f option to pinpoint to a specfic test class
168and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000169
Johnny Chena224cd12010-11-08 01:21:03 +0000170$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000171----------------------------------------------------------------------
172Collected 1 test
173
174test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
175Test 'frame variable this' when stopped on a class constructor. ... ok
176
177----------------------------------------------------------------------
178Ran 1 test in 1.396s
179
180OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000181
182And this is an example of using the -p option to run a single file (the filename
183matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
184
185$ ./dotest.py -v -p ObjC
186----------------------------------------------------------------------
187Collected 4 tests
188
189test_break_with_dsym (TestObjCMethods.FoundationTestCase)
190Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'. ... ok
191test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
192Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'. ... ok
193test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
194Lookup objective-c data types and evaluate expressions. ... ok
195test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
196Lookup objective-c data types and evaluate expressions. ... ok
197
198----------------------------------------------------------------------
199Ran 4 tests in 16.661s
200
201OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000202
Johnny Chen58f93922010-06-29 23:10:39 +0000203Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000204individual test cases can locate their supporting files correctly. The script
205tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000206relative to this script. See also the '-i' option in the following example.
207
208Finally, this is an example of using the lldb.py module distributed/installed by
209Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
210option to add some delay between two tests. It uses ARCH=x86_64 to specify that
211as the architecture and CC=clang to specify the compiler used for the test run:
212
213$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
214
215Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
216----------------------------------------------------------------------
217Collected 2 tests
218
219test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
220Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
221test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
222Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
223
224----------------------------------------------------------------------
225Ran 2 tests in 5.659s
226
227OK
228
229The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
230notify the directory containing the session logs for test failures or errors.
231In case there is any test failure/error, a similar message is appended at the
232end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000233
234Environment variables related to loggings:
235
236o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
237 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
238
239o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
240 'process.gdb-remote' subsystem with a default option of 'packets' if
241 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000242"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000243 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000244
245
Johnny Chenaf149a02010-09-16 17:11:30 +0000246def parseOptionsAndInitTestdirs():
247 """Initialize the list of directories containing our unittest scripts.
248
249 '-h/--help as the first option prints out usage info and exit the program.
250 """
251
Johnny Chen4f93bf12010-12-10 00:51:23 +0000252 global dont_do_python_api_test
253 global just_do_python_api_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000254 global blacklist
255 global blacklistConfig
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000256 global configFile
Johnny Chend2acdb32010-11-16 22:42:58 +0000257 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000258 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000259 global dumpSysPath
Johnny Chen7d6d8442010-12-03 19:59:35 +0000260 global failfast
Johnny Chenb62436b2010-10-06 20:40:56 +0000261 global filterspec
262 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000263 global ignore
Johnny Chen41998192010-10-01 22:59:49 +0000264 global skipLongRunningTest
Johnny Chen7c52ff12010-09-27 23:29:54 +0000265 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000266 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000267 global sdir_name
Johnny Chenaf149a02010-09-16 17:11:30 +0000268 global verbose
269 global testdirs
270
271 if len(sys.argv) == 1:
272 return
273
274 # Process possible trace and/or verbose flag, among other things.
275 index = 1
Johnny Chence2212c2010-10-07 15:41:55 +0000276 while index < len(sys.argv):
Johnny Chen4f93bf12010-12-10 00:51:23 +0000277 if sys.argv[index].startswith('-') or sys.argv[index].startswith('+'):
278 # We should continue processing...
279 pass
280 else:
Johnny Chenaf149a02010-09-16 17:11:30 +0000281 # End of option processing.
282 break
283
284 if sys.argv[index].find('-h') != -1:
285 usage()
Johnny Chen012cba12011-01-26 19:07:42 +0000286 elif sys.argv[index].startswith('-A'):
287 # Increment by 1 to fetch the ARCH spec.
288 index += 1
289 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
290 usage()
291 os.environ["ARCH"] = sys.argv[index]
292 index += 1
293 elif sys.argv[index].startswith('-C'):
294 # Increment by 1 to fetch the CC spec.
295 index += 1
296 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
297 usage()
298 os.environ["CC"] = sys.argv[index]
299 index += 1
Johnny Chen50bc6382011-01-29 01:16:52 +0000300 elif sys.argv[index].startswith('-D'):
301 dumpSysPath = True
302 index += 1
Johnny Chen4f93bf12010-12-10 00:51:23 +0000303 elif sys.argv[index].startswith('-a'):
304 dont_do_python_api_test = True
305 index += 1
306 elif sys.argv[index].startswith('+a'):
307 just_do_python_api_test = True
308 index += 1
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000309 elif sys.argv[index].startswith('-b'):
310 # Increment by 1 to fetch the blacklist file name option argument.
311 index += 1
312 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
313 usage()
314 blacklistFile = sys.argv[index]
315 if not os.path.isfile(blacklistFile):
316 print "Blacklist file:", blacklistFile, "does not exist!"
317 usage()
318 index += 1
319 # Now read the blacklist contents and assign it to blacklist.
320 execfile(blacklistFile, globals(), blacklistConfig)
321 blacklist = blacklistConfig.get('blacklist')
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000322 elif sys.argv[index].startswith('-c'):
323 # Increment by 1 to fetch the config file name option argument.
324 index += 1
325 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
326 usage()
327 configFile = sys.argv[index]
328 if not os.path.isfile(configFile):
329 print "Config file:", configFile, "does not exist!"
330 usage()
331 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000332 elif sys.argv[index].startswith('-d'):
333 delay = True
334 index += 1
Johnny Chen7d6d8442010-12-03 19:59:35 +0000335 elif sys.argv[index].startswith('-F'):
336 failfast = True
337 index += 1
Johnny Chenb62436b2010-10-06 20:40:56 +0000338 elif sys.argv[index].startswith('-f'):
339 # Increment by 1 to fetch the filter spec.
340 index += 1
341 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
342 usage()
343 filterspec = sys.argv[index]
344 index += 1
345 elif sys.argv[index].startswith('-g'):
Johnny Chena224cd12010-11-08 01:21:03 +0000346 fs4all = False
Johnny Chenb62436b2010-10-06 20:40:56 +0000347 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000348 elif sys.argv[index].startswith('-i'):
349 ignore = True
350 index += 1
Johnny Chen41998192010-10-01 22:59:49 +0000351 elif sys.argv[index].startswith('-l'):
352 skipLongRunningTest = False
353 index += 1
Johnny Chen7c52ff12010-09-27 23:29:54 +0000354 elif sys.argv[index].startswith('-p'):
355 # Increment by 1 to fetch the reg exp pattern argument.
356 index += 1
357 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
358 usage()
359 regexp = sys.argv[index]
360 index += 1
Johnny Chen548aefd2010-10-11 22:25:46 +0000361 elif sys.argv[index].startswith('-r'):
362 # Increment by 1 to fetch the relocated directory argument.
363 index += 1
364 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
365 usage()
366 rdir = os.path.abspath(sys.argv[index])
367 if os.path.exists(rdir):
368 print "Relocated directory:", rdir, "must not exist!"
369 usage()
370 index += 1
Johnny Chen125fc2b2010-10-21 16:55:35 +0000371 elif sys.argv[index].startswith('-s'):
372 # Increment by 1 to fetch the session dir name.
373 index += 1
374 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
375 usage()
376 sdir_name = sys.argv[index]
377 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000378 elif sys.argv[index].startswith('-t'):
379 os.environ["LLDB_COMMAND_TRACE"] = "YES"
380 index += 1
381 elif sys.argv[index].startswith('-v'):
382 verbose = 2
383 index += 1
Johnny Chene47649c2010-10-07 02:04:14 +0000384 elif sys.argv[index].startswith('-w'):
385 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] = 'YES'
386 index += 1
Johnny Chend2acdb32010-11-16 22:42:58 +0000387 elif sys.argv[index].startswith('-#'):
388 # Increment by 1 to fetch the repeat count argument.
389 index += 1
390 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
391 usage()
392 count = int(sys.argv[index])
393 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000394 else:
395 print "Unknown option: ", sys.argv[index]
396 usage()
Johnny Chenaf149a02010-09-16 17:11:30 +0000397
Johnny Chencc659ad2010-12-10 19:02:23 +0000398 # Do not specify both '-a' and '+a' at the same time.
399 if dont_do_python_api_test and just_do_python_api_test:
400 usage()
401
Johnny Chenaf149a02010-09-16 17:11:30 +0000402 # Gather all the dirs passed on the command line.
403 if len(sys.argv) > index:
404 testdirs = map(os.path.abspath, sys.argv[index:])
405
Johnny Chen548aefd2010-10-11 22:25:46 +0000406 # If '-r dir' is specified, the tests should be run under the relocated
407 # directory. Let's copy the testdirs over.
408 if rdir:
409 from shutil import copytree, ignore_patterns
410
411 tmpdirs = []
412 for srcdir in testdirs:
413 dstdir = os.path.join(rdir, os.path.basename(srcdir))
414 # Don't copy the *.pyc and .svn stuffs.
415 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
416 tmpdirs.append(dstdir)
417
418 # This will be our modified testdirs.
419 testdirs = tmpdirs
420
421 # With '-r dir' specified, there's no cleanup of intermediate test files.
422 os.environ["LLDB_DO_CLEANUP"] = 'NO'
423
424 # If testdirs is ['test'], the make directory has already been copied
425 # recursively and is contained within the rdir/test dir. For anything
426 # else, we would need to copy over the make directory and its contents,
427 # so that, os.listdir(rdir) looks like, for example:
428 #
429 # array_types conditional_break make
430 #
431 # where the make directory contains the Makefile.rules file.
432 if len(testdirs) != 1 or os.path.basename(testdirs[0]) != 'test':
433 # Don't copy the .svn stuffs.
434 copytree('make', os.path.join(rdir, 'make'),
435 ignore=ignore_patterns('.svn'))
436
437 #print "testdirs:", testdirs
438
Johnny Chenb40056b2010-09-21 00:09:27 +0000439 # Source the configFile if specified.
440 # The side effect, if any, will be felt from this point on. An example
441 # config file may be these simple two lines:
442 #
443 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
444 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
445 #
446 # which will reassign the two file objects to sys.stderr and sys.stdout,
447 # respectively.
448 #
449 # See also lldb-trunk/example/test/usage-config.
450 global config
451 if configFile:
452 # Pass config (a dictionary) as the locals namespace for side-effect.
453 execfile(configFile, globals(), config)
454 #print "config:", config
455 #print "sys.stderr:", sys.stderr
456 #print "sys.stdout:", sys.stdout
457
Johnny Chenaf149a02010-09-16 17:11:30 +0000458
Johnny Chen9707bb62010-06-25 21:14:08 +0000459def setupSysPath():
460 """Add LLDB.framework/Resources/Python to the search paths for modules."""
461
Johnny Chen548aefd2010-10-11 22:25:46 +0000462 global rdir
463 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000464 global dumpSysPath
Johnny Chen548aefd2010-10-11 22:25:46 +0000465
Johnny Chen9707bb62010-06-25 21:14:08 +0000466 # Get the directory containing the current script.
Johnny Chen0de6ab52011-01-19 02:10:40 +0000467 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
468 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
469 else:
470 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000471 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000472 print "This script expects to reside in lldb's test directory."
473 sys.exit(-1)
474
Johnny Chen548aefd2010-10-11 22:25:46 +0000475 if rdir:
476 # Set up the LLDB_TEST environment variable appropriately, so that the
477 # individual tests can be located relatively.
478 #
479 # See also lldbtest.TestBase.setUpClass(cls).
480 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
481 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
482 else:
483 os.environ["LLDB_TEST"] = rdir
484 else:
485 os.environ["LLDB_TEST"] = scriptPath
Johnny Chen9de4ede2010-08-31 17:42:54 +0000486 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen58f93922010-06-29 23:10:39 +0000487
Johnny Chenaf149a02010-09-16 17:11:30 +0000488 # Append script dir and plugin dir to the sys.path.
489 sys.path.append(scriptPath)
490 sys.path.append(pluginPath)
491
492 global ignore
493
494 # The '-i' option is used to skip looking for lldb.py in the build tree.
495 if ignore:
496 return
497
Johnny Chena1affab2010-07-03 03:41:59 +0000498 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen9707bb62010-06-25 21:14:08 +0000499 dbgPath = os.path.join(base, 'build', 'Debug', 'LLDB.framework',
500 'Resources', 'Python')
Greg Claytond9846b02011-02-14 21:17:06 +0000501 dbgPath2 = os.path.join(base, 'build', 'lldb', 'Build', 'Products',
502 'Debug', 'LLDB.framework', 'Resources', 'Python')
Johnny Chen9707bb62010-06-25 21:14:08 +0000503 relPath = os.path.join(base, 'build', 'Release', 'LLDB.framework',
504 'Resources', 'Python')
Greg Claytond9846b02011-02-14 21:17:06 +0000505 relPath2 = os.path.join(base, 'build', 'lldb', 'Build', 'Products',
506 'Release', 'LLDB.framework', 'Resources', 'Python')
Johnny Chenc202c462010-09-15 18:11:19 +0000507 baiPath = os.path.join(base, 'build', 'BuildAndIntegration',
508 'LLDB.framework', 'Resources', 'Python')
Greg Claytond9846b02011-02-14 21:17:06 +0000509 baiPath2 = os.path.join(base, 'build', 'lldb', 'Build', 'Products',
510 'BuildAndIntegration', 'LLDB.framework', 'Resources', 'Python')
Johnny Chen9707bb62010-06-25 21:14:08 +0000511
512 lldbPath = None
513 if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
514 lldbPath = dbgPath
Greg Claytond9846b02011-02-14 21:17:06 +0000515 elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')):
516 lldbPath = dbgPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000517 elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
518 lldbPath = relPath
Greg Claytond9846b02011-02-14 21:17:06 +0000519 elif os.path.isfile(os.path.join(relPath2, 'lldb.py')):
520 lldbPath = relPath2
Johnny Chenc202c462010-09-15 18:11:19 +0000521 elif os.path.isfile(os.path.join(baiPath, 'lldb.py')):
522 lldbPath = baiPath
Greg Claytond9846b02011-02-14 21:17:06 +0000523 elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')):
524 lldbPath = baiPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000525
526 if not lldbPath:
Johnny Chenc202c462010-09-15 18:11:19 +0000527 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
528 print relPath + ', or ' + baiPath
Johnny Chen9707bb62010-06-25 21:14:08 +0000529 sys.exit(-1)
530
Johnny Chenaf149a02010-09-16 17:11:30 +0000531 # This is to locate the lldb.py module. Insert it right after sys.path[0].
532 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000533 if dumpSysPath:
534 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000535
Johnny Chen9707bb62010-06-25 21:14:08 +0000536
Johnny Chencd0279d2010-09-20 18:07:50 +0000537def doDelay(delta):
538 """Delaying startup for delta-seconds to facilitate debugger attachment."""
539 def alarm_handler(*args):
540 raise Exception("timeout")
541
542 signal.signal(signal.SIGALRM, alarm_handler)
543 signal.alarm(delta)
544 sys.stdout.write("pid=%d\n" % os.getpid())
545 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
546 delta)
547 sys.stdout.flush()
548 try:
549 text = sys.stdin.readline()
550 except:
551 text = ""
552 signal.alarm(0)
553 sys.stdout.write("proceeding...\n")
554 pass
555
556
Johnny Chen9707bb62010-06-25 21:14:08 +0000557def visit(prefix, dir, names):
558 """Visitor function for os.path.walk(path, visit, arg)."""
559
560 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000561 global regexp
Johnny Chenb62436b2010-10-06 20:40:56 +0000562 global filterspec
563 global fs4all
Johnny Chen9707bb62010-06-25 21:14:08 +0000564
565 for name in names:
566 if os.path.isdir(os.path.join(dir, name)):
567 continue
568
569 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000570 # Try to match the regexp pattern, if specified.
571 if regexp:
572 import re
573 if re.search(regexp, name):
574 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
575 pass
576 else:
577 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
578 continue
579
Johnny Chen953864a2010-10-12 21:35:54 +0000580 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000581
582 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000583 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000584 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000585 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000586
587 # Thoroughly check the filterspec against the base module and admit
588 # the (base, filterspec) combination only when it makes sense.
589 if filterspec:
590 # Optimistically set the flag to True.
591 filtered = True
592 module = __import__(base)
593 parts = filterspec.split('.')
594 obj = module
595 for part in parts:
596 try:
597 parent, obj = obj, getattr(obj, part)
598 except AttributeError:
599 # The filterspec has failed.
600 filtered = False
601 break
602 # Forgo this module if the (base, filterspec) combo is invalid
Johnny Chena224cd12010-11-08 01:21:03 +0000603 # and no '-g' option is specified
Johnny Chenb62436b2010-10-06 20:40:56 +0000604 if fs4all and not filtered:
605 continue
606
Johnny Chen953864a2010-10-12 21:35:54 +0000607 # Add either the filtered test case or the entire test class.
Johnny Chenb62436b2010-10-06 20:40:56 +0000608 if filterspec and filtered:
609 suite.addTests(
610 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
611 else:
612 # A simple case of just the module name. Also the failover case
613 # from the filterspec branch when the (base, filterspec) combo
614 # doesn't make sense.
615 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000616
617
Johnny Chencd0279d2010-09-20 18:07:50 +0000618def lldbLoggings():
619 """Check and do lldb loggings if necessary."""
620
621 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
622 # defined. Use ${LLDB_LOG} to specify the log file.
623 ci = lldb.DBG.GetCommandInterpreter()
624 res = lldb.SBCommandReturnObject()
625 if ("LLDB_LOG" in os.environ):
626 if ("LLDB_LOG_OPTION" in os.environ):
627 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
628 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +0000629 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +0000630 ci.HandleCommand(
Johnny Chen58bf3442010-12-02 23:31:02 +0000631 "log enable -T -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +0000632 res)
633 if not res.Succeeded():
634 raise Exception('log enable failed (check LLDB_LOG env variable.')
635 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
636 # Use ${GDB_REMOTE_LOG} to specify the log file.
637 if ("GDB_REMOTE_LOG" in os.environ):
638 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
639 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
640 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +0000641 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +0000642 ci.HandleCommand(
Johnny Chen58bf3442010-12-02 23:31:02 +0000643 "log enable -T -n -f " + os.environ["GDB_REMOTE_LOG"] + " process.gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +0000644 + gdb_remote_log_option,
645 res)
646 if not res.Succeeded():
647 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
648
Johnny Chen067022b2011-01-19 19:31:46 +0000649def getMyCommandLine():
650 import subprocess
651 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
652 lines = ps.split('\n')
653 cmd_line = lines[1]
654 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +0000655
Johnny Chend96b5682010-11-05 17:30:53 +0000656# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000657# #
658# Execution of the test driver starts here #
659# #
Johnny Chend96b5682010-11-05 17:30:53 +0000660# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000661
Johnny Chen9707bb62010-06-25 21:14:08 +0000662#
Johnny Chenaf149a02010-09-16 17:11:30 +0000663# Start the actions by first parsing the options while setting up the test
664# directories, followed by setting up the search paths for lldb utilities;
665# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +0000666#
Johnny Chenaf149a02010-09-16 17:11:30 +0000667parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +0000668setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +0000669
670#
671# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
672#
673if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +0000674 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +0000675
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000676#
Johnny Chen41998192010-10-01 22:59:49 +0000677# If '-l' is specified, do not skip the long running tests.
678if not skipLongRunningTest:
679 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
680
681#
Johnny Chen79723352010-10-12 15:53:22 +0000682# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000683#
Johnny Chen9707bb62010-06-25 21:14:08 +0000684for testdir in testdirs:
685 os.path.walk(testdir, visit, 'Test')
686
Johnny Chenb40056b2010-09-21 00:09:27 +0000687#
Johnny Chen9707bb62010-06-25 21:14:08 +0000688# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +0000689#
Johnny Chencd0279d2010-09-20 18:07:50 +0000690
Johnny Chen1bfbd412010-06-29 19:44:16 +0000691# For the time being, let's bracket the test runner within the
692# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000693import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +0000694# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
695# there's no need to call it a second time.
696#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000697atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +0000698
Johnny Chen909e5a62010-07-01 22:52:57 +0000699# Create a singleton SBDebugger in the lldb namespace.
700lldb.DBG = lldb.SBDebugger.Create()
701
Johnny Chen4f93bf12010-12-10 00:51:23 +0000702# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000703lldb.blacklist = blacklist
704
Johnny Chen4f93bf12010-12-10 00:51:23 +0000705# Put dont/just_do_python_api_test in the lldb namespace, too.
706lldb.dont_do_python_api_test = dont_do_python_api_test
707lldb.just_do_python_api_test = just_do_python_api_test
708
Johnny Chencd0279d2010-09-20 18:07:50 +0000709# Turn on lldb loggings if necessary.
710lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +0000711
Johnny Chen7987ac92010-08-09 20:40:52 +0000712# Install the control-c handler.
713unittest2.signals.installHandler()
714
Johnny Chen125fc2b2010-10-21 16:55:35 +0000715# If sdir_name is not specified through the '-s sdir_name' option, get a
716# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
717# be used when/if we want to dump the session info of individual test cases
718# later on.
Johnny Chence681462010-10-19 00:25:01 +0000719#
720# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chen125fc2b2010-10-21 16:55:35 +0000721if not sdir_name:
722 import datetime
Johnny Chen41fae812010-10-29 22:26:38 +0000723 # The windows platforms don't like ':' in the pathname.
Johnny Chen76bd0102010-10-28 16:32:13 +0000724 timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +0000725 sdir_name = timestamp
726os.environ["LLDB_SESSION_DIRNAME"] = sdir_name
Johnny Chen067022b2011-01-19 19:31:46 +0000727
Johnny Chen47c47c42010-11-09 23:42:00 +0000728sys.stderr.write("\nSession logs for test failures/errors will go into directory '%s'\n" % sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +0000729sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +0000730
Johnny Chenb40056b2010-09-21 00:09:27 +0000731#
732# Invoke the default TextTestRunner to run the test suite, possibly iterating
733# over different configurations.
734#
735
Johnny Chenb40056b2010-09-21 00:09:27 +0000736iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +0000737iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +0000738
739from types import *
740if "archs" in config:
741 archs = config["archs"]
742 if type(archs) is ListType and len(archs) >= 1:
743 iterArchs = True
744if "compilers" in config:
745 compilers = config["compilers"]
746 if type(compilers) is ListType and len(compilers) >= 1:
747 iterCompilers = True
748
Johnny Chen953864a2010-10-12 21:35:54 +0000749# Make a shallow copy of sys.path, we need to manipulate the search paths later.
750# This is only necessary if we are relocated and with different configurations.
751if rdir and (iterArchs or iterCompilers):
752 old_sys_path = sys.path[:]
753 old_stderr = sys.stderr
754 old_stdout = sys.stdout
755 new_stderr = None
756 new_stdout = None
757
Johnny Chend96b5682010-11-05 17:30:53 +0000758# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +0000759for ia in range(len(archs) if iterArchs else 1):
760 archConfig = ""
761 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +0000762 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +0000763 archConfig = "arch=%s" % archs[ia]
764 for ic in range(len(compilers) if iterCompilers else 1):
765 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +0000766 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +0000767 configString = "%s compiler=%s" % (archConfig, compilers[ic])
768 else:
769 configString = archConfig
770
Johnny Chenb40056b2010-09-21 00:09:27 +0000771 if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +0000772 # If we specified a relocated directory to run the test suite, do
773 # the extra housekeeping to copy the testdirs to a configStringified
774 # directory and to update sys.path before invoking the test runner.
775 # The purpose is to separate the configuration-specific directories
776 # from each other.
777 if rdir:
778 from string import maketrans
779 from shutil import copytree, ignore_patterns
780
781 # Translate ' ' to '-' for dir name.
782 tbl = maketrans(' ', '-')
783 configPostfix = configString.translate(tbl)
784 newrdir = "%s.%s" % (rdir, configPostfix)
785
786 # Copy the tree to a new directory with postfix name configPostfix.
787 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
788
789 # Check whether we need to split stderr/stdout into configuration
790 # specific files.
791 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
792 if new_stderr:
793 new_stderr.close()
794 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
795 sys.stderr = new_stderr
Johnny Chen4b6630e2010-10-12 21:50:36 +0000796 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
Johnny Chen953864a2010-10-12 21:35:54 +0000797 if new_stdout:
798 new_stdout.close()
799 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
800 sys.stdout = new_stdout
801
802 # Update the LLDB_TEST environment variable to reflect new top
803 # level test directory.
804 #
805 # See also lldbtest.TestBase.setUpClass(cls).
806 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
807 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
808 else:
809 os.environ["LLDB_TEST"] = newrdir
810
811 # And update the Python search paths for modules.
812 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
813
814 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +0000815 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +0000816
817 #print "sys.stderr name is", sys.stderr.name
818 #print "sys.stdout name is", sys.stdout.name
819
820 # First, write out the number of collected test cases.
821 sys.stderr.write(separator + "\n")
822 sys.stderr.write("Collected %d test%s\n\n"
823 % (suite.countTestCases(),
824 suite.countTestCases() != 1 and "s" or ""))
825
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000826 class LLDBTestResult(unittest2.TextTestResult):
827 """
Johnny Chen26be4532010-11-09 23:56:14 +0000828 Enforce a singleton pattern to allow introspection of test progress.
829
830 Overwrite addError(), addFailure(), and addExpectedFailure() methods
831 to enable each test instance to track its failure/error status. It
832 is used in the LLDB test framework to emit detailed trace messages
833 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000834 """
835 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +0000836 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000837
838 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +0000839 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +0000840 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000841 super(LLDBTestResult, self).__init__(*args)
842 LLDBTestResult.__singleton__ = self
843 # Now put this singleton into the lldb module namespace.
844 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +0000845 # Computes the format string for displaying the counter.
846 global suite
847 counterWidth = len(str(suite.countTestCases()))
848 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +0000849 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +0000850 # This counts from 1 .. suite.countTestCases().
851 self.counter = 0
852
Johnny Chenc87fd492011-01-05 22:50:11 +0000853 def getDescription(self, test):
854 doc_first_line = test.shortDescription()
855 if self.descriptions and doc_first_line:
856 return '\n'.join((str(test), self.indentation + doc_first_line))
857 else:
858 return str(test)
859
Johnny Chen810042e2011-01-05 20:24:11 +0000860 def startTest(self, test):
861 self.counter += 1
862 if self.showAll:
863 self.stream.write(self.fmt % self.counter)
864 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000865
Johnny Chence681462010-10-19 00:25:01 +0000866 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +0000867 global sdir_has_content
868 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +0000869 super(LLDBTestResult, self).addError(test, err)
870 method = getattr(test, "markError", None)
871 if method:
872 method()
873
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000874 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +0000875 global sdir_has_content
876 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000877 super(LLDBTestResult, self).addFailure(test, err)
878 method = getattr(test, "markFailure", None)
879 if method:
880 method()
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000881
Johnny Chendd2bb2c2010-11-03 18:17:03 +0000882 def addExpectedFailure(self, test, err):
883 global sdir_has_content
884 sdir_has_content = True
885 super(LLDBTestResult, self).addExpectedFailure(test, err)
886 method = getattr(test, "markExpectedFailure", None)
887 if method:
888 method()
889
Johnny Chen26be4532010-11-09 23:56:14 +0000890 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +0000891 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +0000892 result = unittest2.TextTestRunner(stream=sys.stderr,
893 verbosity=verbose,
894 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +0000895 resultclass=LLDBTestResult).run(suite)
896 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +0000897 # We are invoking the same test suite more than once. In this case,
898 # mark __ignore_singleton__ flag as True so the signleton pattern is
899 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +0000900 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +0000901 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +0000902 result = unittest2.TextTestRunner(stream=sys.stderr,
903 verbosity=verbose,
904 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +0000905 resultclass=LLDBTestResult).run(suite)
Johnny Chenb40056b2010-09-21 00:09:27 +0000906
Johnny Chen1bfbd412010-06-29 19:44:16 +0000907
Johnny Chen63c2cba2010-10-29 22:20:36 +0000908if sdir_has_content:
Johnny Chen47c47c42010-11-09 23:42:00 +0000909 sys.stderr.write("Session logs for test failures/errors can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +0000910
Johnny Chencd0279d2010-09-20 18:07:50 +0000911# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
912# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +0000913if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
914 import subprocess
915 print "Terminating Test suite..."
916 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
917
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000918# Exiting.
919sys.exit(not result.wasSuccessful)