blob: 36678c2abec18f6db8e6e6f4a6e72cffa75c8184 [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
Greg Clayton4793e942012-09-04 15:42:49 +000023import argparse
24import os
25import platform
26import signal
Johnny Chen2891bb02011-09-16 01:04:26 +000027import subprocess
Greg Clayton4793e942012-09-04 15:42:49 +000028import sys
29import textwrap
30import time
Johnny Chen75e28f92010-08-05 23:42:46 +000031import unittest2
Johnny Chen9707bb62010-06-25 21:14:08 +000032
Johnny Chen26901c82011-03-11 19:47:23 +000033def is_exe(fpath):
Johnny Chenf2c7b282011-04-26 23:10:51 +000034 """Returns true if fpath is an executable."""
Johnny Chen26901c82011-03-11 19:47:23 +000035 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
36
Johnny Chen26901c82011-03-11 19:47:23 +000037def which(program):
Johnny Chenf2c7b282011-04-26 23:10:51 +000038 """Returns the full path to a program; None otherwise."""
Johnny Chen26901c82011-03-11 19:47:23 +000039 fpath, fname = os.path.split(program)
40 if fpath:
41 if is_exe(program):
42 return program
43 else:
44 for path in os.environ["PATH"].split(os.pathsep):
45 exe_file = os.path.join(path, program)
46 if is_exe(exe_file):
47 return exe_file
48 return None
49
Johnny Chen877c7e42010-08-07 00:16:07 +000050class _WritelnDecorator(object):
51 """Used to decorate file-like objects with a handy 'writeln' method"""
52 def __init__(self,stream):
53 self.stream = stream
54
55 def __getattr__(self, attr):
56 if attr in ('stream', '__getstate__'):
57 raise AttributeError(attr)
58 return getattr(self.stream,attr)
59
60 def writeln(self, arg=None):
61 if arg:
62 self.write(arg)
63 self.write('\n') # text-mode streams translate to \r\n if needed
64
Johnny Chen9707bb62010-06-25 21:14:08 +000065#
66# Global variables:
67#
68
Enrico Granataac3a8e22012-09-21 19:10:53 +000069# Dictionary of categories
70# When you define a new category for your testcases, be sure to add it here, or the test suite
71# will gladly complain as soon as you try to use it. This allows us to centralize which categories
72# exist, and to provide a description for each one
73validCategories = {
74'dataformatters':'Tests related to the type command and the data formatters subsystem',
75'expression':'Tests related to the expression parser',
76'objc':'Tests related to the Objective-C programming language support',
77'pyapi':'Tests related to the Python API'
78}
79
Johnny Chen9707bb62010-06-25 21:14:08 +000080# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000081suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000082
Johnny Chen4f93bf12010-12-10 00:51:23 +000083# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000084# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
85# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000086dont_do_python_api_test = False
87
88# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000089just_do_python_api_test = False
90
Johnny Chen82ccf402011-07-30 01:39:58 +000091# By default, benchmarks tests are not run.
92just_do_benchmarks_test = False
93
Johnny Chena3ed7d82012-04-06 00:56:05 +000094# By default, both dsym and dwarf tests are performed.
95# Use @dsym_test or @dwarf_test decorators, defined in lldbtest.py, to mark a test
96# as a dsym or dwarf test. Use '-N dsym' or '-N dwarf' to exclude dsym or dwarf
97# tests from running.
98dont_do_dsym_test = False
99dont_do_dwarf_test = False
100
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000101# The blacklist is optional (-b blacklistFile) and allows a central place to skip
102# testclass's and/or testclass.testmethod's.
103blacklist = None
104
105# The dictionary as a result of sourcing blacklistFile.
106blacklistConfig = {}
107
Enrico Granataac3a8e22012-09-21 19:10:53 +0000108# The list of categories we said we care about
109categoriesList = None
110# set to true if we are going to use categories for cherry-picking test cases
111useCategories = False
112# use this to track per-category failures
113failuresPerCategory = {}
114
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000115# The config file is optional.
116configFile = None
117
Johnny Chend2acdb32010-11-16 22:42:58 +0000118# Test suite repeat count. Can be overwritten with '-# count'.
119count = 1
120
Johnny Chenb40056b2010-09-21 00:09:27 +0000121# The dictionary as a result of sourcing configFile.
122config = {}
Johnny Chenac97a6b2012-04-16 18:55:15 +0000123# The pre_flight and post_flight functions come from reading a config file.
124pre_flight = None
125post_flight = None
Johnny Chenb40056b2010-09-21 00:09:27 +0000126
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000127# The 'archs' and 'compilers' can be specified via either command line or configFile,
Greg Clayton4793e942012-09-04 15:42:49 +0000128# with the command line overriding the configFile. The corresponding options can be
129# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386']
130# and "-C gcc -C clang" => compilers=['gcc', 'clang'].
131archs = None # Must be initialized after option parsing
132compilers = None # Must be initialized after option parsing
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000133
Johnny Chen1abe4c02012-03-20 00:33:51 +0000134# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
135# the inferior programs. The global variable cflags_extras provides a hook to do
136# just that.
137cflags_extras = ''
138
Johnny Chen91960d32010-09-08 20:56:16 +0000139# Delay startup in order for the debugger to attach.
140delay = False
141
Johnny Chend5362332011-01-29 01:21:04 +0000142# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000143dumpSysPath = False
144
Johnny Chene00c9302011-10-10 22:03:44 +0000145# Full path of the benchmark executable, as specified by the '-e' option.
146bmExecutable = None
147# The breakpoint specification of bmExecutable, as specified by the '-x' option.
148bmBreakpointSpec = None
Johnny Chen5f2ed172011-10-20 18:43:28 +0000149# The benchamrk iteration count, as specified by the '-y' option.
150bmIterationCount = -1
Johnny Chene00c9302011-10-10 22:03:44 +0000151
Johnny Chene9eae812012-01-18 05:15:00 +0000152# By default, don't exclude any directories. Use '-X' to add one excluded directory.
153excluded = set(['.svn', '.git'])
154
Johnny Chen7d6d8442010-12-03 19:59:35 +0000155# By default, failfast is False. Use '-F' to overwrite it.
156failfast = False
157
Johnny Chenc5fa0052011-07-29 22:54:56 +0000158# The filters (testclass.testmethod) used to admit tests into our test suite.
159filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000160
Johnny Chen38f823c2011-10-11 01:30:27 +0000161# The runhooks is a list of lldb commands specifically for the debugger.
162# Use '-k' to specify a runhook.
163runHooks = []
164
Johnny Chena224cd12010-11-08 01:21:03 +0000165# If '-g' is specified, the filterspec is not exclusive. If a test module does
166# not contain testclass.testmethod which matches the filterspec, the whole test
167# module is still admitted into our test suite. fs4all flag defaults to True.
168fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000169
Johnny Chenaf149a02010-09-16 17:11:30 +0000170# Ignore the build search path relative to this script to locate the lldb.py module.
171ignore = False
172
Johnny Chen028d8eb2011-11-17 19:57:27 +0000173# By default, we do not skip build and cleanup. Use '-S' option to override.
174skip_build_and_cleanup = False
175
Johnny Chen548aefd2010-10-11 22:25:46 +0000176# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000177skip_long_running_test = True
Johnny Chen41998192010-10-01 22:59:49 +0000178
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000179# By default, we print the build dir, lldb version, and svn info. Use '-n' option to
180# turn it off.
181noHeaders = False
182
Johnny Chen7c52ff12010-09-27 23:29:54 +0000183# The regular expression pattern to match against eligible filenames as our test cases.
184regexp = None
185
Johnny Chen548aefd2010-10-11 22:25:46 +0000186# By default, tests are executed in place and cleanups are performed afterwards.
187# Use '-r dir' option to relocate the tests and their intermediate files to a
188# different directory and to forgo any cleanups. The directory specified must
189# not exist yet.
190rdir = None
191
Johnny Chen125fc2b2010-10-21 16:55:35 +0000192# By default, recorded session info for errored/failed test are dumped into its
193# own file under a session directory named after the timestamp of the test suite
194# run. Use '-s session-dir-name' to specify a specific dir name.
195sdir_name = None
196
Johnny Chen63c2cba2010-10-29 22:20:36 +0000197# Set this flag if there is any session info dumped during the test run.
198sdir_has_content = False
199
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000200# svn_info stores the output from 'svn info lldb.base.dir'.
201svn_info = ''
202
Johnny Chen0f907b82012-01-31 00:38:03 +0000203# The environment variables to unset before running the test cases.
204unsets = []
205
Johnny Chen9707bb62010-06-25 21:14:08 +0000206# Default verbosity is 0.
207verbose = 0
208
Johnny Chen08967192011-11-18 00:19:29 +0000209# Set to True only if verbose is 0 and LLDB trace mode is off.
210progress_bar = False
211
Peter Collingbourne61aca482011-06-20 19:06:29 +0000212# By default, search from the script directory.
213testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000214
Johnny Chen877c7e42010-08-07 00:16:07 +0000215# Separator string.
216separator = '-' * 70
217
Johnny Chen9707bb62010-06-25 21:14:08 +0000218
Greg Clayton4793e942012-09-04 15:42:49 +0000219def usage(parser):
220 parser.print_help()
Jim Ingham4f347cb2011-04-13 21:11:41 +0000221 if verbose > 0:
222 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000223Examples:
224
Johnny Chena224cd12010-11-08 01:21:03 +0000225This is an example of using the -f option to pinpoint to a specfic test class
226and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000227
Johnny Chena224cd12010-11-08 01:21:03 +0000228$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000229----------------------------------------------------------------------
230Collected 1 test
231
232test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
233Test 'frame variable this' when stopped on a class constructor. ... ok
234
235----------------------------------------------------------------------
236Ran 1 test in 1.396s
237
238OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000239
240And this is an example of using the -p option to run a single file (the filename
241matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
242
243$ ./dotest.py -v -p ObjC
244----------------------------------------------------------------------
245Collected 4 tests
246
247test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000248Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000249test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000250Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000251test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
252Lookup objective-c data types and evaluate expressions. ... ok
253test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
254Lookup objective-c data types and evaluate expressions. ... ok
255
256----------------------------------------------------------------------
257Ran 4 tests in 16.661s
258
259OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000260
Johnny Chen58f93922010-06-29 23:10:39 +0000261Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000262individual test cases can locate their supporting files correctly. The script
263tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000264relative to this script. See also the '-i' option in the following example.
265
266Finally, this is an example of using the lldb.py module distributed/installed by
267Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
268option to add some delay between two tests. It uses ARCH=x86_64 to specify that
269as the architecture and CC=clang to specify the compiler used for the test run:
270
271$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
272
273Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
274----------------------------------------------------------------------
275Collected 2 tests
276
277test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
278Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
279test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
280Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
281
282----------------------------------------------------------------------
283Ran 2 tests in 5.659s
284
285OK
286
287The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
288notify the directory containing the session logs for test failures or errors.
289In case there is any test failure/error, a similar message is appended at the
290end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000291
292Environment variables related to loggings:
293
294o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
295 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
296
297o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
298 'process.gdb-remote' subsystem with a default option of 'packets' if
299 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000300"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000301 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000302
303
Johnny Chenaf149a02010-09-16 17:11:30 +0000304def parseOptionsAndInitTestdirs():
305 """Initialize the list of directories containing our unittest scripts.
306
307 '-h/--help as the first option prints out usage info and exit the program.
308 """
309
Johnny Chen4f93bf12010-12-10 00:51:23 +0000310 global dont_do_python_api_test
311 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000312 global just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +0000313 global dont_do_dsym_test
314 global dont_do_dwarf_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000315 global blacklist
316 global blacklistConfig
Enrico Granataac3a8e22012-09-21 19:10:53 +0000317 global categoriesList
318 global validCategories
319 global useCategories
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000320 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000321 global archs
322 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000323 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000324 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000325 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000326 global bmExecutable
327 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000328 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000329 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000330 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000331 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000332 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000333 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000334 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000335 global skip_build_and_cleanup
336 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000337 global noHeaders
Johnny Chen7c52ff12010-09-27 23:29:54 +0000338 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000339 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000340 global sdir_name
Johnny Chen0f907b82012-01-31 00:38:03 +0000341 global unsets
Johnny Chenaf149a02010-09-16 17:11:30 +0000342 global verbose
343 global testdirs
344
Jim Ingham4f347cb2011-04-13 21:11:41 +0000345 do_help = False
346
Greg Clayton4793e942012-09-04 15:42:49 +0000347 parser = argparse.ArgumentParser(description='description', prefix_chars='+-', add_help=False)
348 group = None
Johnny Chenaf149a02010-09-16 17:11:30 +0000349
Greg Clayton4793e942012-09-04 15:42:49 +0000350 # Helper function for boolean options (group will point to the current group when executing X)
351 X = lambda optstr, helpstr, **kwargs: group.add_argument(optstr, help=helpstr, action='store_true', **kwargs)
352
353 group = parser.add_argument_group('Help')
354 group.add_argument('-h', '--help', dest='h', action='store_true', help="Print this help message and exit. Add '-v' for more detailed help.")
355
356 # C and Python toolchain options
357 group = parser.add_argument_group('Toolchain options')
358 group.add_argument('-A', '--arch', metavar='arch', action='append', dest='archs', help=textwrap.dedent('''Specify the architecture(s) to test. This option can be specified more than once'''))
359 group.add_argument('-C', '--compiler', metavar='compiler', dest='compilers', action='append', help=textwrap.dedent('''Specify the compiler(s) used to build the inferior executables. The compiler path can be an executable basename or a full path to a compiler executable. This option can be specified multiple times.'''))
360 # FIXME? This won't work for different extra flags according to each arch.
361 group.add_argument('-E', metavar='extra-flags', help=textwrap.dedent('''Specify the extra flags to be passed to the toolchain when building the inferior programs to be debugged
362 suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
363 X('-D', 'Dump the Python sys.path variable')
364
365 # Test filtering options
366 group = parser.add_argument_group('Test filtering options')
367 group.add_argument('-N', choices=['dwarf', 'dsym'], help="Don't do test cases marked with the @dsym decorator by passing 'dsym' as the option arg, or don't do test cases marked with the @dwarf decorator by passing 'dwarf' as the option arg")
368 X('-a', "Don't do lldb Python API tests")
369 X('+a', "Just do lldb Python API tests. Do not specify along with '+a'", dest='plus_a')
370 X('+b', 'Just do benchmark tests', dest='plus_b')
371 group.add_argument('-b', metavar='blacklist', help='Read a blacklist file specified after this option')
372 group.add_argument('-f', metavar='filterspec', help='Specify a filter, which consists of the test class name, a dot, followed by the test method, to only admit such test into the test suite') # FIXME: Example?
373 X('-g', 'If specified, the filterspec by -f is not exclusive, i.e., if a test module does not match the filterspec (testclass.testmethod), the whole module is still admitted to the test suite')
374 X('-l', "Don't skip long running tests")
375 group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite')
376 group.add_argument('-X', metavar='directory', help="Exclude a directory from consideration for test discovery. -X types => if 'types' appear in the pathname components of a potential testfile, it will be ignored")
Enrico Granataac3a8e22012-09-21 19:10:53 +0000377 group.add_argument('-G', '--category', metavar='category', action='append', dest='categoriesList', help=textwrap.dedent('''Specify categories of test cases of interest. Can be specified more than once.'''))
Greg Clayton4793e942012-09-04 15:42:49 +0000378
379 # Configuration options
380 group = parser.add_argument_group('Configuration options')
381 group.add_argument('-c', metavar='config-file', help='Read a config file specified after this option') # FIXME: additional doc.
382 group.add_argument('-e', metavar='benchmark-exe', help='Specify the full path of an executable used for benchmark purposes (see also: -x)')
383 group.add_argument('-k', metavar='command', action='append', help="Specify a runhook, which is an lldb command to be executed by the debugger; The option can occur multiple times. The commands are executed one after the other to bring the debugger to a desired state, so that, for example, further benchmarking can be done")
384 group.add_argument('-R', metavar='dir', help='Specify a directory to relocate the tests and their intermediate files to. BE WARNED THAT the directory, if exists, will be deleted before running this test driver. No cleanup of intermediate test files is performed in this case')
385 group.add_argument('-r', metavar='dir', help="Similar to '-R', except that the directory must not exist before running this test driver")
386 group.add_argument('-s', metavar='name', help='Specify the name of the dir created to store the session files of tests with errored or failed status. If not specified, the test driver uses the timestamp as the session dir name')
387 group.add_argument('-x', metavar='breakpoint-spec', help='Specify the breakpoint specification for the benchmark executable')
388 group.add_argument('-y', type=int, metavar='count', help="Specify the iteration count used to collect our benchmarks. An example is the number of times to do 'thread step-over' to measure stepping speed.")
389 group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times')
390
391 # Test-suite behaviour
392 group = parser.add_argument_group('Runtime behaviour options')
393 X('-d', 'Delay startup for 10 seconds (in order for the debugger to attach)')
394 X('-F', 'Fail fast. Stop the test suite on the first error/failure')
395 X('-i', "Ignore (don't bailout) if 'lldb.py' module cannot be located in the build tree relative to this script; use PYTHONPATH to locate the module")
396 X('-n', "Don't print the headers like build dir, lldb version, and svn info at all")
397 X('-S', "Skip the build and cleanup while running the test. Use this option with care as you would need to build the inferior(s) by hand and build the executable(s) with the correct name(s). This can be used with '-# n' to stress test certain test cases for n number of times")
398 X('-t', 'Turn on tracing of lldb command and other detailed test executions')
399 group.add_argument('-u', metavar='variable', action='append', help='Specify an environment variable to unset before running the test cases. e.g., -u DYLD_INSERT_LIBRARIES -u MallocScribble')
400 X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
401 X('-w', 'Insert some wait time (currently 0.5 sec) between consecutive test cases')
402
403 # Remove the reference to our helper function
404 del X
405
406 group = parser.add_argument_group('Test directories')
407 group.add_argument('args', metavar='test-dir', nargs='*', help='Specify a list of directory names to search for test modules named after Test*.py (test discovery). If empty, search from the current working directory instead.')
408 args = parser.parse_args()
409
410 platform_system = platform.system()
411 platform_machine = platform.machine()
412 print args
413
414 if args.h:
415 do_help = True
416
417 if args.archs:
418 archs = args.archs
419 else:
420 if platform_system == 'Darwin' and platform_machine == 'x86_64':
421 archs = ['x86_64', 'i386']
Johnny Chenaf149a02010-09-16 17:11:30 +0000422 else:
Greg Clayton4793e942012-09-04 15:42:49 +0000423 archs = [platform_machine]
424
Enrico Granataac3a8e22012-09-21 19:10:53 +0000425 if args.categoriesList:
426 for category in args.categoriesList:
427 if not(category in validCategories):
428 print "fatal error: category '" + category + "' is not a valid category - edit dotest.py or correct your invocation"
429 sys.exit(1)
430 categoriesList = set(args.categoriesList)
431 useCategories = True
432 else:
433 categoriesList = []
434
Greg Clayton4793e942012-09-04 15:42:49 +0000435 if args.compilers:
436 compilers = args.compilers
437 else:
438 compilers = ['clang']
439
440 if args.D:
441 dumpSysPath = True
442
443 if args.E:
444 cflags_extras = args.E
445 os.environ['CFLAGS_EXTRAS'] = cflags_extras
446
447 # argparse makes sure we have correct options
448 if args.N == 'dwarf':
449 dont_do_dwarf_test = True
450 elif args.N == 'dsym':
451 dont_do_dsym_test = True
452
453 if args.a:
454 dont_do_python_api_test = True
455
456 if args.plus_a:
457 if dont_do_python_api_test:
458 print "Warning: -a and +a can't both be specified! Using only -a"
459 else:
460 just_do_python_api_test = True
461
462 if args.plus_b:
463 just_do_benchmarks_test = True
464
465 if args.b:
466 if args.b.startswith('-'):
467 usage(parser)
468 blacklistFile = args.b
469 if not os.path.isfile(blacklistFile):
470 print 'Blacklist file:', blacklistFile, 'does not exist!'
471 usage(parser)
472 # Now read the blacklist contents and assign it to blacklist.
473 execfile(blacklistFile, globals(), blacklistConfig)
474 blacklist = blacklistConfig.get('blacklist')
475
476 if args.c:
477 if args.c.startswith('-'):
478 usage(parser)
479 configFile = args.c
480 if not os.path.isfile(configFile):
481 print 'Config file:', configFile, 'does not exist!'
482 usage(parser)
483
484 if args.d:
485 delay = True
486
487 if args.e:
488 if args.e.startswith('-'):
489 usage(parser)
490 bmExecutable = args.e
491 if not is_exe(bmExecutable):
492 usage(parser)
493
494 if args.F:
495 failfast = True
496
497 if args.f:
498 if args.f.startswith('-'):
499 usage(parser)
500 filters.append(args.f)
501
502 if args.g:
503 fs4all = False
504
505 if args.i:
506 ignore = True
507
508 if args.k:
509 runHooks.extend(args.k)
510
511 if args.l:
512 skip_long_running_test = False
513
514 if args.n:
515 noHeaders = True
516
517 if args.p:
518 if args.p.startswith('-'):
519 usage(parser)
520 regexp = args.p
521
522 if args.R:
523 if args.R.startswith('-'):
524 usage(parser)
525 rdir = os.path.abspath(args.R)
526 if os.path.exists(rdir):
527 import shutil
528 print 'Removing tree:', rdir
529 shutil.rmtree(rdir)
530
531 if args.r:
532 if args.r.startswith('-'):
533 usage(parser)
534 rdir = os.path.abspath(args.r)
535 if os.path.exists(rdir):
536 print 'Relocated directory:', rdir, 'must not exist!'
537 usage(parser)
538
539 if args.S:
540 skip_build_and_cleanup = True
541
542 if args.s:
543 if args.s.startswith('-'):
544 usage(parser)
545 sdir_name = args.s
546
547 if args.t:
548 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
549
550 if args.u:
551 unsets.extend(args.u)
552
553 if args.v:
554 verbose = 2
555
556 if args.w:
557 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
558
559 if args.X:
560 if args.X.startswith('-'):
561 usage(parser)
562 excluded.add(args.X)
563
564 if args.x:
565 if args.x.startswith('-'):
566 usage(parser)
567 bmBreakpointSpec = args.x
568
569 # argparse makes sure we have a number
570 if args.y:
571 bmIterationCount = args.y
572
573 # argparse makes sure we have a number
574 if args.sharp:
575 count = args.sharp
Johnny Chenaf149a02010-09-16 17:11:30 +0000576
Jim Ingham4f347cb2011-04-13 21:11:41 +0000577 if do_help == True:
Greg Clayton4793e942012-09-04 15:42:49 +0000578 usage(parser)
Jim Ingham4f347cb2011-04-13 21:11:41 +0000579
Johnny Chencc659ad2010-12-10 19:02:23 +0000580 # Do not specify both '-a' and '+a' at the same time.
581 if dont_do_python_api_test and just_do_python_api_test:
Greg Clayton4793e942012-09-04 15:42:49 +0000582 usage(parser)
Johnny Chencc659ad2010-12-10 19:02:23 +0000583
Johnny Chen08967192011-11-18 00:19:29 +0000584 # The simple progress bar is turned on only if verbose == 0 and LLDB_COMMAND_TRACE is not 'YES'
Greg Clayton4793e942012-09-04 15:42:49 +0000585 if ("LLDB_COMMAND_TRACE" not in os.environ or os.environ["LLDB_COMMAND_TRACE"] != "YES") and verbose == 0:
Johnny Chen08967192011-11-18 00:19:29 +0000586 progress_bar = True
587
Johnny Chenaf149a02010-09-16 17:11:30 +0000588 # Gather all the dirs passed on the command line.
Greg Clayton4793e942012-09-04 15:42:49 +0000589 if len(args.args) > 0:
590 testdirs = map(os.path.abspath, args.args)
Johnny Chenaf149a02010-09-16 17:11:30 +0000591
Johnny Chen548aefd2010-10-11 22:25:46 +0000592 # If '-r dir' is specified, the tests should be run under the relocated
593 # directory. Let's copy the testdirs over.
594 if rdir:
595 from shutil import copytree, ignore_patterns
596
597 tmpdirs = []
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000598 orig_testdirs = testdirs[:]
Johnny Chen548aefd2010-10-11 22:25:46 +0000599 for srcdir in testdirs:
Johnny Chen1abe4c02012-03-20 00:33:51 +0000600 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
601 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
602 # Utilize the relative path to the 'test' directory to make our destination dir path.
Greg Clayton4793e942012-09-04 15:42:49 +0000603 if ("test" + os.sep) in srcdir:
604 to_split_on = "test" + os.sep
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000605 else:
606 to_split_on = "test"
607 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
608 dstdir = dstdir.rstrip(os.sep)
Johnny Chen548aefd2010-10-11 22:25:46 +0000609 # Don't copy the *.pyc and .svn stuffs.
610 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
611 tmpdirs.append(dstdir)
612
613 # This will be our modified testdirs.
614 testdirs = tmpdirs
615
616 # With '-r dir' specified, there's no cleanup of intermediate test files.
617 os.environ["LLDB_DO_CLEANUP"] = 'NO'
618
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000619 # If the original testdirs is ['test'], the make directory has already been copied
Johnny Chen548aefd2010-10-11 22:25:46 +0000620 # recursively and is contained within the rdir/test dir. For anything
621 # else, we would need to copy over the make directory and its contents,
622 # so that, os.listdir(rdir) looks like, for example:
623 #
624 # array_types conditional_break make
625 #
626 # where the make directory contains the Makefile.rules file.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000627 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000628 scriptdir = os.path.dirname(__file__)
Johnny Chen548aefd2010-10-11 22:25:46 +0000629 # Don't copy the .svn stuffs.
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000630 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
Johnny Chen548aefd2010-10-11 22:25:46 +0000631 ignore=ignore_patterns('.svn'))
632
633 #print "testdirs:", testdirs
634
Johnny Chenb40056b2010-09-21 00:09:27 +0000635 # Source the configFile if specified.
636 # The side effect, if any, will be felt from this point on. An example
637 # config file may be these simple two lines:
638 #
639 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
640 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
641 #
642 # which will reassign the two file objects to sys.stderr and sys.stdout,
643 # respectively.
644 #
Johnny Chen8c130642012-08-22 17:53:02 +0000645 # See also lldb-trunk/examples/test/usage-config.
Johnny Chenac97a6b2012-04-16 18:55:15 +0000646 global config, pre_flight, post_flight
Johnny Chenb40056b2010-09-21 00:09:27 +0000647 if configFile:
648 # Pass config (a dictionary) as the locals namespace for side-effect.
649 execfile(configFile, globals(), config)
Johnny Chenac97a6b2012-04-16 18:55:15 +0000650 print "config:", config
651 if "pre_flight" in config:
652 pre_flight = config["pre_flight"]
653 if not callable(pre_flight):
654 print "fatal error: pre_flight is not callable, exiting."
655 sys.exit(1)
656 if "post_flight" in config:
657 post_flight = config["post_flight"]
658 if not callable(post_flight):
659 print "fatal error: post_flight is not callable, exiting."
660 sys.exit(1)
Johnny Chenb40056b2010-09-21 00:09:27 +0000661 #print "sys.stderr:", sys.stderr
662 #print "sys.stdout:", sys.stdout
663
Johnny Chenaf149a02010-09-16 17:11:30 +0000664
Johnny Chen9707bb62010-06-25 21:14:08 +0000665def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000666 """
667 Add LLDB.framework/Resources/Python to the search paths for modules.
668 As a side effect, we also discover the 'lldb' executable and export it here.
669 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000670
Johnny Chen548aefd2010-10-11 22:25:46 +0000671 global rdir
672 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000673 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000674 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000675 global svn_info
Johnny Chen548aefd2010-10-11 22:25:46 +0000676
Johnny Chen9707bb62010-06-25 21:14:08 +0000677 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000678 if ("DOTEST_PROFILE" in os.environ or "DOTEST_PDB" in os.environ) and "DOTEST_SCRIPT_DIR" in os.environ:
Johnny Chen0de6ab52011-01-19 02:10:40 +0000679 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
680 else:
681 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000682 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000683 print "This script expects to reside in lldb's test directory."
684 sys.exit(-1)
685
Johnny Chen548aefd2010-10-11 22:25:46 +0000686 if rdir:
687 # Set up the LLDB_TEST environment variable appropriately, so that the
688 # individual tests can be located relatively.
689 #
690 # See also lldbtest.TestBase.setUpClass(cls).
691 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
692 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
693 else:
694 os.environ["LLDB_TEST"] = rdir
695 else:
696 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000697
698 # Set up the LLDB_SRC environment variable, so that the tests can locate
699 # the LLDB source code.
700 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
701
Johnny Chen9de4ede2010-08-31 17:42:54 +0000702 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000703 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000704
Johnny Chen8a3c0432011-03-11 20:13:06 +0000705 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000706 sys.path.append(scriptPath)
707 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000708 sys.path.append(pexpectPath)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000709
Johnny Chen26901c82011-03-11 19:47:23 +0000710 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000711 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000712
Johnny Chen26901c82011-03-11 19:47:23 +0000713 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000714 xcode3_build_dir = ['build']
715 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
716 dbg = ['Debug']
Sean Callanand9d94632012-09-26 21:16:15 +0000717 dbc = ['DebugClang']
Johnny Chen6a564a42011-02-15 18:50:19 +0000718 rel = ['Release']
719 bai = ['BuildAndIntegration']
720 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000721
722 # Some of the tests can invoke the 'lldb' command directly.
723 # We'll try to locate the appropriate executable right here.
724
Johnny Chen6033bed2011-08-26 00:00:01 +0000725 # First, you can define an environment variable LLDB_EXEC specifying the
726 # full pathname of the lldb executable.
727 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
728 lldbExec = os.environ["LLDB_EXEC"]
729 else:
730 lldbExec = None
731
Johnny Chen26901c82011-03-11 19:47:23 +0000732 executable = ['lldb']
733 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
734 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
Sean Callanand9d94632012-09-26 21:16:15 +0000735 dbcExec = os.path.join(base, *(xcode3_build_dir + dbc + executable))
736 dbcExec2 = os.path.join(base, *(xcode4_build_dir + dbc + executable))
Johnny Chen26901c82011-03-11 19:47:23 +0000737 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
738 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
739 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
740 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
741
Johnny Chen6033bed2011-08-26 00:00:01 +0000742 # The 'lldb' executable built here in the source tree.
743 lldbHere = None
Johnny Chen26901c82011-03-11 19:47:23 +0000744 if is_exe(dbgExec):
Johnny Chen6033bed2011-08-26 00:00:01 +0000745 lldbHere = dbgExec
Johnny Chen26901c82011-03-11 19:47:23 +0000746 elif is_exe(dbgExec2):
Johnny Chen6033bed2011-08-26 00:00:01 +0000747 lldbHere = dbgExec2
Sean Callanand9d94632012-09-26 21:16:15 +0000748 elif is_exe(dbcExec):
749 lldbHere = dbcExec
750 elif is_exe(dbcExec2):
751 lldbHere = dbcExec2
Johnny Chen26901c82011-03-11 19:47:23 +0000752 elif is_exe(relExec):
Johnny Chen6033bed2011-08-26 00:00:01 +0000753 lldbHere = relExec
Johnny Chen26901c82011-03-11 19:47:23 +0000754 elif is_exe(relExec2):
Johnny Chen6033bed2011-08-26 00:00:01 +0000755 lldbHere = relExec2
Johnny Chen26901c82011-03-11 19:47:23 +0000756 elif is_exe(baiExec):
Johnny Chen6033bed2011-08-26 00:00:01 +0000757 lldbHere = baiExec
Johnny Chen26901c82011-03-11 19:47:23 +0000758 elif is_exe(baiExec2):
Johnny Chen6033bed2011-08-26 00:00:01 +0000759 lldbHere = baiExec2
Daniel Dunbar2bd310c2011-10-31 23:27:06 +0000760 elif lldbExec:
761 lldbHere = lldbExec
Johnny Chen26901c82011-03-11 19:47:23 +0000762
Johnny Chen6033bed2011-08-26 00:00:01 +0000763 if lldbHere:
764 os.environ["LLDB_HERE"] = lldbHere
Johnny Chen0409d992011-10-25 20:08:03 +0000765 os.environ["LLDB_BUILD_DIR"] = os.path.split(lldbHere)[0]
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000766 if not noHeaders:
767 print "LLDB build dir:", os.environ["LLDB_BUILD_DIR"]
Johnny Chen91da0052011-10-28 17:56:02 +0000768 os.system('%s -v' % lldbHere)
Johnny Chen62d527e2011-08-04 18:17:16 +0000769
Johnny Chen6033bed2011-08-26 00:00:01 +0000770 # One last chance to locate the 'lldb' executable.
Johnny Chen26901c82011-03-11 19:47:23 +0000771 if not lldbExec:
Johnny Chen0409d992011-10-25 20:08:03 +0000772 lldbExec = which('lldb')
773 if lldbHere and not lldbExec:
Johnny Chen6033bed2011-08-26 00:00:01 +0000774 lldbExec = lldbHere
Johnny Chen0409d992011-10-25 20:08:03 +0000775
Johnny Chen26901c82011-03-11 19:47:23 +0000776
777 if not lldbExec:
778 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
779 else:
780 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000781 #print "The 'lldb' from PATH env variable", lldbExec
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000782
Johnny Chenb264c9b2011-06-24 22:52:05 +0000783 if os.path.isdir(os.path.join(base, '.svn')):
784 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
785 svn_info = pipe.stdout.read()
786 elif os.path.isdir(os.path.join(base, '.git')):
787 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
788 svn_info = pipe.stdout.read()
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000789 if not noHeaders:
790 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000791
792 global ignore
793
794 # The '-i' option is used to skip looking for lldb.py in the build tree.
795 if ignore:
796 return
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000797
Johnny Chen6a564a42011-02-15 18:50:19 +0000798 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
799 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
Sean Callanand9d94632012-09-26 21:16:15 +0000800 dbcPath = os.path.join(base, *(xcode3_build_dir + dbc + python_resource_dir))
801 dbcPath2 = os.path.join(base, *(xcode4_build_dir + dbc + python_resource_dir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000802 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
803 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
804 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
805 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Johnny Chen9707bb62010-06-25 21:14:08 +0000806
807 lldbPath = None
Greg Clayton4e651b12012-04-25 00:58:03 +0000808 if os.path.isfile(os.path.join(dbgPath, 'lldb/__init__.py')):
Johnny Chen9707bb62010-06-25 21:14:08 +0000809 lldbPath = dbgPath
Greg Clayton4e651b12012-04-25 00:58:03 +0000810 elif os.path.isfile(os.path.join(dbgPath2, 'lldb/__init__.py')):
Greg Claytond9846b02011-02-14 21:17:06 +0000811 lldbPath = dbgPath2
Sean Callanand9d94632012-09-26 21:16:15 +0000812 elif os.path.isfile(os.path.join(dbcPath, 'lldb/__init__.py')):
813 lldbPath = dbcPath
814 elif os.path.isfile(os.path.join(dbcPath2, 'lldb/__init__.py')):
815 lldbPath = dbcPath2
Greg Clayton4e651b12012-04-25 00:58:03 +0000816 elif os.path.isfile(os.path.join(relPath, 'lldb/__init__.py')):
Johnny Chen9707bb62010-06-25 21:14:08 +0000817 lldbPath = relPath
Greg Clayton4e651b12012-04-25 00:58:03 +0000818 elif os.path.isfile(os.path.join(relPath2, 'lldb/__init__.py')):
Greg Claytond9846b02011-02-14 21:17:06 +0000819 lldbPath = relPath2
Greg Clayton4e651b12012-04-25 00:58:03 +0000820 elif os.path.isfile(os.path.join(baiPath, 'lldb/__init__.py')):
Johnny Chenc202c462010-09-15 18:11:19 +0000821 lldbPath = baiPath
Greg Clayton4e651b12012-04-25 00:58:03 +0000822 elif os.path.isfile(os.path.join(baiPath2, 'lldb/__init__.py')):
Greg Claytond9846b02011-02-14 21:17:06 +0000823 lldbPath = baiPath2
Johnny Chen9707bb62010-06-25 21:14:08 +0000824
825 if not lldbPath:
Johnny Chenc202c462010-09-15 18:11:19 +0000826 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
827 print relPath + ', or ' + baiPath
Johnny Chen9707bb62010-06-25 21:14:08 +0000828 sys.exit(-1)
829
Enrico Granata01458ca2012-10-23 00:09:02 +0000830 # If tests need to find LLDB_FRAMEWORK, now they can do it
831 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPath))
832
Johnny Chenaf149a02010-09-16 17:11:30 +0000833 # This is to locate the lldb.py module. Insert it right after sys.path[0].
834 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000835 if dumpSysPath:
836 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000837
Johnny Chen9707bb62010-06-25 21:14:08 +0000838
Johnny Chencd0279d2010-09-20 18:07:50 +0000839def doDelay(delta):
840 """Delaying startup for delta-seconds to facilitate debugger attachment."""
841 def alarm_handler(*args):
842 raise Exception("timeout")
843
844 signal.signal(signal.SIGALRM, alarm_handler)
845 signal.alarm(delta)
846 sys.stdout.write("pid=%d\n" % os.getpid())
847 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
848 delta)
849 sys.stdout.flush()
850 try:
851 text = sys.stdin.readline()
852 except:
853 text = ""
854 signal.alarm(0)
855 sys.stdout.write("proceeding...\n")
856 pass
857
858
Johnny Chen9707bb62010-06-25 21:14:08 +0000859def visit(prefix, dir, names):
860 """Visitor function for os.path.walk(path, visit, arg)."""
861
862 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000863 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000864 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000865 global fs4all
Johnny Chene9eae812012-01-18 05:15:00 +0000866 global excluded
867
868 if set(dir.split(os.sep)).intersection(excluded):
869 #print "Detected an excluded dir component: %s" % dir
870 return
Johnny Chen9707bb62010-06-25 21:14:08 +0000871
872 for name in names:
873 if os.path.isdir(os.path.join(dir, name)):
874 continue
875
876 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000877 # Try to match the regexp pattern, if specified.
878 if regexp:
879 import re
880 if re.search(regexp, name):
881 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
882 pass
883 else:
884 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
885 continue
886
Johnny Chen953864a2010-10-12 21:35:54 +0000887 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000888
889 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000890 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000891 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000892 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000893
894 # Thoroughly check the filterspec against the base module and admit
895 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000896 filterspec = None
897 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000898 # Optimistically set the flag to True.
899 filtered = True
900 module = __import__(base)
901 parts = filterspec.split('.')
902 obj = module
903 for part in parts:
904 try:
905 parent, obj = obj, getattr(obj, part)
906 except AttributeError:
907 # The filterspec has failed.
908 filtered = False
909 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000910
Johnny Chendb4be602011-08-12 23:55:07 +0000911 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000912 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +0000913 #print "adding filter spec %s to module %s" % (filterspec, module)
914 suite.addTests(
915 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
916 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +0000917
918 # Forgo this module if the (base, filterspec) combo is invalid
919 # and no '-g' option is specified
920 if filters and fs4all and not filtered:
921 continue
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000922
Johnny Chendb4be602011-08-12 23:55:07 +0000923 # Add either the filtered test case(s) (which is done before) or the entire test class.
924 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +0000925 # A simple case of just the module name. Also the failover case
926 # from the filterspec branch when the (base, filterspec) combo
927 # doesn't make sense.
928 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000929
930
Johnny Chencd0279d2010-09-20 18:07:50 +0000931def lldbLoggings():
932 """Check and do lldb loggings if necessary."""
933
934 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
935 # defined. Use ${LLDB_LOG} to specify the log file.
936 ci = lldb.DBG.GetCommandInterpreter()
937 res = lldb.SBCommandReturnObject()
938 if ("LLDB_LOG" in os.environ):
939 if ("LLDB_LOG_OPTION" in os.environ):
940 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
941 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +0000942 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +0000943 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +0000944 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +0000945 res)
946 if not res.Succeeded():
947 raise Exception('log enable failed (check LLDB_LOG env variable.')
948 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
949 # Use ${GDB_REMOTE_LOG} to specify the log file.
950 if ("GDB_REMOTE_LOG" in os.environ):
951 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
952 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
953 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +0000954 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +0000955 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +0000956 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +0000957 + gdb_remote_log_option,
958 res)
959 if not res.Succeeded():
960 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
961
Johnny Chen067022b2011-01-19 19:31:46 +0000962def getMyCommandLine():
Johnny Chen067022b2011-01-19 19:31:46 +0000963 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
964 lines = ps.split('\n')
965 cmd_line = lines[1]
966 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +0000967
Johnny Chend96b5682010-11-05 17:30:53 +0000968# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000969# #
970# Execution of the test driver starts here #
971# #
Johnny Chend96b5682010-11-05 17:30:53 +0000972# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +0000973
Johnny Chen2891bb02011-09-16 01:04:26 +0000974def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +0000975 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
976 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
977 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +0000978 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +0000979 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +0000980 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +0000981 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
982 print "Exiting..."
983 sys.exit(0)
984
985# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
986# does not exist before proceeding to running the test suite.
987if sys.platform.startswith("darwin"):
988 checkDsymForUUIDIsNotOn()
989
Johnny Chen9707bb62010-06-25 21:14:08 +0000990#
Johnny Chenaf149a02010-09-16 17:11:30 +0000991# Start the actions by first parsing the options while setting up the test
992# directories, followed by setting up the search paths for lldb utilities;
993# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +0000994#
Johnny Chenaf149a02010-09-16 17:11:30 +0000995parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +0000996setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +0000997
998#
999# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
1000#
1001if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +00001002 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +00001003
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001004#
Johnny Chen41998192010-10-01 22:59:49 +00001005# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +00001006if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +00001007 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1008
1009#
Johnny Chen79723352010-10-12 15:53:22 +00001010# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001011#
Johnny Chen9707bb62010-06-25 21:14:08 +00001012for testdir in testdirs:
1013 os.path.walk(testdir, visit, 'Test')
1014
Johnny Chenb40056b2010-09-21 00:09:27 +00001015#
Johnny Chen9707bb62010-06-25 21:14:08 +00001016# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +00001017#
Johnny Chencd0279d2010-09-20 18:07:50 +00001018
Johnny Chen1bfbd412010-06-29 19:44:16 +00001019# For the time being, let's bracket the test runner within the
1020# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001021import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +00001022# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
1023# there's no need to call it a second time.
1024#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001025atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +00001026
Johnny Chen909e5a62010-07-01 22:52:57 +00001027# Create a singleton SBDebugger in the lldb namespace.
1028lldb.DBG = lldb.SBDebugger.Create()
1029
Johnny Chen4f93bf12010-12-10 00:51:23 +00001030# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +00001031lldb.blacklist = blacklist
1032
Johnny Chenac97a6b2012-04-16 18:55:15 +00001033# The pre_flight and post_flight come from reading a config file.
1034lldb.pre_flight = pre_flight
1035lldb.post_flight = post_flight
1036def getsource_if_available(obj):
1037 """
1038 Return the text of the source code for an object if available. Otherwise,
1039 a print representation is returned.
1040 """
1041 import inspect
1042 try:
1043 return inspect.getsource(obj)
1044 except:
1045 return repr(obj)
1046
1047print "lldb.pre_flight:", getsource_if_available(lldb.pre_flight)
1048print "lldb.post_flight:", getsource_if_available(lldb.post_flight)
1049
Johnny Chena3ed7d82012-04-06 00:56:05 +00001050# Put all these test decorators in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +00001051lldb.dont_do_python_api_test = dont_do_python_api_test
1052lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +00001053lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +00001054lldb.dont_do_dsym_test = dont_do_dsym_test
1055lldb.dont_do_dwarf_test = dont_do_dwarf_test
Johnny Chen4f93bf12010-12-10 00:51:23 +00001056
Johnny Chen028d8eb2011-11-17 19:57:27 +00001057# Do we need to skip build and cleanup?
1058lldb.skip_build_and_cleanup = skip_build_and_cleanup
1059
Johnny Chen5f2ed172011-10-20 18:43:28 +00001060# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +00001061lldb.bmExecutable = bmExecutable
1062lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +00001063lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +00001064
Johnny Chen38f823c2011-10-11 01:30:27 +00001065# And don't forget the runHooks!
1066lldb.runHooks = runHooks
1067
Johnny Chencd0279d2010-09-20 18:07:50 +00001068# Turn on lldb loggings if necessary.
1069lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +00001070
Johnny Chen7987ac92010-08-09 20:40:52 +00001071# Install the control-c handler.
1072unittest2.signals.installHandler()
1073
Johnny Chen125fc2b2010-10-21 16:55:35 +00001074# If sdir_name is not specified through the '-s sdir_name' option, get a
1075# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1076# be used when/if we want to dump the session info of individual test cases
1077# later on.
Johnny Chence681462010-10-19 00:25:01 +00001078#
1079# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chena73ad662012-08-16 19:15:21 +00001080import datetime
1081# The windows platforms don't like ':' in the pathname.
1082timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +00001083if not sdir_name:
Johnny Chena73ad662012-08-16 19:15:21 +00001084 sdir_name = timestamp_started
Peter Collingbourne132476f2011-06-20 23:55:53 +00001085os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +00001086
Johnny Chenfe5f1ed2011-10-21 18:33:27 +00001087if not noHeaders:
1088 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1089 " will go into directory '%s'\n" % sdir_name)
1090 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +00001091
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001092if not os.path.isdir(sdir_name):
1093 os.mkdir(sdir_name)
Johnny Chena73ad662012-08-16 19:15:21 +00001094fname = os.path.join(sdir_name, "TestStarted")
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001095with open(fname, "w") as f:
Johnny Chena73ad662012-08-16 19:15:21 +00001096 print >> f, "Test started at: %s\n" % timestamp_started
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001097 print >> f, svn_info
1098 print >> f, "Command invoked: %s\n" % getMyCommandLine()
1099
Johnny Chenb40056b2010-09-21 00:09:27 +00001100#
Johnny Chen0f907b82012-01-31 00:38:03 +00001101# If we have environment variables to unset, do it here before we invoke the test runner.
1102#
1103for env_var in unsets :
1104 if env_var in os.environ:
1105 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
Johnny Chen6346a292012-01-31 00:48:02 +00001106 # is automatically translated into a corresponding call to unsetenv().
Johnny Chen0f907b82012-01-31 00:38:03 +00001107 del os.environ[env_var]
1108 #os.unsetenv(env_var)
1109
1110#
Johnny Chenb40056b2010-09-21 00:09:27 +00001111# Invoke the default TextTestRunner to run the test suite, possibly iterating
1112# over different configurations.
1113#
1114
Johnny Chenb40056b2010-09-21 00:09:27 +00001115iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +00001116iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001117
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001118if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001119 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001120
1121if isinstance(archs, list) and len(archs) >= 1:
1122 iterArchs = True
1123
1124if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001125 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001126
Johnny Chen92693b52012-03-09 02:11:37 +00001127#
1128# Add some intervention here to sanity check that the compilers requested are sane.
1129# If found not to be an executable program, the invalid one is dropped from the list.
1130for i in range(len(compilers)):
1131 c = compilers[i]
1132 if which(c):
1133 continue
1134 else:
1135 if sys.platform.startswith("darwin"):
1136 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1137 cmd_output = pipe.stdout.read()
1138 if cmd_output:
1139 if "not found" in cmd_output:
1140 print "dropping %s from the compilers used" % c
1141 compilers.remove(i)
1142 else:
1143 compilers[i] = cmd_output.split('\n')[0]
1144 print "'xcrun -find %s' returning %s" % (c, compilers[i])
1145
1146print "compilers=%s" % str(compilers)
1147
1148if not compilers or len(compilers) == 0:
1149 print "No eligible compiler found, exiting."
1150 sys.exit(1)
1151
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001152if isinstance(compilers, list) and len(compilers) >= 1:
1153 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001154
Johnny Chen953864a2010-10-12 21:35:54 +00001155# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1156# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001157if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001158 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001159# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1160if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001161 old_stderr = sys.stderr
1162 old_stdout = sys.stdout
1163 new_stderr = None
1164 new_stdout = None
1165
Johnny Chend96b5682010-11-05 17:30:53 +00001166# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001167for ia in range(len(archs) if iterArchs else 1):
1168 archConfig = ""
1169 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001170 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001171 archConfig = "arch=%s" % archs[ia]
1172 for ic in range(len(compilers) if iterCompilers else 1):
1173 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001174 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001175 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1176 else:
1177 configString = archConfig
1178
Johnny Chenb40056b2010-09-21 00:09:27 +00001179 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001180 # Translate ' ' to '-' for pathname component.
1181 from string import maketrans
1182 tbl = maketrans(' ', '-')
1183 configPostfix = configString.translate(tbl)
1184
1185 # Check whether we need to split stderr/stdout into configuration
1186 # specific files.
1187 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1188 if new_stderr:
1189 new_stderr.close()
1190 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1191 sys.stderr = new_stderr
1192 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1193 if new_stdout:
1194 new_stdout.close()
1195 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1196 sys.stdout = new_stdout
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001197
Johnny Chen953864a2010-10-12 21:35:54 +00001198 # If we specified a relocated directory to run the test suite, do
1199 # the extra housekeeping to copy the testdirs to a configStringified
1200 # directory and to update sys.path before invoking the test runner.
1201 # The purpose is to separate the configuration-specific directories
1202 # from each other.
1203 if rdir:
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001204 from shutil import copytree, rmtree, ignore_patterns
Johnny Chen953864a2010-10-12 21:35:54 +00001205
Johnny Chen953864a2010-10-12 21:35:54 +00001206 newrdir = "%s.%s" % (rdir, configPostfix)
1207
1208 # Copy the tree to a new directory with postfix name configPostfix.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001209 if os.path.exists(newrdir):
1210 rmtree(newrdir)
Johnny Chen953864a2010-10-12 21:35:54 +00001211 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1212
Filipe Cabecinhas0e1d06d2012-08-08 15:23:24 +00001213 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001214 # level test directory.
1215 #
1216 # See also lldbtest.TestBase.setUpClass(cls).
1217 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1218 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1219 else:
1220 os.environ["LLDB_TEST"] = newrdir
1221
1222 # And update the Python search paths for modules.
1223 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1224
1225 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +00001226 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001227
1228 #print "sys.stderr name is", sys.stderr.name
1229 #print "sys.stdout name is", sys.stdout.name
1230
1231 # First, write out the number of collected test cases.
Johnny Chen08967192011-11-18 00:19:29 +00001232 sys.stderr.write(separator + "\n")
1233 sys.stderr.write("Collected %d test%s\n\n"
1234 % (suite.countTestCases(),
1235 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001236
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001237 class LLDBTestResult(unittest2.TextTestResult):
1238 """
Johnny Chen26be4532010-11-09 23:56:14 +00001239 Enforce a singleton pattern to allow introspection of test progress.
1240
1241 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1242 to enable each test instance to track its failure/error status. It
1243 is used in the LLDB test framework to emit detailed trace messages
1244 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001245 """
1246 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001247 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001248
1249 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001250 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001251 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001252 super(LLDBTestResult, self).__init__(*args)
1253 LLDBTestResult.__singleton__ = self
1254 # Now put this singleton into the lldb module namespace.
1255 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001256 # Computes the format string for displaying the counter.
1257 global suite
1258 counterWidth = len(str(suite.countTestCases()))
1259 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001260 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001261 # This counts from 1 .. suite.countTestCases().
1262 self.counter = 0
1263
Johnny Chenbe452272012-04-19 21:33:55 +00001264 def _exc_info_to_string(self, err, test):
1265 """Overrides superclass TestResult's method in order to append
1266 our test config info string to the exception info string."""
1267 modified_exc_string = '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1268 test.getArchitecture(),
1269 test.getCompiler())
1270 return modified_exc_string
1271
Johnny Chenc87fd492011-01-05 22:50:11 +00001272 def getDescription(self, test):
1273 doc_first_line = test.shortDescription()
1274 if self.descriptions and doc_first_line:
1275 return '\n'.join((str(test), self.indentation + doc_first_line))
1276 else:
1277 return str(test)
1278
Enrico Granataac3a8e22012-09-21 19:10:53 +00001279 def getCategoriesForTest(self,test):
1280 if hasattr(test,"getCategories"):
1281 test_categories = test.getCategories()
1282 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1283 test_categories = test.__self__.getCategories()
1284 else:
1285 test_categories = []
1286 if test_categories == None:
1287 test_categories = []
1288 return test_categories
1289
1290 def shouldSkipBecauseOfCategories(self,test):
1291 global useCategories
1292 import inspect
1293 if useCategories:
1294 global categoriesList
1295 test_categories = self.getCategoriesForTest(test)
1296 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
1297 return True
1298 return False
1299
1300 def hardMarkAsSkipped(self,test):
1301 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1302 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1303
Johnny Chen810042e2011-01-05 20:24:11 +00001304 def startTest(self, test):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001305 if self.shouldSkipBecauseOfCategories(test):
1306 self.hardMarkAsSkipped(test)
Johnny Chen810042e2011-01-05 20:24:11 +00001307 self.counter += 1
1308 if self.showAll:
1309 self.stream.write(self.fmt % self.counter)
1310 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001311
Johnny Chence681462010-10-19 00:25:01 +00001312 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001313 global sdir_has_content
1314 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001315 super(LLDBTestResult, self).addError(test, err)
1316 method = getattr(test, "markError", None)
1317 if method:
1318 method()
1319
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001320 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001321 global sdir_has_content
Enrico Granataac3a8e22012-09-21 19:10:53 +00001322 global failuresPerCategory
Johnny Chen63c2cba2010-10-29 22:20:36 +00001323 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001324 super(LLDBTestResult, self).addFailure(test, err)
1325 method = getattr(test, "markFailure", None)
1326 if method:
1327 method()
Enrico Granataac3a8e22012-09-21 19:10:53 +00001328 if useCategories:
1329 test_categories = self.getCategoriesForTest(test)
1330 for category in test_categories:
1331 if category in failuresPerCategory:
1332 failuresPerCategory[category] = failuresPerCategory[category] + 1
1333 else:
1334 failuresPerCategory[category] = 1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001335
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001336 def addExpectedFailure(self, test, err):
1337 global sdir_has_content
1338 sdir_has_content = True
1339 super(LLDBTestResult, self).addExpectedFailure(test, err)
1340 method = getattr(test, "markExpectedFailure", None)
1341 if method:
1342 method()
1343
Johnny Chenf5b89092011-08-15 23:09:08 +00001344 def addSkip(self, test, reason):
1345 global sdir_has_content
1346 sdir_has_content = True
1347 super(LLDBTestResult, self).addSkip(test, reason)
1348 method = getattr(test, "markSkippedTest", None)
1349 if method:
1350 method()
1351
Johnny Chenab2f0662011-05-06 20:30:22 +00001352 def addUnexpectedSuccess(self, test):
1353 global sdir_has_content
1354 sdir_has_content = True
1355 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1356 method = getattr(test, "markUnexpectedSuccess", None)
1357 if method:
1358 method()
1359
Johnny Chen26be4532010-11-09 23:56:14 +00001360 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001361 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001362 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001363 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001364 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001365 resultclass=LLDBTestResult).run(suite)
1366 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001367 # We are invoking the same test suite more than once. In this case,
1368 # mark __ignore_singleton__ flag as True so the signleton pattern is
1369 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001370 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001371 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +00001372 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001373 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001374 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001375 resultclass=LLDBTestResult).run(suite)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001376
Johnny Chen1bfbd412010-06-29 19:44:16 +00001377
Johnny Chen63c2cba2010-10-29 22:20:36 +00001378if sdir_has_content:
Johnny Chenab2f0662011-05-06 20:30:22 +00001379 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1380 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001381
Enrico Granataac3a8e22012-09-21 19:10:53 +00001382if useCategories and len(failuresPerCategory) > 0:
1383 sys.stderr.write("Failures per category:\n")
1384 for category in failuresPerCategory:
1385 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
1386
Johnny Chena73ad662012-08-16 19:15:21 +00001387fname = os.path.join(sdir_name, "TestFinished")
1388with open(fname, "w") as f:
1389 print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1390
Johnny Chencd0279d2010-09-20 18:07:50 +00001391# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1392# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001393if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001394 print "Terminating Test suite..."
1395 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1396
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001397# Exiting.
1398sys.exit(not result.wasSuccessful)