blob: 86df4307768f30c76d87a54fd2a9757740d6c560 [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 Chen2891bb02011-09-16 01:04:26 +000024import subprocess
Johnny Chen75e28f92010-08-05 23:42:46 +000025import unittest2
Johnny Chen9707bb62010-06-25 21:14:08 +000026
Johnny Chen26901c82011-03-11 19:47:23 +000027def is_exe(fpath):
Johnny Chenf2c7b282011-04-26 23:10:51 +000028 """Returns true if fpath is an executable."""
Johnny Chen26901c82011-03-11 19:47:23 +000029 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
30
Johnny Chen26901c82011-03-11 19:47:23 +000031def which(program):
Johnny Chenf2c7b282011-04-26 23:10:51 +000032 """Returns the full path to a program; None otherwise."""
Johnny Chen26901c82011-03-11 19:47:23 +000033 fpath, fname = os.path.split(program)
34 if fpath:
35 if is_exe(program):
36 return program
37 else:
38 for path in os.environ["PATH"].split(os.pathsep):
39 exe_file = os.path.join(path, program)
40 if is_exe(exe_file):
41 return exe_file
42 return None
43
Johnny Chen877c7e42010-08-07 00:16:07 +000044class _WritelnDecorator(object):
45 """Used to decorate file-like objects with a handy 'writeln' method"""
46 def __init__(self,stream):
47 self.stream = stream
48
49 def __getattr__(self, attr):
50 if attr in ('stream', '__getstate__'):
51 raise AttributeError(attr)
52 return getattr(self.stream,attr)
53
54 def writeln(self, arg=None):
55 if arg:
56 self.write(arg)
57 self.write('\n') # text-mode streams translate to \r\n if needed
58
Johnny Chen9707bb62010-06-25 21:14:08 +000059#
60# Global variables:
61#
62
63# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000064suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000065
Johnny Chen4f93bf12010-12-10 00:51:23 +000066# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000067# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
68# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000069dont_do_python_api_test = False
70
71# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000072just_do_python_api_test = False
73
Johnny Chen82ccf402011-07-30 01:39:58 +000074# By default, benchmarks tests are not run.
75just_do_benchmarks_test = False
76
Johnny Chen82e6b1e2010-12-01 22:47:54 +000077# The blacklist is optional (-b blacklistFile) and allows a central place to skip
78# testclass's and/or testclass.testmethod's.
79blacklist = None
80
81# The dictionary as a result of sourcing blacklistFile.
82blacklistConfig = {}
83
Johnny Chen9fdb0a92010-09-18 00:16:47 +000084# The config file is optional.
85configFile = None
86
Johnny Chend2acdb32010-11-16 22:42:58 +000087# Test suite repeat count. Can be overwritten with '-# count'.
88count = 1
89
Johnny Chenb40056b2010-09-21 00:09:27 +000090# The dictionary as a result of sourcing configFile.
91config = {}
92
Johnny Chen1a4d5e72011-03-04 01:35:22 +000093# The 'archs' and 'compilers' can be specified via either command line or configFile,
94# with the command line overriding the configFile. When specified, they should be
95# of the list type. For example, "-A x86_64^i386" => archs=['x86_64', 'i386'] and
96# "-C gcc^clang" => compilers=['gcc', 'clang'].
97archs = None
98compilers = None
99
Johnny Chen91960d32010-09-08 20:56:16 +0000100# Delay startup in order for the debugger to attach.
101delay = False
102
Johnny Chend5362332011-01-29 01:21:04 +0000103# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000104dumpSysPath = False
105
Johnny Chene00c9302011-10-10 22:03:44 +0000106# Full path of the benchmark executable, as specified by the '-e' option.
107bmExecutable = None
108# The breakpoint specification of bmExecutable, as specified by the '-x' option.
109bmBreakpointSpec = None
Johnny Chen5f2ed172011-10-20 18:43:28 +0000110# The benchamrk iteration count, as specified by the '-y' option.
111bmIterationCount = -1
Johnny Chene00c9302011-10-10 22:03:44 +0000112
Johnny Chen7d6d8442010-12-03 19:59:35 +0000113# By default, failfast is False. Use '-F' to overwrite it.
114failfast = False
115
Johnny Chenc5fa0052011-07-29 22:54:56 +0000116# The filters (testclass.testmethod) used to admit tests into our test suite.
117filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000118
Johnny Chen38f823c2011-10-11 01:30:27 +0000119# The runhooks is a list of lldb commands specifically for the debugger.
120# Use '-k' to specify a runhook.
121runHooks = []
122
Johnny Chena224cd12010-11-08 01:21:03 +0000123# If '-g' is specified, the filterspec is not exclusive. If a test module does
124# not contain testclass.testmethod which matches the filterspec, the whole test
125# module is still admitted into our test suite. fs4all flag defaults to True.
126fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000127
Johnny Chenaf149a02010-09-16 17:11:30 +0000128# Ignore the build search path relative to this script to locate the lldb.py module.
129ignore = False
130
Johnny Chen028d8eb2011-11-17 19:57:27 +0000131# By default, we do not skip build and cleanup. Use '-S' option to override.
132skip_build_and_cleanup = False
133
Johnny Chen548aefd2010-10-11 22:25:46 +0000134# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000135skip_long_running_test = True
Johnny Chen41998192010-10-01 22:59:49 +0000136
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000137# By default, we print the build dir, lldb version, and svn info. Use '-n' option to
138# turn it off.
139noHeaders = False
140
Johnny Chen7c52ff12010-09-27 23:29:54 +0000141# The regular expression pattern to match against eligible filenames as our test cases.
142regexp = None
143
Johnny Chen548aefd2010-10-11 22:25:46 +0000144# By default, tests are executed in place and cleanups are performed afterwards.
145# Use '-r dir' option to relocate the tests and their intermediate files to a
146# different directory and to forgo any cleanups. The directory specified must
147# not exist yet.
148rdir = None
149
Johnny Chen125fc2b2010-10-21 16:55:35 +0000150# By default, recorded session info for errored/failed test are dumped into its
151# own file under a session directory named after the timestamp of the test suite
152# run. Use '-s session-dir-name' to specify a specific dir name.
153sdir_name = None
154
Johnny Chen63c2cba2010-10-29 22:20:36 +0000155# Set this flag if there is any session info dumped during the test run.
156sdir_has_content = False
157
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000158# svn_info stores the output from 'svn info lldb.base.dir'.
159svn_info = ''
160
Johnny Chen9707bb62010-06-25 21:14:08 +0000161# Default verbosity is 0.
162verbose = 0
163
Johnny Chen08967192011-11-18 00:19:29 +0000164# Set to True only if verbose is 0 and LLDB trace mode is off.
165progress_bar = False
166
Peter Collingbourne61aca482011-06-20 19:06:29 +0000167# By default, search from the script directory.
168testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000169
Johnny Chen877c7e42010-08-07 00:16:07 +0000170# Separator string.
171separator = '-' * 70
172
Johnny Chen9707bb62010-06-25 21:14:08 +0000173
174def usage():
175 print """
176Usage: dotest.py [option] [args]
177where options:
Jim Ingham4f347cb2011-04-13 21:11:41 +0000178-h : print this help message and exit. Add '-v' for more detailed help.
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000179-A : specify the architecture(s) to launch for the inferior process
180 -A i386 => launch inferior with i386 architecture
181 -A x86_64^i386 => launch inferior with x86_64 and i386 architectures
182-C : specify the compiler(s) used to build the inferior executable
183 -C clang => build debuggee using clang compiler
Johnny Chence9cf4e2012-01-17 01:26:06 +0000184 -C /my/full/path/to/clang => specify a full path to the clang binary
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000185 -C clang^gcc => build debuggee using clang and gcc compilers
Johnny Chen50bc6382011-01-29 01:16:52 +0000186-D : dump the Python sys.path variable
Johnny Chen4f93bf12010-12-10 00:51:23 +0000187-a : don't do lldb Python API tests
188 use @python_api_test to decorate a test case as lldb Python API test
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000189+a : just do lldb Python API tests
Johnny Chencc659ad2010-12-10 19:02:23 +0000190 do not specify both '-a' and '+a' at the same time
Johnny Chen82ccf402011-07-30 01:39:58 +0000191+b : just do benchmark tests
192 use @benchmark_test to decorate a test case as such
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000193-b : read a blacklist file specified after this option
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000194-c : read a config file specified after this option
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000195 the architectures and compilers (note the plurals) specified via '-A' and '-C'
196 will override those specified via a config file
Johnny Chenb40056b2010-09-21 00:09:27 +0000197 (see also lldb-trunk/example/test/usage-config)
Johnny Chen91960d32010-09-08 20:56:16 +0000198-d : delay startup for 10 seconds (in order for the debugger to attach)
Johnny Chene00c9302011-10-10 22:03:44 +0000199-e : specify the full path of an executable used for benchmark purpose;
200 see also '-x', which provides the breakpoint sepcification
Johnny Chen7d6d8442010-12-03 19:59:35 +0000201-F : failfast, stop the test suite on the first error/failure
Johnny Chen46be75d2010-10-11 16:19:48 +0000202-f : specify a filter, which consists of the test class name, a dot, followed by
Johnny Chen1a6e92a2010-11-08 20:17:04 +0000203 the test method, to only admit such test into the test suite
Johnny Chenb62436b2010-10-06 20:40:56 +0000204 e.g., -f 'ClassTypesTestCase.test_with_dwarf_and_python_api'
Johnny Chena224cd12010-11-08 01:21:03 +0000205-g : if specified, the filterspec by -f is not exclusive, i.e., if a test module
206 does not match the filterspec (testclass.testmethod), the whole module is
207 still admitted to the test suite
Johnny Chenaf149a02010-09-16 17:11:30 +0000208-i : ignore (don't bailout) if 'lldb.py' module cannot be located in the build
209 tree relative to this script; use PYTHONPATH to locate the module
Johnny Chen38f823c2011-10-11 01:30:27 +0000210-k : specify a runhook, which is an lldb command to be executed by the debugger;
211 '-k' option can occur multiple times, the commands are executed one after the
212 other to bring the debugger to a desired state, so that, for example, further
213 benchmarking can be done
Johnny Chen41998192010-10-01 22:59:49 +0000214-l : don't skip long running test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000215-n : don't print the headers like build dir, lldb version, and svn info at all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000216-p : specify a regexp filename pattern for inclusion in the test suite
Johnny Chen548aefd2010-10-11 22:25:46 +0000217-r : specify a dir to relocate the tests and their intermediate files to;
218 the directory must not exist before running this test driver;
219 no cleanup of intermediate test files is performed in this case
Johnny Chen028d8eb2011-11-17 19:57:27 +0000220-S : skip the build and cleanup while running the test
221 use this option with care as you would need to build the inferior(s) by hand
222 and build the executable(s) with the correct name(s)
223 this can be used with '-# n' to stress test certain test cases for n number of
224 times
Johnny Chen125fc2b2010-10-21 16:55:35 +0000225-s : specify the name of the dir created to store the session files of tests
226 with errored or failed status; if not specified, the test driver uses the
227 timestamp as the session dir name
Johnny Chena2486f22011-04-21 20:48:32 +0000228-t : turn on tracing of lldb command and other detailed test executions
229-v : do verbose mode of unittest framework (print out each test case invocation)
Johnny Chene00c9302011-10-10 22:03:44 +0000230-x : specify the breakpoint specification for the benchmark executable;
231 see also '-e', which provides the full path of the executable
Johnny Chen5f2ed172011-10-20 18:43:28 +0000232-y : specify the iteration count used to collect our benchmarks; an example is
233 the number of times to do 'thread step-over' to measure stepping speed
234 see also '-e' and '-x' options
Johnny Chene47649c2010-10-07 02:04:14 +0000235-w : insert some wait time (currently 0.5 sec) between consecutive test cases
Johnny Chend2acdb32010-11-16 22:42:58 +0000236-# : Repeat the test suite for a specified number of times
Johnny Chen9707bb62010-06-25 21:14:08 +0000237
238and:
Johnny Chen9656ab22010-10-22 19:00:18 +0000239args : specify a list of directory names to search for test modules named after
240 Test*.py (test discovery)
Peter Collingbourne5f2b5d62011-06-14 03:55:45 +0000241 if empty, search from the current working directory, instead
Jim Ingham4f347cb2011-04-13 21:11:41 +0000242"""
Johnny Chen58f93922010-06-29 23:10:39 +0000243
Jim Ingham4f347cb2011-04-13 21:11:41 +0000244 if verbose > 0:
245 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000246Examples:
247
Johnny Chena224cd12010-11-08 01:21:03 +0000248This is an example of using the -f option to pinpoint to a specfic test class
249and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000250
Johnny Chena224cd12010-11-08 01:21:03 +0000251$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000252----------------------------------------------------------------------
253Collected 1 test
254
255test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
256Test 'frame variable this' when stopped on a class constructor. ... ok
257
258----------------------------------------------------------------------
259Ran 1 test in 1.396s
260
261OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000262
263And this is an example of using the -p option to run a single file (the filename
264matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
265
266$ ./dotest.py -v -p ObjC
267----------------------------------------------------------------------
268Collected 4 tests
269
270test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000271Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000272test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000273Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000274test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
275Lookup objective-c data types and evaluate expressions. ... ok
276test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
277Lookup objective-c data types and evaluate expressions. ... ok
278
279----------------------------------------------------------------------
280Ran 4 tests in 16.661s
281
282OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000283
Johnny Chen58f93922010-06-29 23:10:39 +0000284Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000285individual test cases can locate their supporting files correctly. The script
286tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000287relative to this script. See also the '-i' option in the following example.
288
289Finally, this is an example of using the lldb.py module distributed/installed by
290Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
291option to add some delay between two tests. It uses ARCH=x86_64 to specify that
292as the architecture and CC=clang to specify the compiler used for the test run:
293
294$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
295
296Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
297----------------------------------------------------------------------
298Collected 2 tests
299
300test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
301Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
302test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
303Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
304
305----------------------------------------------------------------------
306Ran 2 tests in 5.659s
307
308OK
309
310The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
311notify the directory containing the session logs for test failures or errors.
312In case there is any test failure/error, a similar message is appended at the
313end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000314
315Environment variables related to loggings:
316
317o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
318 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
319
320o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
321 'process.gdb-remote' subsystem with a default option of 'packets' if
322 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000323"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000324 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000325
326
Johnny Chenaf149a02010-09-16 17:11:30 +0000327def parseOptionsAndInitTestdirs():
328 """Initialize the list of directories containing our unittest scripts.
329
330 '-h/--help as the first option prints out usage info and exit the program.
331 """
332
Johnny Chen4f93bf12010-12-10 00:51:23 +0000333 global dont_do_python_api_test
334 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000335 global just_do_benchmarks_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000336 global blacklist
337 global blacklistConfig
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000338 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000339 global archs
340 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000341 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000342 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000343 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000344 global bmExecutable
345 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000346 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000347 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000348 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000349 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000350 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000351 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000352 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000353 global skip_build_and_cleanup
354 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000355 global noHeaders
Johnny Chen7c52ff12010-09-27 23:29:54 +0000356 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000357 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000358 global sdir_name
Johnny Chenaf149a02010-09-16 17:11:30 +0000359 global verbose
360 global testdirs
361
Jim Ingham4f347cb2011-04-13 21:11:41 +0000362 do_help = False
363
Johnny Chenaf149a02010-09-16 17:11:30 +0000364 if len(sys.argv) == 1:
365 return
366
367 # Process possible trace and/or verbose flag, among other things.
368 index = 1
Johnny Chence2212c2010-10-07 15:41:55 +0000369 while index < len(sys.argv):
Johnny Chen4f93bf12010-12-10 00:51:23 +0000370 if sys.argv[index].startswith('-') or sys.argv[index].startswith('+'):
371 # We should continue processing...
372 pass
373 else:
Johnny Chenaf149a02010-09-16 17:11:30 +0000374 # End of option processing.
375 break
376
377 if sys.argv[index].find('-h') != -1:
Jim Ingham4f347cb2011-04-13 21:11:41 +0000378 index += 1
379 do_help = True
Johnny Chen012cba12011-01-26 19:07:42 +0000380 elif sys.argv[index].startswith('-A'):
381 # Increment by 1 to fetch the ARCH spec.
382 index += 1
383 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
384 usage()
Johnny Cheneee9b862011-04-26 20:45:00 +0000385 archs = sys.argv[index].split('^')
Johnny Chen012cba12011-01-26 19:07:42 +0000386 index += 1
387 elif sys.argv[index].startswith('-C'):
388 # Increment by 1 to fetch the CC spec.
389 index += 1
390 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
391 usage()
Johnny Cheneee9b862011-04-26 20:45:00 +0000392 compilers = sys.argv[index].split('^')
Johnny Chen012cba12011-01-26 19:07:42 +0000393 index += 1
Johnny Chen50bc6382011-01-29 01:16:52 +0000394 elif sys.argv[index].startswith('-D'):
395 dumpSysPath = True
396 index += 1
Johnny Chen4f93bf12010-12-10 00:51:23 +0000397 elif sys.argv[index].startswith('-a'):
398 dont_do_python_api_test = True
399 index += 1
400 elif sys.argv[index].startswith('+a'):
401 just_do_python_api_test = True
402 index += 1
Johnny Chen82ccf402011-07-30 01:39:58 +0000403 elif sys.argv[index].startswith('+b'):
404 just_do_benchmarks_test = True
405 index += 1
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000406 elif sys.argv[index].startswith('-b'):
407 # Increment by 1 to fetch the blacklist file name option argument.
408 index += 1
409 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
410 usage()
411 blacklistFile = sys.argv[index]
412 if not os.path.isfile(blacklistFile):
413 print "Blacklist file:", blacklistFile, "does not exist!"
414 usage()
415 index += 1
416 # Now read the blacklist contents and assign it to blacklist.
417 execfile(blacklistFile, globals(), blacklistConfig)
418 blacklist = blacklistConfig.get('blacklist')
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000419 elif sys.argv[index].startswith('-c'):
420 # Increment by 1 to fetch the config file name option argument.
421 index += 1
422 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
423 usage()
424 configFile = sys.argv[index]
425 if not os.path.isfile(configFile):
426 print "Config file:", configFile, "does not exist!"
427 usage()
428 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000429 elif sys.argv[index].startswith('-d'):
430 delay = True
431 index += 1
Johnny Chene00c9302011-10-10 22:03:44 +0000432 elif sys.argv[index].startswith('-e'):
433 # Increment by 1 to fetch the full path of the benchmark executable.
434 index += 1
435 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
436 usage()
437 bmExecutable = sys.argv[index]
438 if not is_exe(bmExecutable):
439 usage()
440 index += 1
Johnny Chen7d6d8442010-12-03 19:59:35 +0000441 elif sys.argv[index].startswith('-F'):
442 failfast = True
443 index += 1
Johnny Chenb62436b2010-10-06 20:40:56 +0000444 elif sys.argv[index].startswith('-f'):
445 # Increment by 1 to fetch the filter spec.
446 index += 1
447 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
448 usage()
Johnny Chenc5fa0052011-07-29 22:54:56 +0000449 filters.append(sys.argv[index])
Johnny Chenb62436b2010-10-06 20:40:56 +0000450 index += 1
451 elif sys.argv[index].startswith('-g'):
Johnny Chena224cd12010-11-08 01:21:03 +0000452 fs4all = False
Johnny Chenb62436b2010-10-06 20:40:56 +0000453 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000454 elif sys.argv[index].startswith('-i'):
455 ignore = True
456 index += 1
Johnny Chen38f823c2011-10-11 01:30:27 +0000457 elif sys.argv[index].startswith('-k'):
458 # Increment by 1 to fetch the runhook lldb command.
459 index += 1
460 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
461 usage()
462 runHooks.append(sys.argv[index])
463 index += 1
Johnny Chen41998192010-10-01 22:59:49 +0000464 elif sys.argv[index].startswith('-l'):
Johnny Chen028d8eb2011-11-17 19:57:27 +0000465 skip_long_running_test = False
Johnny Chen41998192010-10-01 22:59:49 +0000466 index += 1
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000467 elif sys.argv[index].startswith('-n'):
468 noHeaders = True
469 index += 1
Johnny Chen7c52ff12010-09-27 23:29:54 +0000470 elif sys.argv[index].startswith('-p'):
471 # Increment by 1 to fetch the reg exp pattern argument.
472 index += 1
473 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
474 usage()
475 regexp = sys.argv[index]
476 index += 1
Johnny Chen548aefd2010-10-11 22:25:46 +0000477 elif sys.argv[index].startswith('-r'):
478 # Increment by 1 to fetch the relocated directory argument.
479 index += 1
480 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
481 usage()
482 rdir = os.path.abspath(sys.argv[index])
483 if os.path.exists(rdir):
484 print "Relocated directory:", rdir, "must not exist!"
485 usage()
486 index += 1
Johnny Chen028d8eb2011-11-17 19:57:27 +0000487 elif sys.argv[index].startswith('-S'):
488 skip_build_and_cleanup = True
489 index += 1
Johnny Chen125fc2b2010-10-21 16:55:35 +0000490 elif sys.argv[index].startswith('-s'):
491 # Increment by 1 to fetch the session dir name.
492 index += 1
493 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
494 usage()
495 sdir_name = sys.argv[index]
496 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000497 elif sys.argv[index].startswith('-t'):
498 os.environ["LLDB_COMMAND_TRACE"] = "YES"
499 index += 1
500 elif sys.argv[index].startswith('-v'):
501 verbose = 2
502 index += 1
Johnny Chene47649c2010-10-07 02:04:14 +0000503 elif sys.argv[index].startswith('-w'):
504 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] = 'YES'
505 index += 1
Johnny Chene00c9302011-10-10 22:03:44 +0000506 elif sys.argv[index].startswith('-x'):
507 # Increment by 1 to fetch the breakpoint specification of the benchmark executable.
508 index += 1
Johnny Chen8a1b1222011-10-20 22:16:24 +0000509 if index >= len(sys.argv):
Johnny Chene00c9302011-10-10 22:03:44 +0000510 usage()
511 bmBreakpointSpec = sys.argv[index]
512 index += 1
Johnny Chen5f2ed172011-10-20 18:43:28 +0000513 elif sys.argv[index].startswith('-y'):
514 # Increment by 1 to fetch the the benchmark iteration count.
515 index += 1
516 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
517 usage()
518 bmIterationCount = int(sys.argv[index])
519 index += 1
Johnny Chend2acdb32010-11-16 22:42:58 +0000520 elif sys.argv[index].startswith('-#'):
521 # Increment by 1 to fetch the repeat count argument.
522 index += 1
523 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
524 usage()
525 count = int(sys.argv[index])
526 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000527 else:
528 print "Unknown option: ", sys.argv[index]
529 usage()
Johnny Chenaf149a02010-09-16 17:11:30 +0000530
Jim Ingham4f347cb2011-04-13 21:11:41 +0000531 if do_help == True:
532 usage()
533
Johnny Chencc659ad2010-12-10 19:02:23 +0000534 # Do not specify both '-a' and '+a' at the same time.
535 if dont_do_python_api_test and just_do_python_api_test:
536 usage()
537
Johnny Chen08967192011-11-18 00:19:29 +0000538 # The simple progress bar is turned on only if verbose == 0 and LLDB_COMMAND_TRACE is not 'YES'
539 if ("LLDB_COMMAND_TRACE" not in os.environ or os.environ["LLDB_COMMAND_TRACE"]!="YES") and verbose==0:
540 progress_bar = True
541
Johnny Chenaf149a02010-09-16 17:11:30 +0000542 # Gather all the dirs passed on the command line.
543 if len(sys.argv) > index:
544 testdirs = map(os.path.abspath, sys.argv[index:])
545
Johnny Chen548aefd2010-10-11 22:25:46 +0000546 # If '-r dir' is specified, the tests should be run under the relocated
547 # directory. Let's copy the testdirs over.
548 if rdir:
549 from shutil import copytree, ignore_patterns
550
551 tmpdirs = []
552 for srcdir in testdirs:
553 dstdir = os.path.join(rdir, os.path.basename(srcdir))
554 # Don't copy the *.pyc and .svn stuffs.
555 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
556 tmpdirs.append(dstdir)
557
558 # This will be our modified testdirs.
559 testdirs = tmpdirs
560
561 # With '-r dir' specified, there's no cleanup of intermediate test files.
562 os.environ["LLDB_DO_CLEANUP"] = 'NO'
563
564 # If testdirs is ['test'], the make directory has already been copied
565 # recursively and is contained within the rdir/test dir. For anything
566 # else, we would need to copy over the make directory and its contents,
567 # so that, os.listdir(rdir) looks like, for example:
568 #
569 # array_types conditional_break make
570 #
571 # where the make directory contains the Makefile.rules file.
572 if len(testdirs) != 1 or os.path.basename(testdirs[0]) != 'test':
573 # Don't copy the .svn stuffs.
574 copytree('make', os.path.join(rdir, 'make'),
575 ignore=ignore_patterns('.svn'))
576
577 #print "testdirs:", testdirs
578
Johnny Chenb40056b2010-09-21 00:09:27 +0000579 # Source the configFile if specified.
580 # The side effect, if any, will be felt from this point on. An example
581 # config file may be these simple two lines:
582 #
583 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
584 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
585 #
586 # which will reassign the two file objects to sys.stderr and sys.stdout,
587 # respectively.
588 #
589 # See also lldb-trunk/example/test/usage-config.
590 global config
591 if configFile:
592 # Pass config (a dictionary) as the locals namespace for side-effect.
593 execfile(configFile, globals(), config)
594 #print "config:", config
595 #print "sys.stderr:", sys.stderr
596 #print "sys.stdout:", sys.stdout
597
Johnny Chenaf149a02010-09-16 17:11:30 +0000598
Johnny Chen9707bb62010-06-25 21:14:08 +0000599def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000600 """
601 Add LLDB.framework/Resources/Python to the search paths for modules.
602 As a side effect, we also discover the 'lldb' executable and export it here.
603 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000604
Johnny Chen548aefd2010-10-11 22:25:46 +0000605 global rdir
606 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000607 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000608 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000609 global svn_info
Johnny Chen548aefd2010-10-11 22:25:46 +0000610
Johnny Chen9707bb62010-06-25 21:14:08 +0000611 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000612 if ("DOTEST_PROFILE" in os.environ or "DOTEST_PDB" in os.environ) and "DOTEST_SCRIPT_DIR" in os.environ:
Johnny Chen0de6ab52011-01-19 02:10:40 +0000613 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
614 else:
615 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000616 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000617 print "This script expects to reside in lldb's test directory."
618 sys.exit(-1)
619
Johnny Chen548aefd2010-10-11 22:25:46 +0000620 if rdir:
621 # Set up the LLDB_TEST environment variable appropriately, so that the
622 # individual tests can be located relatively.
623 #
624 # See also lldbtest.TestBase.setUpClass(cls).
625 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
626 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
627 else:
628 os.environ["LLDB_TEST"] = rdir
629 else:
630 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000631
632 # Set up the LLDB_SRC environment variable, so that the tests can locate
633 # the LLDB source code.
634 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
635
Johnny Chen9de4ede2010-08-31 17:42:54 +0000636 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000637 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000638
Johnny Chen8a3c0432011-03-11 20:13:06 +0000639 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000640 sys.path.append(scriptPath)
641 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000642 sys.path.append(pexpectPath)
Johnny Chenaf149a02010-09-16 17:11:30 +0000643
Johnny Chen26901c82011-03-11 19:47:23 +0000644 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000645 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000646
Johnny Chen26901c82011-03-11 19:47:23 +0000647 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000648 xcode3_build_dir = ['build']
649 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
650 dbg = ['Debug']
651 rel = ['Release']
652 bai = ['BuildAndIntegration']
653 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000654
655 # Some of the tests can invoke the 'lldb' command directly.
656 # We'll try to locate the appropriate executable right here.
657
Johnny Chen6033bed2011-08-26 00:00:01 +0000658 # First, you can define an environment variable LLDB_EXEC specifying the
659 # full pathname of the lldb executable.
660 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
661 lldbExec = os.environ["LLDB_EXEC"]
662 else:
663 lldbExec = None
664
Johnny Chen26901c82011-03-11 19:47:23 +0000665 executable = ['lldb']
666 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
667 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
668 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
669 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
670 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
671 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
672
Johnny Chen6033bed2011-08-26 00:00:01 +0000673 # The 'lldb' executable built here in the source tree.
674 lldbHere = None
Johnny Chen26901c82011-03-11 19:47:23 +0000675 if is_exe(dbgExec):
Johnny Chen6033bed2011-08-26 00:00:01 +0000676 lldbHere = dbgExec
Johnny Chen26901c82011-03-11 19:47:23 +0000677 elif is_exe(dbgExec2):
Johnny Chen6033bed2011-08-26 00:00:01 +0000678 lldbHere = dbgExec2
Johnny Chen26901c82011-03-11 19:47:23 +0000679 elif is_exe(relExec):
Johnny Chen6033bed2011-08-26 00:00:01 +0000680 lldbHere = relExec
Johnny Chen26901c82011-03-11 19:47:23 +0000681 elif is_exe(relExec2):
Johnny Chen6033bed2011-08-26 00:00:01 +0000682 lldbHere = relExec2
Johnny Chen26901c82011-03-11 19:47:23 +0000683 elif is_exe(baiExec):
Johnny Chen6033bed2011-08-26 00:00:01 +0000684 lldbHere = baiExec
Johnny Chen26901c82011-03-11 19:47:23 +0000685 elif is_exe(baiExec2):
Johnny Chen6033bed2011-08-26 00:00:01 +0000686 lldbHere = baiExec2
Daniel Dunbar2bd310c2011-10-31 23:27:06 +0000687 elif lldbExec:
688 lldbHere = lldbExec
Johnny Chen26901c82011-03-11 19:47:23 +0000689
Johnny Chen6033bed2011-08-26 00:00:01 +0000690 if lldbHere:
691 os.environ["LLDB_HERE"] = lldbHere
Johnny Chen0409d992011-10-25 20:08:03 +0000692 os.environ["LLDB_BUILD_DIR"] = os.path.split(lldbHere)[0]
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000693 if not noHeaders:
694 print "LLDB build dir:", os.environ["LLDB_BUILD_DIR"]
Johnny Chen91da0052011-10-28 17:56:02 +0000695 os.system('%s -v' % lldbHere)
Johnny Chen62d527e2011-08-04 18:17:16 +0000696
Johnny Chen6033bed2011-08-26 00:00:01 +0000697 # One last chance to locate the 'lldb' executable.
Johnny Chen26901c82011-03-11 19:47:23 +0000698 if not lldbExec:
Johnny Chen0409d992011-10-25 20:08:03 +0000699 lldbExec = which('lldb')
700 if lldbHere and not lldbExec:
Johnny Chen6033bed2011-08-26 00:00:01 +0000701 lldbExec = lldbHere
Johnny Chen0409d992011-10-25 20:08:03 +0000702
Johnny Chen26901c82011-03-11 19:47:23 +0000703
704 if not lldbExec:
705 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
706 else:
707 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000708 #print "The 'lldb' from PATH env variable", lldbExec
Johnny Chend7931462011-03-17 00:38:22 +0000709
Johnny Chenb264c9b2011-06-24 22:52:05 +0000710 if os.path.isdir(os.path.join(base, '.svn')):
711 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
712 svn_info = pipe.stdout.read()
713 elif os.path.isdir(os.path.join(base, '.git')):
714 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
715 svn_info = pipe.stdout.read()
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000716 if not noHeaders:
717 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000718
719 global ignore
720
721 # The '-i' option is used to skip looking for lldb.py in the build tree.
722 if ignore:
723 return
724
Johnny Chen6a564a42011-02-15 18:50:19 +0000725 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
726 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
727 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
728 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
729 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
730 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Johnny Chen9707bb62010-06-25 21:14:08 +0000731
732 lldbPath = None
733 if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
734 lldbPath = dbgPath
Greg Claytond9846b02011-02-14 21:17:06 +0000735 elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')):
736 lldbPath = dbgPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000737 elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
738 lldbPath = relPath
Greg Claytond9846b02011-02-14 21:17:06 +0000739 elif os.path.isfile(os.path.join(relPath2, 'lldb.py')):
740 lldbPath = relPath2
Johnny Chenc202c462010-09-15 18:11:19 +0000741 elif os.path.isfile(os.path.join(baiPath, 'lldb.py')):
742 lldbPath = baiPath
Greg Claytond9846b02011-02-14 21:17:06 +0000743 elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')):
744 lldbPath = baiPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000745
746 if not lldbPath:
Johnny Chenc202c462010-09-15 18:11:19 +0000747 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
748 print relPath + ', or ' + baiPath
Johnny Chen9707bb62010-06-25 21:14:08 +0000749 sys.exit(-1)
750
Johnny Chenaf149a02010-09-16 17:11:30 +0000751 # This is to locate the lldb.py module. Insert it right after sys.path[0].
752 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000753 if dumpSysPath:
754 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000755
Johnny Chen9707bb62010-06-25 21:14:08 +0000756
Johnny Chencd0279d2010-09-20 18:07:50 +0000757def doDelay(delta):
758 """Delaying startup for delta-seconds to facilitate debugger attachment."""
759 def alarm_handler(*args):
760 raise Exception("timeout")
761
762 signal.signal(signal.SIGALRM, alarm_handler)
763 signal.alarm(delta)
764 sys.stdout.write("pid=%d\n" % os.getpid())
765 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
766 delta)
767 sys.stdout.flush()
768 try:
769 text = sys.stdin.readline()
770 except:
771 text = ""
772 signal.alarm(0)
773 sys.stdout.write("proceeding...\n")
774 pass
775
776
Johnny Chen9707bb62010-06-25 21:14:08 +0000777def visit(prefix, dir, names):
778 """Visitor function for os.path.walk(path, visit, arg)."""
779
780 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000781 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000782 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000783 global fs4all
Johnny Chen9707bb62010-06-25 21:14:08 +0000784
785 for name in names:
786 if os.path.isdir(os.path.join(dir, name)):
787 continue
788
789 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000790 # Try to match the regexp pattern, if specified.
791 if regexp:
792 import re
793 if re.search(regexp, name):
794 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
795 pass
796 else:
797 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
798 continue
799
Johnny Chen953864a2010-10-12 21:35:54 +0000800 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000801
802 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000803 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000804 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000805 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000806
807 # Thoroughly check the filterspec against the base module and admit
808 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000809 filterspec = None
810 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000811 # Optimistically set the flag to True.
812 filtered = True
813 module = __import__(base)
814 parts = filterspec.split('.')
815 obj = module
816 for part in parts:
817 try:
818 parent, obj = obj, getattr(obj, part)
819 except AttributeError:
820 # The filterspec has failed.
821 filtered = False
822 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000823
Johnny Chendb4be602011-08-12 23:55:07 +0000824 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000825 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +0000826 #print "adding filter spec %s to module %s" % (filterspec, module)
827 suite.addTests(
828 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
829 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +0000830
831 # Forgo this module if the (base, filterspec) combo is invalid
832 # and no '-g' option is specified
833 if filters and fs4all and not filtered:
834 continue
Johnny Chenb62436b2010-10-06 20:40:56 +0000835
Johnny Chendb4be602011-08-12 23:55:07 +0000836 # Add either the filtered test case(s) (which is done before) or the entire test class.
837 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +0000838 # A simple case of just the module name. Also the failover case
839 # from the filterspec branch when the (base, filterspec) combo
840 # doesn't make sense.
841 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000842
843
Johnny Chencd0279d2010-09-20 18:07:50 +0000844def lldbLoggings():
845 """Check and do lldb loggings if necessary."""
846
847 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
848 # defined. Use ${LLDB_LOG} to specify the log file.
849 ci = lldb.DBG.GetCommandInterpreter()
850 res = lldb.SBCommandReturnObject()
851 if ("LLDB_LOG" in os.environ):
852 if ("LLDB_LOG_OPTION" in os.environ):
853 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
854 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +0000855 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +0000856 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +0000857 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +0000858 res)
859 if not res.Succeeded():
860 raise Exception('log enable failed (check LLDB_LOG env variable.')
861 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
862 # Use ${GDB_REMOTE_LOG} to specify the log file.
863 if ("GDB_REMOTE_LOG" in os.environ):
864 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
865 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
866 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +0000867 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +0000868 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +0000869 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +0000870 + gdb_remote_log_option,
871 res)
872 if not res.Succeeded():
873 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
874
Johnny Chen067022b2011-01-19 19:31:46 +0000875def getMyCommandLine():
Johnny Chen067022b2011-01-19 19:31:46 +0000876 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
877 lines = ps.split('\n')
878 cmd_line = lines[1]
879 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +0000880
Johnny Chend96b5682010-11-05 17:30:53 +0000881# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000882# #
883# Execution of the test driver starts here #
884# #
Johnny Chend96b5682010-11-05 17:30:53 +0000885# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000886
Johnny Chen2891bb02011-09-16 01:04:26 +0000887def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +0000888 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
889 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
890 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +0000891 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +0000892 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +0000893 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +0000894 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
895 print "Exiting..."
896 sys.exit(0)
897
898# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
899# does not exist before proceeding to running the test suite.
900if sys.platform.startswith("darwin"):
901 checkDsymForUUIDIsNotOn()
902
Johnny Chen9707bb62010-06-25 21:14:08 +0000903#
Johnny Chenaf149a02010-09-16 17:11:30 +0000904# Start the actions by first parsing the options while setting up the test
905# directories, followed by setting up the search paths for lldb utilities;
906# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +0000907#
Johnny Chenaf149a02010-09-16 17:11:30 +0000908parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +0000909setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +0000910
911#
912# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
913#
914if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +0000915 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +0000916
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000917#
Johnny Chen41998192010-10-01 22:59:49 +0000918# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000919if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +0000920 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
921
922#
Johnny Chen79723352010-10-12 15:53:22 +0000923# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000924#
Johnny Chen9707bb62010-06-25 21:14:08 +0000925for testdir in testdirs:
926 os.path.walk(testdir, visit, 'Test')
927
Johnny Chenb40056b2010-09-21 00:09:27 +0000928#
Johnny Chen9707bb62010-06-25 21:14:08 +0000929# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +0000930#
Johnny Chencd0279d2010-09-20 18:07:50 +0000931
Johnny Chen1bfbd412010-06-29 19:44:16 +0000932# For the time being, let's bracket the test runner within the
933# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000934import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +0000935# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
936# there's no need to call it a second time.
937#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000938atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +0000939
Johnny Chen909e5a62010-07-01 22:52:57 +0000940# Create a singleton SBDebugger in the lldb namespace.
941lldb.DBG = lldb.SBDebugger.Create()
942
Johnny Chen4f93bf12010-12-10 00:51:23 +0000943# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000944lldb.blacklist = blacklist
945
Johnny Chene00c9302011-10-10 22:03:44 +0000946# Put dont/just_do_python_api_test in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +0000947lldb.dont_do_python_api_test = dont_do_python_api_test
948lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000949lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chen4f93bf12010-12-10 00:51:23 +0000950
Johnny Chen028d8eb2011-11-17 19:57:27 +0000951# Do we need to skip build and cleanup?
952lldb.skip_build_and_cleanup = skip_build_and_cleanup
953
Johnny Chen5f2ed172011-10-20 18:43:28 +0000954# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +0000955lldb.bmExecutable = bmExecutable
956lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000957lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +0000958
Johnny Chen38f823c2011-10-11 01:30:27 +0000959# And don't forget the runHooks!
960lldb.runHooks = runHooks
961
Johnny Chencd0279d2010-09-20 18:07:50 +0000962# Turn on lldb loggings if necessary.
963lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +0000964
Johnny Chen7987ac92010-08-09 20:40:52 +0000965# Install the control-c handler.
966unittest2.signals.installHandler()
967
Johnny Chen125fc2b2010-10-21 16:55:35 +0000968# If sdir_name is not specified through the '-s sdir_name' option, get a
969# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
970# be used when/if we want to dump the session info of individual test cases
971# later on.
Johnny Chence681462010-10-19 00:25:01 +0000972#
973# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chen125fc2b2010-10-21 16:55:35 +0000974if not sdir_name:
975 import datetime
Johnny Chen41fae812010-10-29 22:26:38 +0000976 # The windows platforms don't like ':' in the pathname.
Johnny Chen76bd0102010-10-28 16:32:13 +0000977 timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +0000978 sdir_name = timestamp
Peter Collingbourne132476f2011-06-20 23:55:53 +0000979os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +0000980
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000981if not noHeaders:
982 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
983 " will go into directory '%s'\n" % sdir_name)
984 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +0000985
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000986if not os.path.isdir(sdir_name):
987 os.mkdir(sdir_name)
988fname = os.path.join(sdir_name, "svn-info")
989with open(fname, "w") as f:
990 print >> f, svn_info
991 print >> f, "Command invoked: %s\n" % getMyCommandLine()
992
Johnny Chenb40056b2010-09-21 00:09:27 +0000993#
994# Invoke the default TextTestRunner to run the test suite, possibly iterating
995# over different configurations.
996#
997
Johnny Chenb40056b2010-09-21 00:09:27 +0000998iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +0000999iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001000
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001001if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001002 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001003
1004if isinstance(archs, list) and len(archs) >= 1:
1005 iterArchs = True
1006
1007if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001008 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001009
1010if isinstance(compilers, list) and len(compilers) >= 1:
1011 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001012
Johnny Chen953864a2010-10-12 21:35:54 +00001013# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1014# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001015if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001016 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001017# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1018if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001019 old_stderr = sys.stderr
1020 old_stdout = sys.stdout
1021 new_stderr = None
1022 new_stdout = None
1023
Johnny Chend96b5682010-11-05 17:30:53 +00001024# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001025for ia in range(len(archs) if iterArchs else 1):
1026 archConfig = ""
1027 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001028 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001029 archConfig = "arch=%s" % archs[ia]
1030 for ic in range(len(compilers) if iterCompilers else 1):
1031 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001032 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001033 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1034 else:
1035 configString = archConfig
1036
Johnny Chenb40056b2010-09-21 00:09:27 +00001037 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001038 # Translate ' ' to '-' for pathname component.
1039 from string import maketrans
1040 tbl = maketrans(' ', '-')
1041 configPostfix = configString.translate(tbl)
1042
1043 # Check whether we need to split stderr/stdout into configuration
1044 # specific files.
1045 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1046 if new_stderr:
1047 new_stderr.close()
1048 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1049 sys.stderr = new_stderr
1050 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1051 if new_stdout:
1052 new_stdout.close()
1053 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1054 sys.stdout = new_stdout
1055
Johnny Chen953864a2010-10-12 21:35:54 +00001056 # If we specified a relocated directory to run the test suite, do
1057 # the extra housekeeping to copy the testdirs to a configStringified
1058 # directory and to update sys.path before invoking the test runner.
1059 # The purpose is to separate the configuration-specific directories
1060 # from each other.
1061 if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001062 from shutil import copytree, ignore_patterns
1063
Johnny Chen953864a2010-10-12 21:35:54 +00001064 newrdir = "%s.%s" % (rdir, configPostfix)
1065
1066 # Copy the tree to a new directory with postfix name configPostfix.
1067 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1068
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001069 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001070 # level test directory.
1071 #
1072 # See also lldbtest.TestBase.setUpClass(cls).
1073 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1074 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1075 else:
1076 os.environ["LLDB_TEST"] = newrdir
1077
1078 # And update the Python search paths for modules.
1079 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1080
1081 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +00001082 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001083
1084 #print "sys.stderr name is", sys.stderr.name
1085 #print "sys.stdout name is", sys.stdout.name
1086
1087 # First, write out the number of collected test cases.
Johnny Chen08967192011-11-18 00:19:29 +00001088 sys.stderr.write(separator + "\n")
1089 sys.stderr.write("Collected %d test%s\n\n"
1090 % (suite.countTestCases(),
1091 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001092
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001093 class LLDBTestResult(unittest2.TextTestResult):
1094 """
Johnny Chen26be4532010-11-09 23:56:14 +00001095 Enforce a singleton pattern to allow introspection of test progress.
1096
1097 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1098 to enable each test instance to track its failure/error status. It
1099 is used in the LLDB test framework to emit detailed trace messages
1100 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001101 """
1102 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001103 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001104
1105 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001106 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001107 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001108 super(LLDBTestResult, self).__init__(*args)
1109 LLDBTestResult.__singleton__ = self
1110 # Now put this singleton into the lldb module namespace.
1111 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001112 # Computes the format string for displaying the counter.
1113 global suite
1114 counterWidth = len(str(suite.countTestCases()))
1115 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001116 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001117 # This counts from 1 .. suite.countTestCases().
1118 self.counter = 0
1119
Johnny Chenc87fd492011-01-05 22:50:11 +00001120 def getDescription(self, test):
1121 doc_first_line = test.shortDescription()
1122 if self.descriptions and doc_first_line:
1123 return '\n'.join((str(test), self.indentation + doc_first_line))
1124 else:
1125 return str(test)
1126
Johnny Chen810042e2011-01-05 20:24:11 +00001127 def startTest(self, test):
1128 self.counter += 1
1129 if self.showAll:
1130 self.stream.write(self.fmt % self.counter)
1131 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001132
Johnny Chen08967192011-11-18 00:19:29 +00001133 def stopTest(self, test):
1134 """Called when the given test has been run"""
1135 if progress_bar:
1136 sys.__stdout__.write('.')
1137 sys.__stdout__.flush()
1138 if self.counter == suite.countTestCases():
1139 sys.__stdout__.write('\n')
1140
1141 super(LLDBTestResult, self).stopTest(test)
1142
Johnny Chence681462010-10-19 00:25:01 +00001143 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001144 global sdir_has_content
1145 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001146 super(LLDBTestResult, self).addError(test, err)
1147 method = getattr(test, "markError", None)
1148 if method:
1149 method()
1150
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001151 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001152 global sdir_has_content
1153 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001154 super(LLDBTestResult, self).addFailure(test, err)
1155 method = getattr(test, "markFailure", None)
1156 if method:
1157 method()
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001158
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001159 def addExpectedFailure(self, test, err):
1160 global sdir_has_content
1161 sdir_has_content = True
1162 super(LLDBTestResult, self).addExpectedFailure(test, err)
1163 method = getattr(test, "markExpectedFailure", None)
1164 if method:
1165 method()
1166
Johnny Chenf5b89092011-08-15 23:09:08 +00001167 def addSkip(self, test, reason):
1168 global sdir_has_content
1169 sdir_has_content = True
1170 super(LLDBTestResult, self).addSkip(test, reason)
1171 method = getattr(test, "markSkippedTest", None)
1172 if method:
1173 method()
1174
Johnny Chenab2f0662011-05-06 20:30:22 +00001175 def addUnexpectedSuccess(self, test):
1176 global sdir_has_content
1177 sdir_has_content = True
1178 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1179 method = getattr(test, "markUnexpectedSuccess", None)
1180 if method:
1181 method()
1182
Johnny Chen26be4532010-11-09 23:56:14 +00001183 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001184 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001185 result = unittest2.TextTestRunner(stream=sys.stderr,
1186 verbosity=verbose,
1187 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001188 resultclass=LLDBTestResult).run(suite)
1189 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001190 # We are invoking the same test suite more than once. In this case,
1191 # mark __ignore_singleton__ flag as True so the signleton pattern is
1192 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001193 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001194 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +00001195 result = unittest2.TextTestRunner(stream=sys.stderr,
1196 verbosity=verbose,
1197 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001198 resultclass=LLDBTestResult).run(suite)
Johnny Chenb40056b2010-09-21 00:09:27 +00001199
Johnny Chen1bfbd412010-06-29 19:44:16 +00001200
Johnny Chen63c2cba2010-10-29 22:20:36 +00001201if sdir_has_content:
Johnny Chenab2f0662011-05-06 20:30:22 +00001202 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1203 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001204
Johnny Chencd0279d2010-09-20 18:07:50 +00001205# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1206# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001207if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001208 print "Terminating Test suite..."
1209 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1210
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001211# Exiting.
1212sys.exit(not result.wasSuccessful)