blob: 68cca8c6ec17000a24c1caf5ae2a8043413a98a2 [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 Chen26901c82011-03-11 19:47:23 +000026def is_exe(fpath):
Johnny Chenf2c7b282011-04-26 23:10:51 +000027 """Returns true if fpath is an executable."""
Johnny Chen26901c82011-03-11 19:47:23 +000028 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
29
Johnny Chen26901c82011-03-11 19:47:23 +000030def which(program):
Johnny Chenf2c7b282011-04-26 23:10:51 +000031 """Returns the full path to a program; None otherwise."""
Johnny Chen26901c82011-03-11 19:47:23 +000032 fpath, fname = os.path.split(program)
33 if fpath:
34 if is_exe(program):
35 return program
36 else:
37 for path in os.environ["PATH"].split(os.pathsep):
38 exe_file = os.path.join(path, program)
39 if is_exe(exe_file):
40 return exe_file
41 return None
42
Johnny Chen877c7e42010-08-07 00:16:07 +000043class _WritelnDecorator(object):
44 """Used to decorate file-like objects with a handy 'writeln' method"""
45 def __init__(self,stream):
46 self.stream = stream
47
48 def __getattr__(self, attr):
49 if attr in ('stream', '__getstate__'):
50 raise AttributeError(attr)
51 return getattr(self.stream,attr)
52
53 def writeln(self, arg=None):
54 if arg:
55 self.write(arg)
56 self.write('\n') # text-mode streams translate to \r\n if needed
57
Johnny Chen9707bb62010-06-25 21:14:08 +000058#
59# Global variables:
60#
61
62# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000063suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000064
Johnny Chen4f93bf12010-12-10 00:51:23 +000065# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000066# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
67# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000068dont_do_python_api_test = False
69
70# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000071just_do_python_api_test = False
72
Johnny Chen82e6b1e2010-12-01 22:47:54 +000073# The blacklist is optional (-b blacklistFile) and allows a central place to skip
74# testclass's and/or testclass.testmethod's.
75blacklist = None
76
77# The dictionary as a result of sourcing blacklistFile.
78blacklistConfig = {}
79
Johnny Chen9fdb0a92010-09-18 00:16:47 +000080# The config file is optional.
81configFile = None
82
Johnny Chend2acdb32010-11-16 22:42:58 +000083# Test suite repeat count. Can be overwritten with '-# count'.
84count = 1
85
Johnny Chenb40056b2010-09-21 00:09:27 +000086# The dictionary as a result of sourcing configFile.
87config = {}
88
Johnny Chen1a4d5e72011-03-04 01:35:22 +000089# The 'archs' and 'compilers' can be specified via either command line or configFile,
90# with the command line overriding the configFile. When specified, they should be
91# of the list type. For example, "-A x86_64^i386" => archs=['x86_64', 'i386'] and
92# "-C gcc^clang" => compilers=['gcc', 'clang'].
93archs = None
94compilers = None
95
Johnny Chen91960d32010-09-08 20:56:16 +000096# Delay startup in order for the debugger to attach.
97delay = False
98
Johnny Chend5362332011-01-29 01:21:04 +000099# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000100dumpSysPath = False
101
Johnny Chen7d6d8442010-12-03 19:59:35 +0000102# By default, failfast is False. Use '-F' to overwrite it.
103failfast = False
104
Johnny Chenc5fa0052011-07-29 22:54:56 +0000105# The filters (testclass.testmethod) used to admit tests into our test suite.
106filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000107
Johnny Chena224cd12010-11-08 01:21:03 +0000108# If '-g' is specified, the filterspec is not exclusive. If a test module does
109# not contain testclass.testmethod which matches the filterspec, the whole test
110# module is still admitted into our test suite. fs4all flag defaults to True.
111fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000112
Johnny Chenaf149a02010-09-16 17:11:30 +0000113# Ignore the build search path relative to this script to locate the lldb.py module.
114ignore = False
115
Johnny Chen548aefd2010-10-11 22:25:46 +0000116# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen41998192010-10-01 22:59:49 +0000117skipLongRunningTest = True
118
Johnny Chen7c52ff12010-09-27 23:29:54 +0000119# The regular expression pattern to match against eligible filenames as our test cases.
120regexp = None
121
Johnny Chen548aefd2010-10-11 22:25:46 +0000122# By default, tests are executed in place and cleanups are performed afterwards.
123# Use '-r dir' option to relocate the tests and their intermediate files to a
124# different directory and to forgo any cleanups. The directory specified must
125# not exist yet.
126rdir = None
127
Johnny Chen125fc2b2010-10-21 16:55:35 +0000128# By default, recorded session info for errored/failed test are dumped into its
129# own file under a session directory named after the timestamp of the test suite
130# run. Use '-s session-dir-name' to specify a specific dir name.
131sdir_name = None
132
Johnny Chen63c2cba2010-10-29 22:20:36 +0000133# Set this flag if there is any session info dumped during the test run.
134sdir_has_content = False
135
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000136# svn_info stores the output from 'svn info lldb.base.dir'.
137svn_info = ''
138
Johnny Chen9707bb62010-06-25 21:14:08 +0000139# Default verbosity is 0.
140verbose = 0
141
Peter Collingbourne61aca482011-06-20 19:06:29 +0000142# By default, search from the script directory.
143testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000144
Johnny Chen877c7e42010-08-07 00:16:07 +0000145# Separator string.
146separator = '-' * 70
147
Johnny Chen9707bb62010-06-25 21:14:08 +0000148
149def usage():
150 print """
151Usage: dotest.py [option] [args]
152where options:
Jim Ingham4f347cb2011-04-13 21:11:41 +0000153-h : print this help message and exit. Add '-v' for more detailed help.
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000154-A : specify the architecture(s) to launch for the inferior process
155 -A i386 => launch inferior with i386 architecture
156 -A x86_64^i386 => launch inferior with x86_64 and i386 architectures
157-C : specify the compiler(s) used to build the inferior executable
158 -C clang => build debuggee using clang compiler
159 -C clang^gcc => build debuggee using clang and gcc compilers
Johnny Chen50bc6382011-01-29 01:16:52 +0000160-D : dump the Python sys.path variable
Johnny Chen4f93bf12010-12-10 00:51:23 +0000161-a : don't do lldb Python API tests
162 use @python_api_test to decorate a test case as lldb Python API test
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000163+a : just do lldb Python API tests
Johnny Chencc659ad2010-12-10 19:02:23 +0000164 do not specify both '-a' and '+a' at the same time
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000165-b : read a blacklist file specified after this option
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000166-c : read a config file specified after this option
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000167 the architectures and compilers (note the plurals) specified via '-A' and '-C'
168 will override those specified via a config file
Johnny Chenb40056b2010-09-21 00:09:27 +0000169 (see also lldb-trunk/example/test/usage-config)
Johnny Chen91960d32010-09-08 20:56:16 +0000170-d : delay startup for 10 seconds (in order for the debugger to attach)
Johnny Chen7d6d8442010-12-03 19:59:35 +0000171-F : failfast, stop the test suite on the first error/failure
Johnny Chen46be75d2010-10-11 16:19:48 +0000172-f : specify a filter, which consists of the test class name, a dot, followed by
Johnny Chen1a6e92a2010-11-08 20:17:04 +0000173 the test method, to only admit such test into the test suite
Johnny Chenb62436b2010-10-06 20:40:56 +0000174 e.g., -f 'ClassTypesTestCase.test_with_dwarf_and_python_api'
Johnny Chena224cd12010-11-08 01:21:03 +0000175-g : if specified, the filterspec by -f is not exclusive, i.e., if a test module
176 does not match the filterspec (testclass.testmethod), the whole module is
177 still admitted to the test suite
Johnny Chenaf149a02010-09-16 17:11:30 +0000178-i : ignore (don't bailout) if 'lldb.py' module cannot be located in the build
179 tree relative to this script; use PYTHONPATH to locate the module
Johnny Chen41998192010-10-01 22:59:49 +0000180-l : don't skip long running test
Johnny Chen7c52ff12010-09-27 23:29:54 +0000181-p : specify a regexp filename pattern for inclusion in the test suite
Johnny Chen548aefd2010-10-11 22:25:46 +0000182-r : specify a dir to relocate the tests and their intermediate files to;
183 the directory must not exist before running this test driver;
184 no cleanup of intermediate test files is performed in this case
Johnny Chen125fc2b2010-10-21 16:55:35 +0000185-s : specify the name of the dir created to store the session files of tests
186 with errored or failed status; if not specified, the test driver uses the
187 timestamp as the session dir name
Johnny Chena2486f22011-04-21 20:48:32 +0000188-t : turn on tracing of lldb command and other detailed test executions
189-v : do verbose mode of unittest framework (print out each test case invocation)
Johnny Chene47649c2010-10-07 02:04:14 +0000190-w : insert some wait time (currently 0.5 sec) between consecutive test cases
Johnny Chend2acdb32010-11-16 22:42:58 +0000191-# : Repeat the test suite for a specified number of times
Johnny Chen9707bb62010-06-25 21:14:08 +0000192
193and:
Johnny Chen9656ab22010-10-22 19:00:18 +0000194args : specify a list of directory names to search for test modules named after
195 Test*.py (test discovery)
Peter Collingbourne5f2b5d62011-06-14 03:55:45 +0000196 if empty, search from the current working directory, instead
Jim Ingham4f347cb2011-04-13 21:11:41 +0000197"""
Johnny Chen58f93922010-06-29 23:10:39 +0000198
Jim Ingham4f347cb2011-04-13 21:11:41 +0000199 if verbose > 0:
200 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000201Examples:
202
Johnny Chena224cd12010-11-08 01:21:03 +0000203This is an example of using the -f option to pinpoint to a specfic test class
204and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000205
Johnny Chena224cd12010-11-08 01:21:03 +0000206$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000207----------------------------------------------------------------------
208Collected 1 test
209
210test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
211Test 'frame variable this' when stopped on a class constructor. ... ok
212
213----------------------------------------------------------------------
214Ran 1 test in 1.396s
215
216OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000217
218And this is an example of using the -p option to run a single file (the filename
219matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
220
221$ ./dotest.py -v -p ObjC
222----------------------------------------------------------------------
223Collected 4 tests
224
225test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000226Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000227test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000228Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000229test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
230Lookup objective-c data types and evaluate expressions. ... ok
231test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
232Lookup objective-c data types and evaluate expressions. ... ok
233
234----------------------------------------------------------------------
235Ran 4 tests in 16.661s
236
237OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000238
Johnny Chen58f93922010-06-29 23:10:39 +0000239Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000240individual test cases can locate their supporting files correctly. The script
241tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000242relative to this script. See also the '-i' option in the following example.
243
244Finally, this is an example of using the lldb.py module distributed/installed by
245Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
246option to add some delay between two tests. It uses ARCH=x86_64 to specify that
247as the architecture and CC=clang to specify the compiler used for the test run:
248
249$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
250
251Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
252----------------------------------------------------------------------
253Collected 2 tests
254
255test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
256Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
257test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
258Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
259
260----------------------------------------------------------------------
261Ran 2 tests in 5.659s
262
263OK
264
265The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
266notify the directory containing the session logs for test failures or errors.
267In case there is any test failure/error, a similar message is appended at the
268end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000269
270Environment variables related to loggings:
271
272o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
273 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
274
275o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
276 'process.gdb-remote' subsystem with a default option of 'packets' if
277 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000278"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000279 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000280
281
Johnny Chenaf149a02010-09-16 17:11:30 +0000282def parseOptionsAndInitTestdirs():
283 """Initialize the list of directories containing our unittest scripts.
284
285 '-h/--help as the first option prints out usage info and exit the program.
286 """
287
Johnny Chen4f93bf12010-12-10 00:51:23 +0000288 global dont_do_python_api_test
289 global just_do_python_api_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000290 global blacklist
291 global blacklistConfig
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000292 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000293 global archs
294 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000295 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000296 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000297 global dumpSysPath
Johnny Chen7d6d8442010-12-03 19:59:35 +0000298 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000299 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000300 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000301 global ignore
Johnny Chen41998192010-10-01 22:59:49 +0000302 global skipLongRunningTest
Johnny Chen7c52ff12010-09-27 23:29:54 +0000303 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000304 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000305 global sdir_name
Johnny Chenaf149a02010-09-16 17:11:30 +0000306 global verbose
307 global testdirs
308
Jim Ingham4f347cb2011-04-13 21:11:41 +0000309 do_help = False
310
Johnny Chenaf149a02010-09-16 17:11:30 +0000311 if len(sys.argv) == 1:
312 return
313
314 # Process possible trace and/or verbose flag, among other things.
315 index = 1
Johnny Chence2212c2010-10-07 15:41:55 +0000316 while index < len(sys.argv):
Johnny Chen4f93bf12010-12-10 00:51:23 +0000317 if sys.argv[index].startswith('-') or sys.argv[index].startswith('+'):
318 # We should continue processing...
319 pass
320 else:
Johnny Chenaf149a02010-09-16 17:11:30 +0000321 # End of option processing.
322 break
323
324 if sys.argv[index].find('-h') != -1:
Jim Ingham4f347cb2011-04-13 21:11:41 +0000325 index += 1
326 do_help = True
Johnny Chen012cba12011-01-26 19:07:42 +0000327 elif sys.argv[index].startswith('-A'):
328 # Increment by 1 to fetch the ARCH spec.
329 index += 1
330 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
331 usage()
Johnny Cheneee9b862011-04-26 20:45:00 +0000332 archs = sys.argv[index].split('^')
Johnny Chen012cba12011-01-26 19:07:42 +0000333 index += 1
334 elif sys.argv[index].startswith('-C'):
335 # Increment by 1 to fetch the CC spec.
336 index += 1
337 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
338 usage()
Johnny Cheneee9b862011-04-26 20:45:00 +0000339 compilers = sys.argv[index].split('^')
Johnny Chen012cba12011-01-26 19:07:42 +0000340 index += 1
Johnny Chen50bc6382011-01-29 01:16:52 +0000341 elif sys.argv[index].startswith('-D'):
342 dumpSysPath = True
343 index += 1
Johnny Chen4f93bf12010-12-10 00:51:23 +0000344 elif sys.argv[index].startswith('-a'):
345 dont_do_python_api_test = True
346 index += 1
347 elif sys.argv[index].startswith('+a'):
348 just_do_python_api_test = True
349 index += 1
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000350 elif sys.argv[index].startswith('-b'):
351 # Increment by 1 to fetch the blacklist file name option argument.
352 index += 1
353 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
354 usage()
355 blacklistFile = sys.argv[index]
356 if not os.path.isfile(blacklistFile):
357 print "Blacklist file:", blacklistFile, "does not exist!"
358 usage()
359 index += 1
360 # Now read the blacklist contents and assign it to blacklist.
361 execfile(blacklistFile, globals(), blacklistConfig)
362 blacklist = blacklistConfig.get('blacklist')
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000363 elif sys.argv[index].startswith('-c'):
364 # Increment by 1 to fetch the config file name option argument.
365 index += 1
366 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
367 usage()
368 configFile = sys.argv[index]
369 if not os.path.isfile(configFile):
370 print "Config file:", configFile, "does not exist!"
371 usage()
372 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000373 elif sys.argv[index].startswith('-d'):
374 delay = True
375 index += 1
Johnny Chen7d6d8442010-12-03 19:59:35 +0000376 elif sys.argv[index].startswith('-F'):
377 failfast = True
378 index += 1
Johnny Chenb62436b2010-10-06 20:40:56 +0000379 elif sys.argv[index].startswith('-f'):
380 # Increment by 1 to fetch the filter spec.
381 index += 1
382 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
383 usage()
Johnny Chenc5fa0052011-07-29 22:54:56 +0000384 filters.append(sys.argv[index])
Johnny Chenb62436b2010-10-06 20:40:56 +0000385 index += 1
386 elif sys.argv[index].startswith('-g'):
Johnny Chena224cd12010-11-08 01:21:03 +0000387 fs4all = False
Johnny Chenb62436b2010-10-06 20:40:56 +0000388 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000389 elif sys.argv[index].startswith('-i'):
390 ignore = True
391 index += 1
Johnny Chen41998192010-10-01 22:59:49 +0000392 elif sys.argv[index].startswith('-l'):
393 skipLongRunningTest = False
394 index += 1
Johnny Chen7c52ff12010-09-27 23:29:54 +0000395 elif sys.argv[index].startswith('-p'):
396 # Increment by 1 to fetch the reg exp pattern argument.
397 index += 1
398 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
399 usage()
400 regexp = sys.argv[index]
401 index += 1
Johnny Chen548aefd2010-10-11 22:25:46 +0000402 elif sys.argv[index].startswith('-r'):
403 # Increment by 1 to fetch the relocated directory argument.
404 index += 1
405 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
406 usage()
407 rdir = os.path.abspath(sys.argv[index])
408 if os.path.exists(rdir):
409 print "Relocated directory:", rdir, "must not exist!"
410 usage()
411 index += 1
Johnny Chen125fc2b2010-10-21 16:55:35 +0000412 elif sys.argv[index].startswith('-s'):
413 # Increment by 1 to fetch the session dir name.
414 index += 1
415 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
416 usage()
417 sdir_name = sys.argv[index]
418 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000419 elif sys.argv[index].startswith('-t'):
420 os.environ["LLDB_COMMAND_TRACE"] = "YES"
421 index += 1
422 elif sys.argv[index].startswith('-v'):
423 verbose = 2
424 index += 1
Johnny Chene47649c2010-10-07 02:04:14 +0000425 elif sys.argv[index].startswith('-w'):
426 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] = 'YES'
427 index += 1
Johnny Chend2acdb32010-11-16 22:42:58 +0000428 elif sys.argv[index].startswith('-#'):
429 # Increment by 1 to fetch the repeat count argument.
430 index += 1
431 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
432 usage()
433 count = int(sys.argv[index])
434 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000435 else:
436 print "Unknown option: ", sys.argv[index]
437 usage()
Johnny Chenaf149a02010-09-16 17:11:30 +0000438
Jim Ingham4f347cb2011-04-13 21:11:41 +0000439 if do_help == True:
440 usage()
441
Johnny Chencc659ad2010-12-10 19:02:23 +0000442 # Do not specify both '-a' and '+a' at the same time.
443 if dont_do_python_api_test and just_do_python_api_test:
444 usage()
445
Johnny Chenaf149a02010-09-16 17:11:30 +0000446 # Gather all the dirs passed on the command line.
447 if len(sys.argv) > index:
448 testdirs = map(os.path.abspath, sys.argv[index:])
449
Johnny Chen548aefd2010-10-11 22:25:46 +0000450 # If '-r dir' is specified, the tests should be run under the relocated
451 # directory. Let's copy the testdirs over.
452 if rdir:
453 from shutil import copytree, ignore_patterns
454
455 tmpdirs = []
456 for srcdir in testdirs:
457 dstdir = os.path.join(rdir, os.path.basename(srcdir))
458 # Don't copy the *.pyc and .svn stuffs.
459 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
460 tmpdirs.append(dstdir)
461
462 # This will be our modified testdirs.
463 testdirs = tmpdirs
464
465 # With '-r dir' specified, there's no cleanup of intermediate test files.
466 os.environ["LLDB_DO_CLEANUP"] = 'NO'
467
468 # If testdirs is ['test'], the make directory has already been copied
469 # recursively and is contained within the rdir/test dir. For anything
470 # else, we would need to copy over the make directory and its contents,
471 # so that, os.listdir(rdir) looks like, for example:
472 #
473 # array_types conditional_break make
474 #
475 # where the make directory contains the Makefile.rules file.
476 if len(testdirs) != 1 or os.path.basename(testdirs[0]) != 'test':
477 # Don't copy the .svn stuffs.
478 copytree('make', os.path.join(rdir, 'make'),
479 ignore=ignore_patterns('.svn'))
480
481 #print "testdirs:", testdirs
482
Johnny Chenb40056b2010-09-21 00:09:27 +0000483 # Source the configFile if specified.
484 # The side effect, if any, will be felt from this point on. An example
485 # config file may be these simple two lines:
486 #
487 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
488 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
489 #
490 # which will reassign the two file objects to sys.stderr and sys.stdout,
491 # respectively.
492 #
493 # See also lldb-trunk/example/test/usage-config.
494 global config
495 if configFile:
496 # Pass config (a dictionary) as the locals namespace for side-effect.
497 execfile(configFile, globals(), config)
498 #print "config:", config
499 #print "sys.stderr:", sys.stderr
500 #print "sys.stdout:", sys.stdout
501
Johnny Chenaf149a02010-09-16 17:11:30 +0000502
Johnny Chen9707bb62010-06-25 21:14:08 +0000503def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000504 """
505 Add LLDB.framework/Resources/Python to the search paths for modules.
506 As a side effect, we also discover the 'lldb' executable and export it here.
507 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000508
Johnny Chen548aefd2010-10-11 22:25:46 +0000509 global rdir
510 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000511 global dumpSysPath
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000512 global svn_info
Johnny Chen548aefd2010-10-11 22:25:46 +0000513
Johnny Chen9707bb62010-06-25 21:14:08 +0000514 # Get the directory containing the current script.
Johnny Chen0de6ab52011-01-19 02:10:40 +0000515 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
516 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
517 else:
518 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000519 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000520 print "This script expects to reside in lldb's test directory."
521 sys.exit(-1)
522
Johnny Chen548aefd2010-10-11 22:25:46 +0000523 if rdir:
524 # Set up the LLDB_TEST environment variable appropriately, so that the
525 # individual tests can be located relatively.
526 #
527 # See also lldbtest.TestBase.setUpClass(cls).
528 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
529 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
530 else:
531 os.environ["LLDB_TEST"] = rdir
532 else:
533 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000534
535 # Set up the LLDB_SRC environment variable, so that the tests can locate
536 # the LLDB source code.
537 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
538
Johnny Chen9de4ede2010-08-31 17:42:54 +0000539 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000540 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000541
Johnny Chen8a3c0432011-03-11 20:13:06 +0000542 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000543 sys.path.append(scriptPath)
544 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000545 sys.path.append(pexpectPath)
Johnny Chenaf149a02010-09-16 17:11:30 +0000546
Johnny Chen26901c82011-03-11 19:47:23 +0000547 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000548 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000549
Johnny Chen26901c82011-03-11 19:47:23 +0000550 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000551 xcode3_build_dir = ['build']
552 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
553 dbg = ['Debug']
554 rel = ['Release']
555 bai = ['BuildAndIntegration']
556 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000557
558 # Some of the tests can invoke the 'lldb' command directly.
559 # We'll try to locate the appropriate executable right here.
560
561 executable = ['lldb']
562 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
563 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
564 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
565 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
566 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
567 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
568
569 lldbExec = None
570 if is_exe(dbgExec):
571 lldbExec = dbgExec
572 elif is_exe(dbgExec2):
573 lldbExec = dbgExec2
574 elif is_exe(relExec):
575 lldbExec = relExec
576 elif is_exe(relExec2):
577 lldbExec = relExec2
578 elif is_exe(baiExec):
579 lldbExec = baiExec
580 elif is_exe(baiExec2):
581 lldbExec = baiExec2
582
583 if not lldbExec:
584 lldbExec = which('lldb')
585
586 if not lldbExec:
587 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
588 else:
589 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chend7931462011-03-17 00:38:22 +0000590 #print "The 'lldb' executable path is", lldbExec
591 os.system('%s -v' % lldbExec)
592
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000593 import subprocess
Johnny Chenb264c9b2011-06-24 22:52:05 +0000594 if os.path.isdir(os.path.join(base, '.svn')):
595 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
596 svn_info = pipe.stdout.read()
597 elif os.path.isdir(os.path.join(base, '.git')):
598 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
599 svn_info = pipe.stdout.read()
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000600 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000601
602 global ignore
603
604 # The '-i' option is used to skip looking for lldb.py in the build tree.
605 if ignore:
606 return
607
Johnny Chen6a564a42011-02-15 18:50:19 +0000608 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
609 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
610 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
611 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
612 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
613 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Johnny Chen9707bb62010-06-25 21:14:08 +0000614
615 lldbPath = None
616 if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
617 lldbPath = dbgPath
Greg Claytond9846b02011-02-14 21:17:06 +0000618 elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')):
619 lldbPath = dbgPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000620 elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
621 lldbPath = relPath
Greg Claytond9846b02011-02-14 21:17:06 +0000622 elif os.path.isfile(os.path.join(relPath2, 'lldb.py')):
623 lldbPath = relPath2
Johnny Chenc202c462010-09-15 18:11:19 +0000624 elif os.path.isfile(os.path.join(baiPath, 'lldb.py')):
625 lldbPath = baiPath
Greg Claytond9846b02011-02-14 21:17:06 +0000626 elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')):
627 lldbPath = baiPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000628
629 if not lldbPath:
Johnny Chenc202c462010-09-15 18:11:19 +0000630 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
631 print relPath + ', or ' + baiPath
Johnny Chen9707bb62010-06-25 21:14:08 +0000632 sys.exit(-1)
633
Johnny Chenaf149a02010-09-16 17:11:30 +0000634 # This is to locate the lldb.py module. Insert it right after sys.path[0].
635 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000636 if dumpSysPath:
637 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000638
Johnny Chen9707bb62010-06-25 21:14:08 +0000639
Johnny Chencd0279d2010-09-20 18:07:50 +0000640def doDelay(delta):
641 """Delaying startup for delta-seconds to facilitate debugger attachment."""
642 def alarm_handler(*args):
643 raise Exception("timeout")
644
645 signal.signal(signal.SIGALRM, alarm_handler)
646 signal.alarm(delta)
647 sys.stdout.write("pid=%d\n" % os.getpid())
648 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
649 delta)
650 sys.stdout.flush()
651 try:
652 text = sys.stdin.readline()
653 except:
654 text = ""
655 signal.alarm(0)
656 sys.stdout.write("proceeding...\n")
657 pass
658
659
Johnny Chen9707bb62010-06-25 21:14:08 +0000660def visit(prefix, dir, names):
661 """Visitor function for os.path.walk(path, visit, arg)."""
662
663 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000664 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000665 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000666 global fs4all
Johnny Chen9707bb62010-06-25 21:14:08 +0000667
668 for name in names:
669 if os.path.isdir(os.path.join(dir, name)):
670 continue
671
672 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000673 # Try to match the regexp pattern, if specified.
674 if regexp:
675 import re
676 if re.search(regexp, name):
677 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
678 pass
679 else:
680 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
681 continue
682
Johnny Chen953864a2010-10-12 21:35:54 +0000683 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000684
685 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000686 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000687 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000688 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000689
690 # Thoroughly check the filterspec against the base module and admit
691 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000692 filterspec = None
693 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000694 # Optimistically set the flag to True.
695 filtered = True
696 module = __import__(base)
697 parts = filterspec.split('.')
698 obj = module
699 for part in parts:
700 try:
701 parent, obj = obj, getattr(obj, part)
702 except AttributeError:
703 # The filterspec has failed.
704 filtered = False
705 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000706
707 # If we reach here, we have a good filterspec. Add it.
708 if filtered:
709 break
710
711 # Forgo this module if the (base, filterspec) combo is invalid
712 # and no '-g' option is specified
713 if filters and fs4all and not filtered:
714 continue
Johnny Chenb62436b2010-10-06 20:40:56 +0000715
Johnny Chen953864a2010-10-12 21:35:54 +0000716 # Add either the filtered test case or the entire test class.
Johnny Chenb62436b2010-10-06 20:40:56 +0000717 if filterspec and filtered:
Johnny Chenc5fa0052011-07-29 22:54:56 +0000718 #print "adding filter spec %s to module %s" % (filterspec, module)
Johnny Chenb62436b2010-10-06 20:40:56 +0000719 suite.addTests(
720 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
721 else:
722 # A simple case of just the module name. Also the failover case
723 # from the filterspec branch when the (base, filterspec) combo
724 # doesn't make sense.
725 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000726
727
Johnny Chencd0279d2010-09-20 18:07:50 +0000728def lldbLoggings():
729 """Check and do lldb loggings if necessary."""
730
731 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
732 # defined. Use ${LLDB_LOG} to specify the log file.
733 ci = lldb.DBG.GetCommandInterpreter()
734 res = lldb.SBCommandReturnObject()
735 if ("LLDB_LOG" in os.environ):
736 if ("LLDB_LOG_OPTION" in os.environ):
737 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
738 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +0000739 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +0000740 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +0000741 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +0000742 res)
743 if not res.Succeeded():
744 raise Exception('log enable failed (check LLDB_LOG env variable.')
745 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
746 # Use ${GDB_REMOTE_LOG} to specify the log file.
747 if ("GDB_REMOTE_LOG" in os.environ):
748 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
749 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
750 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +0000751 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +0000752 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +0000753 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +0000754 + gdb_remote_log_option,
755 res)
756 if not res.Succeeded():
757 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
758
Johnny Chen067022b2011-01-19 19:31:46 +0000759def getMyCommandLine():
760 import subprocess
761 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
762 lines = ps.split('\n')
763 cmd_line = lines[1]
764 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +0000765
Johnny Chend96b5682010-11-05 17:30:53 +0000766# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000767# #
768# Execution of the test driver starts here #
769# #
Johnny Chend96b5682010-11-05 17:30:53 +0000770# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000771
Johnny Chen9707bb62010-06-25 21:14:08 +0000772#
Johnny Chenaf149a02010-09-16 17:11:30 +0000773# Start the actions by first parsing the options while setting up the test
774# directories, followed by setting up the search paths for lldb utilities;
775# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +0000776#
Johnny Chenaf149a02010-09-16 17:11:30 +0000777parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +0000778setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +0000779
780#
781# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
782#
783if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +0000784 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +0000785
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000786#
Johnny Chen41998192010-10-01 22:59:49 +0000787# If '-l' is specified, do not skip the long running tests.
788if not skipLongRunningTest:
789 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
790
791#
Johnny Chen79723352010-10-12 15:53:22 +0000792# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000793#
Johnny Chen9707bb62010-06-25 21:14:08 +0000794for testdir in testdirs:
795 os.path.walk(testdir, visit, 'Test')
796
Johnny Chenb40056b2010-09-21 00:09:27 +0000797#
Johnny Chen9707bb62010-06-25 21:14:08 +0000798# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +0000799#
Johnny Chencd0279d2010-09-20 18:07:50 +0000800
Johnny Chen1bfbd412010-06-29 19:44:16 +0000801# For the time being, let's bracket the test runner within the
802# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000803import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +0000804# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
805# there's no need to call it a second time.
806#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000807atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +0000808
Johnny Chen909e5a62010-07-01 22:52:57 +0000809# Create a singleton SBDebugger in the lldb namespace.
810lldb.DBG = lldb.SBDebugger.Create()
811
Johnny Chen4f93bf12010-12-10 00:51:23 +0000812# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000813lldb.blacklist = blacklist
814
Johnny Chen4f93bf12010-12-10 00:51:23 +0000815# Put dont/just_do_python_api_test in the lldb namespace, too.
816lldb.dont_do_python_api_test = dont_do_python_api_test
817lldb.just_do_python_api_test = just_do_python_api_test
818
Johnny Chencd0279d2010-09-20 18:07:50 +0000819# Turn on lldb loggings if necessary.
820lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +0000821
Johnny Chen7987ac92010-08-09 20:40:52 +0000822# Install the control-c handler.
823unittest2.signals.installHandler()
824
Johnny Chen125fc2b2010-10-21 16:55:35 +0000825# If sdir_name is not specified through the '-s sdir_name' option, get a
826# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
827# be used when/if we want to dump the session info of individual test cases
828# later on.
Johnny Chence681462010-10-19 00:25:01 +0000829#
830# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chen125fc2b2010-10-21 16:55:35 +0000831if not sdir_name:
832 import datetime
Johnny Chen41fae812010-10-29 22:26:38 +0000833 # The windows platforms don't like ':' in the pathname.
Johnny Chen76bd0102010-10-28 16:32:13 +0000834 timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +0000835 sdir_name = timestamp
Peter Collingbourne132476f2011-06-20 23:55:53 +0000836os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +0000837
Johnny Chenab2f0662011-05-06 20:30:22 +0000838sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
839 " will go into directory '%s'\n" % sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +0000840sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +0000841
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000842if not os.path.isdir(sdir_name):
843 os.mkdir(sdir_name)
844fname = os.path.join(sdir_name, "svn-info")
845with open(fname, "w") as f:
846 print >> f, svn_info
847 print >> f, "Command invoked: %s\n" % getMyCommandLine()
848
Johnny Chenb40056b2010-09-21 00:09:27 +0000849#
850# Invoke the default TextTestRunner to run the test suite, possibly iterating
851# over different configurations.
852#
853
Johnny Chenb40056b2010-09-21 00:09:27 +0000854iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +0000855iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +0000856
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000857if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +0000858 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000859
860if isinstance(archs, list) and len(archs) >= 1:
861 iterArchs = True
862
863if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +0000864 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000865
866if isinstance(compilers, list) and len(compilers) >= 1:
867 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +0000868
Johnny Chen953864a2010-10-12 21:35:54 +0000869# Make a shallow copy of sys.path, we need to manipulate the search paths later.
870# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000871if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +0000872 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000873# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
874if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +0000875 old_stderr = sys.stderr
876 old_stdout = sys.stdout
877 new_stderr = None
878 new_stdout = None
879
Johnny Chend96b5682010-11-05 17:30:53 +0000880# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +0000881for ia in range(len(archs) if iterArchs else 1):
882 archConfig = ""
883 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +0000884 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +0000885 archConfig = "arch=%s" % archs[ia]
886 for ic in range(len(compilers) if iterCompilers else 1):
887 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +0000888 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +0000889 configString = "%s compiler=%s" % (archConfig, compilers[ic])
890 else:
891 configString = archConfig
892
Johnny Chenb40056b2010-09-21 00:09:27 +0000893 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000894 # Translate ' ' to '-' for pathname component.
895 from string import maketrans
896 tbl = maketrans(' ', '-')
897 configPostfix = configString.translate(tbl)
898
899 # Check whether we need to split stderr/stdout into configuration
900 # specific files.
901 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
902 if new_stderr:
903 new_stderr.close()
904 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
905 sys.stderr = new_stderr
906 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
907 if new_stdout:
908 new_stdout.close()
909 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
910 sys.stdout = new_stdout
911
Johnny Chen953864a2010-10-12 21:35:54 +0000912 # If we specified a relocated directory to run the test suite, do
913 # the extra housekeeping to copy the testdirs to a configStringified
914 # directory and to update sys.path before invoking the test runner.
915 # The purpose is to separate the configuration-specific directories
916 # from each other.
917 if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +0000918 from shutil import copytree, ignore_patterns
919
Johnny Chen953864a2010-10-12 21:35:54 +0000920 newrdir = "%s.%s" % (rdir, configPostfix)
921
922 # Copy the tree to a new directory with postfix name configPostfix.
923 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
924
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000925 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +0000926 # level test directory.
927 #
928 # See also lldbtest.TestBase.setUpClass(cls).
929 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
930 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
931 else:
932 os.environ["LLDB_TEST"] = newrdir
933
934 # And update the Python search paths for modules.
935 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
936
937 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +0000938 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +0000939
940 #print "sys.stderr name is", sys.stderr.name
941 #print "sys.stdout name is", sys.stdout.name
942
943 # First, write out the number of collected test cases.
944 sys.stderr.write(separator + "\n")
945 sys.stderr.write("Collected %d test%s\n\n"
946 % (suite.countTestCases(),
947 suite.countTestCases() != 1 and "s" or ""))
948
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000949 class LLDBTestResult(unittest2.TextTestResult):
950 """
Johnny Chen26be4532010-11-09 23:56:14 +0000951 Enforce a singleton pattern to allow introspection of test progress.
952
953 Overwrite addError(), addFailure(), and addExpectedFailure() methods
954 to enable each test instance to track its failure/error status. It
955 is used in the LLDB test framework to emit detailed trace messages
956 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000957 """
958 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +0000959 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000960
961 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +0000962 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +0000963 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000964 super(LLDBTestResult, self).__init__(*args)
965 LLDBTestResult.__singleton__ = self
966 # Now put this singleton into the lldb module namespace.
967 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +0000968 # Computes the format string for displaying the counter.
969 global suite
970 counterWidth = len(str(suite.countTestCases()))
971 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +0000972 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +0000973 # This counts from 1 .. suite.countTestCases().
974 self.counter = 0
975
Johnny Chenc87fd492011-01-05 22:50:11 +0000976 def getDescription(self, test):
977 doc_first_line = test.shortDescription()
978 if self.descriptions and doc_first_line:
979 return '\n'.join((str(test), self.indentation + doc_first_line))
980 else:
981 return str(test)
982
Johnny Chen810042e2011-01-05 20:24:11 +0000983 def startTest(self, test):
984 self.counter += 1
985 if self.showAll:
986 self.stream.write(self.fmt % self.counter)
987 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000988
Johnny Chence681462010-10-19 00:25:01 +0000989 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +0000990 global sdir_has_content
991 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +0000992 super(LLDBTestResult, self).addError(test, err)
993 method = getattr(test, "markError", None)
994 if method:
995 method()
996
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000997 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +0000998 global sdir_has_content
999 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001000 super(LLDBTestResult, self).addFailure(test, err)
1001 method = getattr(test, "markFailure", None)
1002 if method:
1003 method()
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001004
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001005 def addExpectedFailure(self, test, err):
1006 global sdir_has_content
1007 sdir_has_content = True
1008 super(LLDBTestResult, self).addExpectedFailure(test, err)
1009 method = getattr(test, "markExpectedFailure", None)
1010 if method:
1011 method()
1012
Johnny Chenab2f0662011-05-06 20:30:22 +00001013 def addUnexpectedSuccess(self, test):
1014 global sdir_has_content
1015 sdir_has_content = True
1016 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1017 method = getattr(test, "markUnexpectedSuccess", None)
1018 if method:
1019 method()
1020
Johnny Chen26be4532010-11-09 23:56:14 +00001021 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001022 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001023 result = unittest2.TextTestRunner(stream=sys.stderr,
1024 verbosity=verbose,
1025 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001026 resultclass=LLDBTestResult).run(suite)
1027 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001028 # We are invoking the same test suite more than once. In this case,
1029 # mark __ignore_singleton__ flag as True so the signleton pattern is
1030 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001031 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001032 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +00001033 result = unittest2.TextTestRunner(stream=sys.stderr,
1034 verbosity=verbose,
1035 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001036 resultclass=LLDBTestResult).run(suite)
Johnny Chenb40056b2010-09-21 00:09:27 +00001037
Johnny Chen1bfbd412010-06-29 19:44:16 +00001038
Johnny Chen63c2cba2010-10-29 22:20:36 +00001039if sdir_has_content:
Johnny Chenab2f0662011-05-06 20:30:22 +00001040 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1041 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001042
Johnny Chencd0279d2010-09-20 18:07:50 +00001043# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1044# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001045if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
1046 import subprocess
1047 print "Terminating Test suite..."
1048 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1049
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001050# Exiting.
1051sys.exit(not result.wasSuccessful)