blob: f422bc50d4e60259d3fbe79a84f6f6ba3ee548f4 [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 Chen82ccf402011-07-30 01:39:58 +000073# By default, benchmarks tests are not run.
74just_do_benchmarks_test = False
75
Johnny Chen82e6b1e2010-12-01 22:47:54 +000076# The blacklist is optional (-b blacklistFile) and allows a central place to skip
77# testclass's and/or testclass.testmethod's.
78blacklist = None
79
80# The dictionary as a result of sourcing blacklistFile.
81blacklistConfig = {}
82
Johnny Chen9fdb0a92010-09-18 00:16:47 +000083# The config file is optional.
84configFile = None
85
Johnny Chend2acdb32010-11-16 22:42:58 +000086# Test suite repeat count. Can be overwritten with '-# count'.
87count = 1
88
Johnny Chenb40056b2010-09-21 00:09:27 +000089# The dictionary as a result of sourcing configFile.
90config = {}
91
Johnny Chen1a4d5e72011-03-04 01:35:22 +000092# The 'archs' and 'compilers' can be specified via either command line or configFile,
93# with the command line overriding the configFile. When specified, they should be
94# of the list type. For example, "-A x86_64^i386" => archs=['x86_64', 'i386'] and
95# "-C gcc^clang" => compilers=['gcc', 'clang'].
96archs = None
97compilers = None
98
Johnny Chen91960d32010-09-08 20:56:16 +000099# Delay startup in order for the debugger to attach.
100delay = False
101
Johnny Chend5362332011-01-29 01:21:04 +0000102# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000103dumpSysPath = False
104
Johnny Chen7d6d8442010-12-03 19:59:35 +0000105# By default, failfast is False. Use '-F' to overwrite it.
106failfast = False
107
Johnny Chenc5fa0052011-07-29 22:54:56 +0000108# The filters (testclass.testmethod) used to admit tests into our test suite.
109filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000110
Johnny Chena224cd12010-11-08 01:21:03 +0000111# If '-g' is specified, the filterspec is not exclusive. If a test module does
112# not contain testclass.testmethod which matches the filterspec, the whole test
113# module is still admitted into our test suite. fs4all flag defaults to True.
114fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000115
Johnny Chenaf149a02010-09-16 17:11:30 +0000116# Ignore the build search path relative to this script to locate the lldb.py module.
117ignore = False
118
Johnny Chen548aefd2010-10-11 22:25:46 +0000119# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen41998192010-10-01 22:59:49 +0000120skipLongRunningTest = True
121
Johnny Chen7c52ff12010-09-27 23:29:54 +0000122# The regular expression pattern to match against eligible filenames as our test cases.
123regexp = None
124
Johnny Chen548aefd2010-10-11 22:25:46 +0000125# By default, tests are executed in place and cleanups are performed afterwards.
126# Use '-r dir' option to relocate the tests and their intermediate files to a
127# different directory and to forgo any cleanups. The directory specified must
128# not exist yet.
129rdir = None
130
Johnny Chen125fc2b2010-10-21 16:55:35 +0000131# By default, recorded session info for errored/failed test are dumped into its
132# own file under a session directory named after the timestamp of the test suite
133# run. Use '-s session-dir-name' to specify a specific dir name.
134sdir_name = None
135
Johnny Chen63c2cba2010-10-29 22:20:36 +0000136# Set this flag if there is any session info dumped during the test run.
137sdir_has_content = False
138
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000139# svn_info stores the output from 'svn info lldb.base.dir'.
140svn_info = ''
141
Johnny Chen9707bb62010-06-25 21:14:08 +0000142# Default verbosity is 0.
143verbose = 0
144
Peter Collingbourne61aca482011-06-20 19:06:29 +0000145# By default, search from the script directory.
146testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000147
Johnny Chen877c7e42010-08-07 00:16:07 +0000148# Separator string.
149separator = '-' * 70
150
Johnny Chen9707bb62010-06-25 21:14:08 +0000151
152def usage():
153 print """
154Usage: dotest.py [option] [args]
155where options:
Jim Ingham4f347cb2011-04-13 21:11:41 +0000156-h : print this help message and exit. Add '-v' for more detailed help.
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000157-A : specify the architecture(s) to launch for the inferior process
158 -A i386 => launch inferior with i386 architecture
159 -A x86_64^i386 => launch inferior with x86_64 and i386 architectures
160-C : specify the compiler(s) used to build the inferior executable
161 -C clang => build debuggee using clang compiler
162 -C clang^gcc => build debuggee using clang and gcc compilers
Johnny Chen50bc6382011-01-29 01:16:52 +0000163-D : dump the Python sys.path variable
Johnny Chen4f93bf12010-12-10 00:51:23 +0000164-a : don't do lldb Python API tests
165 use @python_api_test to decorate a test case as lldb Python API test
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000166+a : just do lldb Python API tests
Johnny Chencc659ad2010-12-10 19:02:23 +0000167 do not specify both '-a' and '+a' at the same time
Johnny Chen82ccf402011-07-30 01:39:58 +0000168+b : just do benchmark tests
169 use @benchmark_test to decorate a test case as such
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000170-b : read a blacklist file specified after this option
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000171-c : read a config file specified after this option
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000172 the architectures and compilers (note the plurals) specified via '-A' and '-C'
173 will override those specified via a config file
Johnny Chenb40056b2010-09-21 00:09:27 +0000174 (see also lldb-trunk/example/test/usage-config)
Johnny Chen91960d32010-09-08 20:56:16 +0000175-d : delay startup for 10 seconds (in order for the debugger to attach)
Johnny Chen7d6d8442010-12-03 19:59:35 +0000176-F : failfast, stop the test suite on the first error/failure
Johnny Chen46be75d2010-10-11 16:19:48 +0000177-f : specify a filter, which consists of the test class name, a dot, followed by
Johnny Chen1a6e92a2010-11-08 20:17:04 +0000178 the test method, to only admit such test into the test suite
Johnny Chenb62436b2010-10-06 20:40:56 +0000179 e.g., -f 'ClassTypesTestCase.test_with_dwarf_and_python_api'
Johnny Chena224cd12010-11-08 01:21:03 +0000180-g : if specified, the filterspec by -f is not exclusive, i.e., if a test module
181 does not match the filterspec (testclass.testmethod), the whole module is
182 still admitted to the test suite
Johnny Chenaf149a02010-09-16 17:11:30 +0000183-i : ignore (don't bailout) if 'lldb.py' module cannot be located in the build
184 tree relative to this script; use PYTHONPATH to locate the module
Johnny Chen41998192010-10-01 22:59:49 +0000185-l : don't skip long running test
Johnny Chen7c52ff12010-09-27 23:29:54 +0000186-p : specify a regexp filename pattern for inclusion in the test suite
Johnny Chen548aefd2010-10-11 22:25:46 +0000187-r : specify a dir to relocate the tests and their intermediate files to;
188 the directory must not exist before running this test driver;
189 no cleanup of intermediate test files is performed in this case
Johnny Chen125fc2b2010-10-21 16:55:35 +0000190-s : specify the name of the dir created to store the session files of tests
191 with errored or failed status; if not specified, the test driver uses the
192 timestamp as the session dir name
Johnny Chena2486f22011-04-21 20:48:32 +0000193-t : turn on tracing of lldb command and other detailed test executions
194-v : do verbose mode of unittest framework (print out each test case invocation)
Johnny Chene47649c2010-10-07 02:04:14 +0000195-w : insert some wait time (currently 0.5 sec) between consecutive test cases
Johnny Chend2acdb32010-11-16 22:42:58 +0000196-# : Repeat the test suite for a specified number of times
Johnny Chen9707bb62010-06-25 21:14:08 +0000197
198and:
Johnny Chen9656ab22010-10-22 19:00:18 +0000199args : specify a list of directory names to search for test modules named after
200 Test*.py (test discovery)
Peter Collingbourne5f2b5d62011-06-14 03:55:45 +0000201 if empty, search from the current working directory, instead
Jim Ingham4f347cb2011-04-13 21:11:41 +0000202"""
Johnny Chen58f93922010-06-29 23:10:39 +0000203
Jim Ingham4f347cb2011-04-13 21:11:41 +0000204 if verbose > 0:
205 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000206Examples:
207
Johnny Chena224cd12010-11-08 01:21:03 +0000208This is an example of using the -f option to pinpoint to a specfic test class
209and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000210
Johnny Chena224cd12010-11-08 01:21:03 +0000211$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000212----------------------------------------------------------------------
213Collected 1 test
214
215test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
216Test 'frame variable this' when stopped on a class constructor. ... ok
217
218----------------------------------------------------------------------
219Ran 1 test in 1.396s
220
221OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000222
223And this is an example of using the -p option to run a single file (the filename
224matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
225
226$ ./dotest.py -v -p ObjC
227----------------------------------------------------------------------
228Collected 4 tests
229
230test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000231Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000232test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000233Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000234test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
235Lookup objective-c data types and evaluate expressions. ... ok
236test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
237Lookup objective-c data types and evaluate expressions. ... ok
238
239----------------------------------------------------------------------
240Ran 4 tests in 16.661s
241
242OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000243
Johnny Chen58f93922010-06-29 23:10:39 +0000244Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000245individual test cases can locate their supporting files correctly. The script
246tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000247relative to this script. See also the '-i' option in the following example.
248
249Finally, this is an example of using the lldb.py module distributed/installed by
250Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
251option to add some delay between two tests. It uses ARCH=x86_64 to specify that
252as the architecture and CC=clang to specify the compiler used for the test run:
253
254$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
255
256Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
257----------------------------------------------------------------------
258Collected 2 tests
259
260test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
261Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
262test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
263Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
264
265----------------------------------------------------------------------
266Ran 2 tests in 5.659s
267
268OK
269
270The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
271notify the directory containing the session logs for test failures or errors.
272In case there is any test failure/error, a similar message is appended at the
273end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000274
275Environment variables related to loggings:
276
277o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
278 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
279
280o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
281 'process.gdb-remote' subsystem with a default option of 'packets' if
282 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000283"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000284 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000285
286
Johnny Chenaf149a02010-09-16 17:11:30 +0000287def parseOptionsAndInitTestdirs():
288 """Initialize the list of directories containing our unittest scripts.
289
290 '-h/--help as the first option prints out usage info and exit the program.
291 """
292
Johnny Chen4f93bf12010-12-10 00:51:23 +0000293 global dont_do_python_api_test
294 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000295 global just_do_benchmarks_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000296 global blacklist
297 global blacklistConfig
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000298 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000299 global archs
300 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000301 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000302 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000303 global dumpSysPath
Johnny Chen7d6d8442010-12-03 19:59:35 +0000304 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000305 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000306 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000307 global ignore
Johnny Chen41998192010-10-01 22:59:49 +0000308 global skipLongRunningTest
Johnny Chen7c52ff12010-09-27 23:29:54 +0000309 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000310 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000311 global sdir_name
Johnny Chenaf149a02010-09-16 17:11:30 +0000312 global verbose
313 global testdirs
314
Jim Ingham4f347cb2011-04-13 21:11:41 +0000315 do_help = False
316
Johnny Chenaf149a02010-09-16 17:11:30 +0000317 if len(sys.argv) == 1:
318 return
319
320 # Process possible trace and/or verbose flag, among other things.
321 index = 1
Johnny Chence2212c2010-10-07 15:41:55 +0000322 while index < len(sys.argv):
Johnny Chen4f93bf12010-12-10 00:51:23 +0000323 if sys.argv[index].startswith('-') or sys.argv[index].startswith('+'):
324 # We should continue processing...
325 pass
326 else:
Johnny Chenaf149a02010-09-16 17:11:30 +0000327 # End of option processing.
328 break
329
330 if sys.argv[index].find('-h') != -1:
Jim Ingham4f347cb2011-04-13 21:11:41 +0000331 index += 1
332 do_help = True
Johnny Chen012cba12011-01-26 19:07:42 +0000333 elif sys.argv[index].startswith('-A'):
334 # Increment by 1 to fetch the ARCH spec.
335 index += 1
336 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
337 usage()
Johnny Cheneee9b862011-04-26 20:45:00 +0000338 archs = sys.argv[index].split('^')
Johnny Chen012cba12011-01-26 19:07:42 +0000339 index += 1
340 elif sys.argv[index].startswith('-C'):
341 # Increment by 1 to fetch the CC spec.
342 index += 1
343 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
344 usage()
Johnny Cheneee9b862011-04-26 20:45:00 +0000345 compilers = sys.argv[index].split('^')
Johnny Chen012cba12011-01-26 19:07:42 +0000346 index += 1
Johnny Chen50bc6382011-01-29 01:16:52 +0000347 elif sys.argv[index].startswith('-D'):
348 dumpSysPath = True
349 index += 1
Johnny Chen4f93bf12010-12-10 00:51:23 +0000350 elif sys.argv[index].startswith('-a'):
351 dont_do_python_api_test = True
352 index += 1
353 elif sys.argv[index].startswith('+a'):
354 just_do_python_api_test = True
355 index += 1
Johnny Chen82ccf402011-07-30 01:39:58 +0000356 elif sys.argv[index].startswith('+b'):
357 just_do_benchmarks_test = True
358 index += 1
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000359 elif sys.argv[index].startswith('-b'):
360 # Increment by 1 to fetch the blacklist file name option argument.
361 index += 1
362 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
363 usage()
364 blacklistFile = sys.argv[index]
365 if not os.path.isfile(blacklistFile):
366 print "Blacklist file:", blacklistFile, "does not exist!"
367 usage()
368 index += 1
369 # Now read the blacklist contents and assign it to blacklist.
370 execfile(blacklistFile, globals(), blacklistConfig)
371 blacklist = blacklistConfig.get('blacklist')
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000372 elif sys.argv[index].startswith('-c'):
373 # Increment by 1 to fetch the config file name option argument.
374 index += 1
375 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
376 usage()
377 configFile = sys.argv[index]
378 if not os.path.isfile(configFile):
379 print "Config file:", configFile, "does not exist!"
380 usage()
381 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000382 elif sys.argv[index].startswith('-d'):
383 delay = True
384 index += 1
Johnny Chen7d6d8442010-12-03 19:59:35 +0000385 elif sys.argv[index].startswith('-F'):
386 failfast = True
387 index += 1
Johnny Chenb62436b2010-10-06 20:40:56 +0000388 elif sys.argv[index].startswith('-f'):
389 # Increment by 1 to fetch the filter spec.
390 index += 1
391 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
392 usage()
Johnny Chenc5fa0052011-07-29 22:54:56 +0000393 filters.append(sys.argv[index])
Johnny Chenb62436b2010-10-06 20:40:56 +0000394 index += 1
395 elif sys.argv[index].startswith('-g'):
Johnny Chena224cd12010-11-08 01:21:03 +0000396 fs4all = False
Johnny Chenb62436b2010-10-06 20:40:56 +0000397 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000398 elif sys.argv[index].startswith('-i'):
399 ignore = True
400 index += 1
Johnny Chen41998192010-10-01 22:59:49 +0000401 elif sys.argv[index].startswith('-l'):
402 skipLongRunningTest = False
403 index += 1
Johnny Chen7c52ff12010-09-27 23:29:54 +0000404 elif sys.argv[index].startswith('-p'):
405 # Increment by 1 to fetch the reg exp pattern argument.
406 index += 1
407 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
408 usage()
409 regexp = sys.argv[index]
410 index += 1
Johnny Chen548aefd2010-10-11 22:25:46 +0000411 elif sys.argv[index].startswith('-r'):
412 # Increment by 1 to fetch the relocated directory argument.
413 index += 1
414 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
415 usage()
416 rdir = os.path.abspath(sys.argv[index])
417 if os.path.exists(rdir):
418 print "Relocated directory:", rdir, "must not exist!"
419 usage()
420 index += 1
Johnny Chen125fc2b2010-10-21 16:55:35 +0000421 elif sys.argv[index].startswith('-s'):
422 # Increment by 1 to fetch the session dir name.
423 index += 1
424 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
425 usage()
426 sdir_name = sys.argv[index]
427 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000428 elif sys.argv[index].startswith('-t'):
429 os.environ["LLDB_COMMAND_TRACE"] = "YES"
430 index += 1
431 elif sys.argv[index].startswith('-v'):
432 verbose = 2
433 index += 1
Johnny Chene47649c2010-10-07 02:04:14 +0000434 elif sys.argv[index].startswith('-w'):
435 os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] = 'YES'
436 index += 1
Johnny Chend2acdb32010-11-16 22:42:58 +0000437 elif sys.argv[index].startswith('-#'):
438 # Increment by 1 to fetch the repeat count argument.
439 index += 1
440 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
441 usage()
442 count = int(sys.argv[index])
443 index += 1
Johnny Chenaf149a02010-09-16 17:11:30 +0000444 else:
445 print "Unknown option: ", sys.argv[index]
446 usage()
Johnny Chenaf149a02010-09-16 17:11:30 +0000447
Jim Ingham4f347cb2011-04-13 21:11:41 +0000448 if do_help == True:
449 usage()
450
Johnny Chencc659ad2010-12-10 19:02:23 +0000451 # Do not specify both '-a' and '+a' at the same time.
452 if dont_do_python_api_test and just_do_python_api_test:
453 usage()
454
Johnny Chenaf149a02010-09-16 17:11:30 +0000455 # Gather all the dirs passed on the command line.
456 if len(sys.argv) > index:
457 testdirs = map(os.path.abspath, sys.argv[index:])
458
Johnny Chen548aefd2010-10-11 22:25:46 +0000459 # If '-r dir' is specified, the tests should be run under the relocated
460 # directory. Let's copy the testdirs over.
461 if rdir:
462 from shutil import copytree, ignore_patterns
463
464 tmpdirs = []
465 for srcdir in testdirs:
466 dstdir = os.path.join(rdir, os.path.basename(srcdir))
467 # Don't copy the *.pyc and .svn stuffs.
468 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
469 tmpdirs.append(dstdir)
470
471 # This will be our modified testdirs.
472 testdirs = tmpdirs
473
474 # With '-r dir' specified, there's no cleanup of intermediate test files.
475 os.environ["LLDB_DO_CLEANUP"] = 'NO'
476
477 # If testdirs is ['test'], the make directory has already been copied
478 # recursively and is contained within the rdir/test dir. For anything
479 # else, we would need to copy over the make directory and its contents,
480 # so that, os.listdir(rdir) looks like, for example:
481 #
482 # array_types conditional_break make
483 #
484 # where the make directory contains the Makefile.rules file.
485 if len(testdirs) != 1 or os.path.basename(testdirs[0]) != 'test':
486 # Don't copy the .svn stuffs.
487 copytree('make', os.path.join(rdir, 'make'),
488 ignore=ignore_patterns('.svn'))
489
490 #print "testdirs:", testdirs
491
Johnny Chenb40056b2010-09-21 00:09:27 +0000492 # Source the configFile if specified.
493 # The side effect, if any, will be felt from this point on. An example
494 # config file may be these simple two lines:
495 #
496 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
497 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
498 #
499 # which will reassign the two file objects to sys.stderr and sys.stdout,
500 # respectively.
501 #
502 # See also lldb-trunk/example/test/usage-config.
503 global config
504 if configFile:
505 # Pass config (a dictionary) as the locals namespace for side-effect.
506 execfile(configFile, globals(), config)
507 #print "config:", config
508 #print "sys.stderr:", sys.stderr
509 #print "sys.stdout:", sys.stdout
510
Johnny Chenaf149a02010-09-16 17:11:30 +0000511
Johnny Chen9707bb62010-06-25 21:14:08 +0000512def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000513 """
514 Add LLDB.framework/Resources/Python to the search paths for modules.
515 As a side effect, we also discover the 'lldb' executable and export it here.
516 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000517
Johnny Chen548aefd2010-10-11 22:25:46 +0000518 global rdir
519 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000520 global dumpSysPath
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000521 global svn_info
Johnny Chen548aefd2010-10-11 22:25:46 +0000522
Johnny Chen9707bb62010-06-25 21:14:08 +0000523 # Get the directory containing the current script.
Johnny Chen0de6ab52011-01-19 02:10:40 +0000524 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
525 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
526 else:
527 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000528 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000529 print "This script expects to reside in lldb's test directory."
530 sys.exit(-1)
531
Johnny Chen548aefd2010-10-11 22:25:46 +0000532 if rdir:
533 # Set up the LLDB_TEST environment variable appropriately, so that the
534 # individual tests can be located relatively.
535 #
536 # See also lldbtest.TestBase.setUpClass(cls).
537 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
538 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
539 else:
540 os.environ["LLDB_TEST"] = rdir
541 else:
542 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000543
544 # Set up the LLDB_SRC environment variable, so that the tests can locate
545 # the LLDB source code.
546 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
547
Johnny Chen9de4ede2010-08-31 17:42:54 +0000548 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000549 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000550
Johnny Chen8a3c0432011-03-11 20:13:06 +0000551 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000552 sys.path.append(scriptPath)
553 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000554 sys.path.append(pexpectPath)
Johnny Chenaf149a02010-09-16 17:11:30 +0000555
Johnny Chen26901c82011-03-11 19:47:23 +0000556 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000557 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000558
Johnny Chen26901c82011-03-11 19:47:23 +0000559 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000560 xcode3_build_dir = ['build']
561 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
562 dbg = ['Debug']
563 rel = ['Release']
564 bai = ['BuildAndIntegration']
565 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000566
567 # Some of the tests can invoke the 'lldb' command directly.
568 # We'll try to locate the appropriate executable right here.
569
570 executable = ['lldb']
571 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
572 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
573 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
574 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
575 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
576 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
577
578 lldbExec = None
579 if is_exe(dbgExec):
580 lldbExec = dbgExec
581 elif is_exe(dbgExec2):
582 lldbExec = dbgExec2
583 elif is_exe(relExec):
584 lldbExec = relExec
585 elif is_exe(relExec2):
586 lldbExec = relExec2
587 elif is_exe(baiExec):
588 lldbExec = baiExec
589 elif is_exe(baiExec2):
590 lldbExec = baiExec2
591
592 if not lldbExec:
593 lldbExec = which('lldb')
594
595 if not lldbExec:
596 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
597 else:
598 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chend7931462011-03-17 00:38:22 +0000599 #print "The 'lldb' executable path is", lldbExec
600 os.system('%s -v' % lldbExec)
601
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000602 import subprocess
Johnny Chenb264c9b2011-06-24 22:52:05 +0000603 if os.path.isdir(os.path.join(base, '.svn')):
604 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
605 svn_info = pipe.stdout.read()
606 elif os.path.isdir(os.path.join(base, '.git')):
607 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
608 svn_info = pipe.stdout.read()
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000609 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000610
611 global ignore
612
613 # The '-i' option is used to skip looking for lldb.py in the build tree.
614 if ignore:
615 return
616
Johnny Chen6a564a42011-02-15 18:50:19 +0000617 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
618 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
619 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
620 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
621 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
622 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Johnny Chen9707bb62010-06-25 21:14:08 +0000623
624 lldbPath = None
625 if os.path.isfile(os.path.join(dbgPath, 'lldb.py')):
626 lldbPath = dbgPath
Greg Claytond9846b02011-02-14 21:17:06 +0000627 elif os.path.isfile(os.path.join(dbgPath2, 'lldb.py')):
628 lldbPath = dbgPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000629 elif os.path.isfile(os.path.join(relPath, 'lldb.py')):
630 lldbPath = relPath
Greg Claytond9846b02011-02-14 21:17:06 +0000631 elif os.path.isfile(os.path.join(relPath2, 'lldb.py')):
632 lldbPath = relPath2
Johnny Chenc202c462010-09-15 18:11:19 +0000633 elif os.path.isfile(os.path.join(baiPath, 'lldb.py')):
634 lldbPath = baiPath
Greg Claytond9846b02011-02-14 21:17:06 +0000635 elif os.path.isfile(os.path.join(baiPath2, 'lldb.py')):
636 lldbPath = baiPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000637
638 if not lldbPath:
Johnny Chenc202c462010-09-15 18:11:19 +0000639 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
640 print relPath + ', or ' + baiPath
Johnny Chen9707bb62010-06-25 21:14:08 +0000641 sys.exit(-1)
642
Johnny Chenaf149a02010-09-16 17:11:30 +0000643 # This is to locate the lldb.py module. Insert it right after sys.path[0].
644 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000645 if dumpSysPath:
646 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000647
Johnny Chen9707bb62010-06-25 21:14:08 +0000648
Johnny Chencd0279d2010-09-20 18:07:50 +0000649def doDelay(delta):
650 """Delaying startup for delta-seconds to facilitate debugger attachment."""
651 def alarm_handler(*args):
652 raise Exception("timeout")
653
654 signal.signal(signal.SIGALRM, alarm_handler)
655 signal.alarm(delta)
656 sys.stdout.write("pid=%d\n" % os.getpid())
657 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
658 delta)
659 sys.stdout.flush()
660 try:
661 text = sys.stdin.readline()
662 except:
663 text = ""
664 signal.alarm(0)
665 sys.stdout.write("proceeding...\n")
666 pass
667
668
Johnny Chen9707bb62010-06-25 21:14:08 +0000669def visit(prefix, dir, names):
670 """Visitor function for os.path.walk(path, visit, arg)."""
671
672 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000673 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000674 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000675 global fs4all
Johnny Chen9707bb62010-06-25 21:14:08 +0000676
677 for name in names:
678 if os.path.isdir(os.path.join(dir, name)):
679 continue
680
681 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000682 # Try to match the regexp pattern, if specified.
683 if regexp:
684 import re
685 if re.search(regexp, name):
686 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
687 pass
688 else:
689 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
690 continue
691
Johnny Chen953864a2010-10-12 21:35:54 +0000692 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000693
694 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000695 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000696 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000697 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000698
699 # Thoroughly check the filterspec against the base module and admit
700 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000701 filterspec = None
702 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000703 # Optimistically set the flag to True.
704 filtered = True
705 module = __import__(base)
706 parts = filterspec.split('.')
707 obj = module
708 for part in parts:
709 try:
710 parent, obj = obj, getattr(obj, part)
711 except AttributeError:
712 # The filterspec has failed.
713 filtered = False
714 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000715
716 # If we reach here, we have a good filterspec. Add it.
717 if filtered:
718 break
719
720 # Forgo this module if the (base, filterspec) combo is invalid
721 # and no '-g' option is specified
722 if filters and fs4all and not filtered:
723 continue
Johnny Chenb62436b2010-10-06 20:40:56 +0000724
Johnny Chen953864a2010-10-12 21:35:54 +0000725 # Add either the filtered test case or the entire test class.
Johnny Chenb62436b2010-10-06 20:40:56 +0000726 if filterspec and filtered:
Johnny Chenc5fa0052011-07-29 22:54:56 +0000727 #print "adding filter spec %s to module %s" % (filterspec, module)
Johnny Chenb62436b2010-10-06 20:40:56 +0000728 suite.addTests(
729 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
730 else:
731 # A simple case of just the module name. Also the failover case
732 # from the filterspec branch when the (base, filterspec) combo
733 # doesn't make sense.
734 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000735
736
Johnny Chencd0279d2010-09-20 18:07:50 +0000737def lldbLoggings():
738 """Check and do lldb loggings if necessary."""
739
740 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
741 # defined. Use ${LLDB_LOG} to specify the log file.
742 ci = lldb.DBG.GetCommandInterpreter()
743 res = lldb.SBCommandReturnObject()
744 if ("LLDB_LOG" in os.environ):
745 if ("LLDB_LOG_OPTION" in os.environ):
746 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
747 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +0000748 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +0000749 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +0000750 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +0000751 res)
752 if not res.Succeeded():
753 raise Exception('log enable failed (check LLDB_LOG env variable.')
754 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
755 # Use ${GDB_REMOTE_LOG} to specify the log file.
756 if ("GDB_REMOTE_LOG" in os.environ):
757 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
758 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
759 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +0000760 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +0000761 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +0000762 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +0000763 + gdb_remote_log_option,
764 res)
765 if not res.Succeeded():
766 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
767
Johnny Chen067022b2011-01-19 19:31:46 +0000768def getMyCommandLine():
769 import subprocess
770 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
771 lines = ps.split('\n')
772 cmd_line = lines[1]
773 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +0000774
Johnny Chend96b5682010-11-05 17:30:53 +0000775# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000776# #
777# Execution of the test driver starts here #
778# #
Johnny Chend96b5682010-11-05 17:30:53 +0000779# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000780
Johnny Chen9707bb62010-06-25 21:14:08 +0000781#
Johnny Chenaf149a02010-09-16 17:11:30 +0000782# Start the actions by first parsing the options while setting up the test
783# directories, followed by setting up the search paths for lldb utilities;
784# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +0000785#
Johnny Chenaf149a02010-09-16 17:11:30 +0000786parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +0000787setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +0000788
789#
790# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
791#
792if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +0000793 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +0000794
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000795#
Johnny Chen41998192010-10-01 22:59:49 +0000796# If '-l' is specified, do not skip the long running tests.
797if not skipLongRunningTest:
798 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
799
800#
Johnny Chen79723352010-10-12 15:53:22 +0000801# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +0000802#
Johnny Chen9707bb62010-06-25 21:14:08 +0000803for testdir in testdirs:
804 os.path.walk(testdir, visit, 'Test')
805
Johnny Chenb40056b2010-09-21 00:09:27 +0000806#
Johnny Chen9707bb62010-06-25 21:14:08 +0000807# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +0000808#
Johnny Chencd0279d2010-09-20 18:07:50 +0000809
Johnny Chen1bfbd412010-06-29 19:44:16 +0000810# For the time being, let's bracket the test runner within the
811# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000812import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +0000813# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
814# there's no need to call it a second time.
815#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +0000816atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +0000817
Johnny Chen909e5a62010-07-01 22:52:57 +0000818# Create a singleton SBDebugger in the lldb namespace.
819lldb.DBG = lldb.SBDebugger.Create()
820
Johnny Chen4f93bf12010-12-10 00:51:23 +0000821# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000822lldb.blacklist = blacklist
823
Johnny Chen4f93bf12010-12-10 00:51:23 +0000824# Put dont/just_do_python_api_test in the lldb namespace, too.
825lldb.dont_do_python_api_test = dont_do_python_api_test
826lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000827lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chen4f93bf12010-12-10 00:51:23 +0000828
Johnny Chencd0279d2010-09-20 18:07:50 +0000829# Turn on lldb loggings if necessary.
830lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +0000831
Johnny Chen7987ac92010-08-09 20:40:52 +0000832# Install the control-c handler.
833unittest2.signals.installHandler()
834
Johnny Chen125fc2b2010-10-21 16:55:35 +0000835# If sdir_name is not specified through the '-s sdir_name' option, get a
836# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
837# be used when/if we want to dump the session info of individual test cases
838# later on.
Johnny Chence681462010-10-19 00:25:01 +0000839#
840# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chen125fc2b2010-10-21 16:55:35 +0000841if not sdir_name:
842 import datetime
Johnny Chen41fae812010-10-29 22:26:38 +0000843 # The windows platforms don't like ':' in the pathname.
Johnny Chen76bd0102010-10-28 16:32:13 +0000844 timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +0000845 sdir_name = timestamp
Peter Collingbourne132476f2011-06-20 23:55:53 +0000846os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +0000847
Johnny Chenab2f0662011-05-06 20:30:22 +0000848sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
849 " will go into directory '%s'\n" % sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +0000850sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +0000851
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000852if not os.path.isdir(sdir_name):
853 os.mkdir(sdir_name)
854fname = os.path.join(sdir_name, "svn-info")
855with open(fname, "w") as f:
856 print >> f, svn_info
857 print >> f, "Command invoked: %s\n" % getMyCommandLine()
858
Johnny Chenb40056b2010-09-21 00:09:27 +0000859#
860# Invoke the default TextTestRunner to run the test suite, possibly iterating
861# over different configurations.
862#
863
Johnny Chenb40056b2010-09-21 00:09:27 +0000864iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +0000865iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +0000866
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000867if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +0000868 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000869
870if isinstance(archs, list) and len(archs) >= 1:
871 iterArchs = True
872
873if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +0000874 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000875
876if isinstance(compilers, list) and len(compilers) >= 1:
877 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +0000878
Johnny Chen953864a2010-10-12 21:35:54 +0000879# Make a shallow copy of sys.path, we need to manipulate the search paths later.
880# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000881if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +0000882 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000883# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
884if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +0000885 old_stderr = sys.stderr
886 old_stdout = sys.stdout
887 new_stderr = None
888 new_stdout = None
889
Johnny Chend96b5682010-11-05 17:30:53 +0000890# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +0000891for ia in range(len(archs) if iterArchs else 1):
892 archConfig = ""
893 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +0000894 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +0000895 archConfig = "arch=%s" % archs[ia]
896 for ic in range(len(compilers) if iterCompilers else 1):
897 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +0000898 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +0000899 configString = "%s compiler=%s" % (archConfig, compilers[ic])
900 else:
901 configString = archConfig
902
Johnny Chenb40056b2010-09-21 00:09:27 +0000903 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000904 # Translate ' ' to '-' for pathname component.
905 from string import maketrans
906 tbl = maketrans(' ', '-')
907 configPostfix = configString.translate(tbl)
908
909 # Check whether we need to split stderr/stdout into configuration
910 # specific files.
911 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
912 if new_stderr:
913 new_stderr.close()
914 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
915 sys.stderr = new_stderr
916 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
917 if new_stdout:
918 new_stdout.close()
919 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
920 sys.stdout = new_stdout
921
Johnny Chen953864a2010-10-12 21:35:54 +0000922 # If we specified a relocated directory to run the test suite, do
923 # the extra housekeeping to copy the testdirs to a configStringified
924 # directory and to update sys.path before invoking the test runner.
925 # The purpose is to separate the configuration-specific directories
926 # from each other.
927 if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +0000928 from shutil import copytree, ignore_patterns
929
Johnny Chen953864a2010-10-12 21:35:54 +0000930 newrdir = "%s.%s" % (rdir, configPostfix)
931
932 # Copy the tree to a new directory with postfix name configPostfix.
933 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
934
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000935 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +0000936 # level test directory.
937 #
938 # See also lldbtest.TestBase.setUpClass(cls).
939 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
940 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
941 else:
942 os.environ["LLDB_TEST"] = newrdir
943
944 # And update the Python search paths for modules.
945 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
946
947 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +0000948 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +0000949
950 #print "sys.stderr name is", sys.stderr.name
951 #print "sys.stdout name is", sys.stdout.name
952
953 # First, write out the number of collected test cases.
954 sys.stderr.write(separator + "\n")
955 sys.stderr.write("Collected %d test%s\n\n"
956 % (suite.countTestCases(),
957 suite.countTestCases() != 1 and "s" or ""))
958
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000959 class LLDBTestResult(unittest2.TextTestResult):
960 """
Johnny Chen26be4532010-11-09 23:56:14 +0000961 Enforce a singleton pattern to allow introspection of test progress.
962
963 Overwrite addError(), addFailure(), and addExpectedFailure() methods
964 to enable each test instance to track its failure/error status. It
965 is used in the LLDB test framework to emit detailed trace messages
966 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000967 """
968 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +0000969 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000970
971 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +0000972 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +0000973 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000974 super(LLDBTestResult, self).__init__(*args)
975 LLDBTestResult.__singleton__ = self
976 # Now put this singleton into the lldb module namespace.
977 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +0000978 # Computes the format string for displaying the counter.
979 global suite
980 counterWidth = len(str(suite.countTestCases()))
981 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +0000982 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +0000983 # This counts from 1 .. suite.countTestCases().
984 self.counter = 0
985
Johnny Chenc87fd492011-01-05 22:50:11 +0000986 def getDescription(self, test):
987 doc_first_line = test.shortDescription()
988 if self.descriptions and doc_first_line:
989 return '\n'.join((str(test), self.indentation + doc_first_line))
990 else:
991 return str(test)
992
Johnny Chen810042e2011-01-05 20:24:11 +0000993 def startTest(self, test):
994 self.counter += 1
995 if self.showAll:
996 self.stream.write(self.fmt % self.counter)
997 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +0000998
Johnny Chence681462010-10-19 00:25:01 +0000999 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001000 global sdir_has_content
1001 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001002 super(LLDBTestResult, self).addError(test, err)
1003 method = getattr(test, "markError", None)
1004 if method:
1005 method()
1006
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001007 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001008 global sdir_has_content
1009 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001010 super(LLDBTestResult, self).addFailure(test, err)
1011 method = getattr(test, "markFailure", None)
1012 if method:
1013 method()
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001014
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001015 def addExpectedFailure(self, test, err):
1016 global sdir_has_content
1017 sdir_has_content = True
1018 super(LLDBTestResult, self).addExpectedFailure(test, err)
1019 method = getattr(test, "markExpectedFailure", None)
1020 if method:
1021 method()
1022
Johnny Chenab2f0662011-05-06 20:30:22 +00001023 def addUnexpectedSuccess(self, test):
1024 global sdir_has_content
1025 sdir_has_content = True
1026 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1027 method = getattr(test, "markUnexpectedSuccess", None)
1028 if method:
1029 method()
1030
Johnny Chen26be4532010-11-09 23:56:14 +00001031 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001032 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001033 result = unittest2.TextTestRunner(stream=sys.stderr,
1034 verbosity=verbose,
1035 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001036 resultclass=LLDBTestResult).run(suite)
1037 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001038 # We are invoking the same test suite more than once. In this case,
1039 # mark __ignore_singleton__ flag as True so the signleton pattern is
1040 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001041 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001042 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +00001043 result = unittest2.TextTestRunner(stream=sys.stderr,
1044 verbosity=verbose,
1045 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001046 resultclass=LLDBTestResult).run(suite)
Johnny Chenb40056b2010-09-21 00:09:27 +00001047
Johnny Chen1bfbd412010-06-29 19:44:16 +00001048
Johnny Chen63c2cba2010-10-29 22:20:36 +00001049if sdir_has_content:
Johnny Chenab2f0662011-05-06 20:30:22 +00001050 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1051 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001052
Johnny Chencd0279d2010-09-20 18:07:50 +00001053# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1054# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001055if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
1056 import subprocess
1057 print "Terminating Test suite..."
1058 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1059
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001060# Exiting.
1061sys.exit(not result.wasSuccessful)