blob: 8ed13daacd6dbfde2421107be145918402997881 [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 os
24import platform
25import signal
Johnny Chen2891bb02011-09-16 01:04:26 +000026import subprocess
Greg Clayton4793e942012-09-04 15:42:49 +000027import sys
28import textwrap
29import time
Johnny Chen75e28f92010-08-05 23:42:46 +000030import unittest2
Enrico Granatabc0c5a62013-02-08 23:39:18 +000031import progress
Johnny Chen9707bb62010-06-25 21:14:08 +000032
Filipe Cabecinhasd3eb8372013-02-16 09:05:23 +000033if sys.version_info >= (2, 7):
34 argparse = __import__('argparse')
35else:
36 argparse = __import__('argparse_compat')
37
Johnny Chen26901c82011-03-11 19:47:23 +000038def is_exe(fpath):
Johnny Chenf2c7b282011-04-26 23:10:51 +000039 """Returns true if fpath is an executable."""
Johnny Chen26901c82011-03-11 19:47:23 +000040 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
41
Johnny Chen26901c82011-03-11 19:47:23 +000042def which(program):
Johnny Chenf2c7b282011-04-26 23:10:51 +000043 """Returns the full path to a program; None otherwise."""
Johnny Chen26901c82011-03-11 19:47:23 +000044 fpath, fname = os.path.split(program)
45 if fpath:
46 if is_exe(program):
47 return program
48 else:
49 for path in os.environ["PATH"].split(os.pathsep):
50 exe_file = os.path.join(path, program)
51 if is_exe(exe_file):
52 return exe_file
53 return None
54
Johnny Chen877c7e42010-08-07 00:16:07 +000055class _WritelnDecorator(object):
56 """Used to decorate file-like objects with a handy 'writeln' method"""
57 def __init__(self,stream):
58 self.stream = stream
59
60 def __getattr__(self, attr):
61 if attr in ('stream', '__getstate__'):
62 raise AttributeError(attr)
63 return getattr(self.stream,attr)
64
65 def writeln(self, arg=None):
66 if arg:
67 self.write(arg)
68 self.write('\n') # text-mode streams translate to \r\n if needed
69
Johnny Chen9707bb62010-06-25 21:14:08 +000070#
71# Global variables:
72#
73
Enrico Granataac3a8e22012-09-21 19:10:53 +000074# Dictionary of categories
75# When you define a new category for your testcases, be sure to add it here, or the test suite
76# will gladly complain as soon as you try to use it. This allows us to centralize which categories
77# exist, and to provide a description for each one
78validCategories = {
79'dataformatters':'Tests related to the type command and the data formatters subsystem',
80'expression':'Tests related to the expression parser',
81'objc':'Tests related to the Objective-C programming language support',
82'pyapi':'Tests related to the Python API'
83}
84
Johnny Chen9707bb62010-06-25 21:14:08 +000085# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000086suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000087
Johnny Chen4f93bf12010-12-10 00:51:23 +000088# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000089# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
90# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000091dont_do_python_api_test = False
92
93# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000094just_do_python_api_test = False
95
Johnny Chen82ccf402011-07-30 01:39:58 +000096# By default, benchmarks tests are not run.
97just_do_benchmarks_test = False
98
Johnny Chena3ed7d82012-04-06 00:56:05 +000099# By default, both dsym and dwarf tests are performed.
100# Use @dsym_test or @dwarf_test decorators, defined in lldbtest.py, to mark a test
101# as a dsym or dwarf test. Use '-N dsym' or '-N dwarf' to exclude dsym or dwarf
102# tests from running.
Daniel Maleab8106282012-11-20 16:07:33 +0000103dont_do_dsym_test = "linux" in sys.platform
Johnny Chena3ed7d82012-04-06 00:56:05 +0000104dont_do_dwarf_test = False
105
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000106# The blacklist is optional (-b blacklistFile) and allows a central place to skip
107# testclass's and/or testclass.testmethod's.
108blacklist = None
109
110# The dictionary as a result of sourcing blacklistFile.
111blacklistConfig = {}
112
Enrico Granataac3a8e22012-09-21 19:10:53 +0000113# The list of categories we said we care about
114categoriesList = None
115# set to true if we are going to use categories for cherry-picking test cases
116useCategories = False
117# use this to track per-category failures
118failuresPerCategory = {}
119
Sean Callanan0acf4c62012-10-24 22:45:39 +0000120# The path to LLDB.framework is optional.
121lldbFrameworkPath = None
122
123# The path to lldb is optional
124lldbExecutablePath = None
125
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000126# The config file is optional.
127configFile = None
128
Johnny Chend2acdb32010-11-16 22:42:58 +0000129# Test suite repeat count. Can be overwritten with '-# count'.
130count = 1
131
Johnny Chenb40056b2010-09-21 00:09:27 +0000132# The dictionary as a result of sourcing configFile.
133config = {}
Johnny Chenac97a6b2012-04-16 18:55:15 +0000134# The pre_flight and post_flight functions come from reading a config file.
135pre_flight = None
136post_flight = None
Johnny Chenb40056b2010-09-21 00:09:27 +0000137
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000138# The 'archs' and 'compilers' can be specified via either command line or configFile,
Greg Clayton4793e942012-09-04 15:42:49 +0000139# with the command line overriding the configFile. The corresponding options can be
Filipe Cabecinhasd3eb8372013-02-16 09:05:23 +0000140# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386']
Greg Clayton4793e942012-09-04 15:42:49 +0000141# and "-C gcc -C clang" => compilers=['gcc', 'clang'].
142archs = None # Must be initialized after option parsing
143compilers = None # Must be initialized after option parsing
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000144
Johnny Chen1abe4c02012-03-20 00:33:51 +0000145# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
146# the inferior programs. The global variable cflags_extras provides a hook to do
147# just that.
148cflags_extras = ''
149
Johnny Chen91960d32010-09-08 20:56:16 +0000150# Delay startup in order for the debugger to attach.
151delay = False
152
Johnny Chend5362332011-01-29 01:21:04 +0000153# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000154dumpSysPath = False
155
Johnny Chene00c9302011-10-10 22:03:44 +0000156# Full path of the benchmark executable, as specified by the '-e' option.
157bmExecutable = None
158# The breakpoint specification of bmExecutable, as specified by the '-x' option.
159bmBreakpointSpec = None
Johnny Chen5f2ed172011-10-20 18:43:28 +0000160# The benchamrk iteration count, as specified by the '-y' option.
161bmIterationCount = -1
Johnny Chene00c9302011-10-10 22:03:44 +0000162
Johnny Chene9eae812012-01-18 05:15:00 +0000163# By default, don't exclude any directories. Use '-X' to add one excluded directory.
164excluded = set(['.svn', '.git'])
165
Johnny Chen7d6d8442010-12-03 19:59:35 +0000166# By default, failfast is False. Use '-F' to overwrite it.
167failfast = False
168
Johnny Chenc5fa0052011-07-29 22:54:56 +0000169# The filters (testclass.testmethod) used to admit tests into our test suite.
170filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000171
Johnny Chen38f823c2011-10-11 01:30:27 +0000172# The runhooks is a list of lldb commands specifically for the debugger.
173# Use '-k' to specify a runhook.
174runHooks = []
175
Johnny Chena224cd12010-11-08 01:21:03 +0000176# If '-g' is specified, the filterspec is not exclusive. If a test module does
177# not contain testclass.testmethod which matches the filterspec, the whole test
178# module is still admitted into our test suite. fs4all flag defaults to True.
179fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000180
Johnny Chenaf149a02010-09-16 17:11:30 +0000181# Ignore the build search path relative to this script to locate the lldb.py module.
182ignore = False
183
Johnny Chen028d8eb2011-11-17 19:57:27 +0000184# By default, we do not skip build and cleanup. Use '-S' option to override.
185skip_build_and_cleanup = False
186
Johnny Chen548aefd2010-10-11 22:25:46 +0000187# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000188skip_long_running_test = True
Johnny Chen41998192010-10-01 22:59:49 +0000189
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000190# By default, we print the build dir, lldb version, and svn info. Use '-n' option to
191# turn it off.
192noHeaders = False
193
Daniel Malea361eb432013-02-15 21:31:37 +0000194# Parsable mode silences headers, and any other output this script might generate, and instead
195# prints machine-readable output similar to what clang tests produce.
196parsable = False
197
Johnny Chen7c52ff12010-09-27 23:29:54 +0000198# The regular expression pattern to match against eligible filenames as our test cases.
199regexp = None
200
Johnny Chen548aefd2010-10-11 22:25:46 +0000201# By default, tests are executed in place and cleanups are performed afterwards.
202# Use '-r dir' option to relocate the tests and their intermediate files to a
203# different directory and to forgo any cleanups. The directory specified must
204# not exist yet.
205rdir = None
206
Johnny Chen125fc2b2010-10-21 16:55:35 +0000207# By default, recorded session info for errored/failed test are dumped into its
208# own file under a session directory named after the timestamp of the test suite
209# run. Use '-s session-dir-name' to specify a specific dir name.
210sdir_name = None
211
Johnny Chen63c2cba2010-10-29 22:20:36 +0000212# Set this flag if there is any session info dumped during the test run.
213sdir_has_content = False
214
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000215# svn_info stores the output from 'svn info lldb.base.dir'.
216svn_info = ''
217
Johnny Chen9707bb62010-06-25 21:14:08 +0000218# Default verbosity is 0.
Jim Ingham75f260a2013-02-19 20:39:27 +0000219verbose = 1
Johnny Chen9707bb62010-06-25 21:14:08 +0000220
Johnny Chen08967192011-11-18 00:19:29 +0000221# Set to True only if verbose is 0 and LLDB trace mode is off.
222progress_bar = False
223
Peter Collingbourne61aca482011-06-20 19:06:29 +0000224# By default, search from the script directory.
225testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000226
Johnny Chen877c7e42010-08-07 00:16:07 +0000227# Separator string.
228separator = '-' * 70
229
Daniel Malea24765572013-02-20 20:12:11 +0000230failed = False
Johnny Chen9707bb62010-06-25 21:14:08 +0000231
Greg Clayton4793e942012-09-04 15:42:49 +0000232def usage(parser):
233 parser.print_help()
Jim Ingham4f347cb2011-04-13 21:11:41 +0000234 if verbose > 0:
235 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000236Examples:
237
Johnny Chena224cd12010-11-08 01:21:03 +0000238This is an example of using the -f option to pinpoint to a specfic test class
239and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000240
Johnny Chena224cd12010-11-08 01:21:03 +0000241$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000242----------------------------------------------------------------------
243Collected 1 test
244
245test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
246Test 'frame variable this' when stopped on a class constructor. ... ok
247
248----------------------------------------------------------------------
249Ran 1 test in 1.396s
250
251OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000252
253And this is an example of using the -p option to run a single file (the filename
254matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
255
256$ ./dotest.py -v -p ObjC
257----------------------------------------------------------------------
258Collected 4 tests
259
260test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000261Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000262test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000263Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000264test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
265Lookup objective-c data types and evaluate expressions. ... ok
266test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
267Lookup objective-c data types and evaluate expressions. ... ok
268
269----------------------------------------------------------------------
270Ran 4 tests in 16.661s
271
272OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000273
Johnny Chen58f93922010-06-29 23:10:39 +0000274Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000275individual test cases can locate their supporting files correctly. The script
276tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000277relative to this script. See also the '-i' option in the following example.
278
279Finally, this is an example of using the lldb.py module distributed/installed by
280Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
281option to add some delay between two tests. It uses ARCH=x86_64 to specify that
282as the architecture and CC=clang to specify the compiler used for the test run:
283
284$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
285
286Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
287----------------------------------------------------------------------
288Collected 2 tests
289
290test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
291Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
292test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
293Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
294
295----------------------------------------------------------------------
296Ran 2 tests in 5.659s
297
298OK
299
300The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
301notify the directory containing the session logs for test failures or errors.
302In case there is any test failure/error, a similar message is appended at the
303end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000304
305Environment variables related to loggings:
306
307o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
308 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
309
310o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
311 'process.gdb-remote' subsystem with a default option of 'packets' if
312 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000313"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000314 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000315
316
Johnny Chenaf149a02010-09-16 17:11:30 +0000317def parseOptionsAndInitTestdirs():
318 """Initialize the list of directories containing our unittest scripts.
319
320 '-h/--help as the first option prints out usage info and exit the program.
321 """
322
Johnny Chen4f93bf12010-12-10 00:51:23 +0000323 global dont_do_python_api_test
324 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000325 global just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +0000326 global dont_do_dsym_test
327 global dont_do_dwarf_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000328 global blacklist
329 global blacklistConfig
Enrico Granataac3a8e22012-09-21 19:10:53 +0000330 global categoriesList
331 global validCategories
332 global useCategories
Sean Callanan0acf4c62012-10-24 22:45:39 +0000333 global lldbFrameworkPath
334 global lldbExecutablePath
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000335 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000336 global archs
337 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000338 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000339 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000340 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000341 global bmExecutable
342 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000343 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000344 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000345 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000346 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000347 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000348 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000349 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000350 global skip_build_and_cleanup
351 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000352 global noHeaders
Daniel Malea361eb432013-02-15 21:31:37 +0000353 global parsable
Johnny Chen7c52ff12010-09-27 23:29:54 +0000354 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000355 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000356 global sdir_name
Johnny Chenaf149a02010-09-16 17:11:30 +0000357 global verbose
358 global testdirs
359
Jim Ingham4f347cb2011-04-13 21:11:41 +0000360 do_help = False
361
Greg Clayton4793e942012-09-04 15:42:49 +0000362 parser = argparse.ArgumentParser(description='description', prefix_chars='+-', add_help=False)
363 group = None
Johnny Chenaf149a02010-09-16 17:11:30 +0000364
Greg Clayton4793e942012-09-04 15:42:49 +0000365 # Helper function for boolean options (group will point to the current group when executing X)
366 X = lambda optstr, helpstr, **kwargs: group.add_argument(optstr, help=helpstr, action='store_true', **kwargs)
367
368 group = parser.add_argument_group('Help')
369 group.add_argument('-h', '--help', dest='h', action='store_true', help="Print this help message and exit. Add '-v' for more detailed help.")
370
371 # C and Python toolchain options
372 group = parser.add_argument_group('Toolchain options')
373 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'''))
374 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.'''))
375 # FIXME? This won't work for different extra flags according to each arch.
376 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
377 suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
378 X('-D', 'Dump the Python sys.path variable')
379
380 # Test filtering options
381 group = parser.add_argument_group('Test filtering options')
382 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")
383 X('-a', "Don't do lldb Python API tests")
384 X('+a', "Just do lldb Python API tests. Do not specify along with '+a'", dest='plus_a')
385 X('+b', 'Just do benchmark tests', dest='plus_b')
386 group.add_argument('-b', metavar='blacklist', help='Read a blacklist file specified after this option')
Enrico Granata58b03a42012-12-14 00:07:09 +0000387 group.add_argument('-f', metavar='filterspec', action='append', 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?
Greg Clayton4793e942012-09-04 15:42:49 +0000388 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')
389 X('-l', "Don't skip long running tests")
390 group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite')
391 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 +0000392 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 +0000393
394 # Configuration options
395 group = parser.add_argument_group('Configuration options')
396 group.add_argument('-c', metavar='config-file', help='Read a config file specified after this option') # FIXME: additional doc.
Sean Callanan0acf4c62012-10-24 22:45:39 +0000397 group.add_argument('--framework', metavar='framework-path', help='The path to LLDB.framework')
398 group.add_argument('--executable', metavar='executable-path', help='The path to the lldb executable')
Greg Clayton4793e942012-09-04 15:42:49 +0000399 group.add_argument('-e', metavar='benchmark-exe', help='Specify the full path of an executable used for benchmark purposes (see also: -x)')
400 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")
401 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')
402 group.add_argument('-r', metavar='dir', help="Similar to '-R', except that the directory must not exist before running this test driver")
403 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')
404 group.add_argument('-x', metavar='breakpoint-spec', help='Specify the breakpoint specification for the benchmark executable')
405 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.")
406 group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times')
407
408 # Test-suite behaviour
409 group = parser.add_argument_group('Runtime behaviour options')
410 X('-d', 'Delay startup for 10 seconds (in order for the debugger to attach)')
411 X('-F', 'Fail fast. Stop the test suite on the first error/failure')
412 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")
413 X('-n', "Don't print the headers like build dir, lldb version, and svn info at all")
Jim Ingham75f260a2013-02-19 20:39:27 +0000414 X('-P', "Use the graphic progress bar.")
Daniel Malea361eb432013-02-15 21:31:37 +0000415 X('-q', "Don't print extra output from this script.")
Greg Clayton4793e942012-09-04 15:42:49 +0000416 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")
417 X('-t', 'Turn on tracing of lldb command and other detailed test executions')
Greg Claytonb85785c2013-02-08 21:52:32 +0000418 group.add_argument('-u', dest='unset_env_varnames', metavar='variable', action='append', help='Specify an environment variable to unset before running the test cases. e.g., -u DYLD_INSERT_LIBRARIES -u MallocScribble')
Greg Clayton4793e942012-09-04 15:42:49 +0000419 X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
420 X('-w', 'Insert some wait time (currently 0.5 sec) between consecutive test cases')
421
422 # Remove the reference to our helper function
423 del X
424
425 group = parser.add_argument_group('Test directories')
426 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.')
427 args = parser.parse_args()
428
429 platform_system = platform.system()
430 platform_machine = platform.machine()
Enrico Granata2d329242012-10-23 22:52:49 +0000431
Greg Claytonb85785c2013-02-08 21:52:32 +0000432 if args.unset_env_varnames:
433 for env_var in args.unset_env_varnames:
434 if env_var in os.environ:
435 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
436 # is automatically translated into a corresponding call to unsetenv().
437 del os.environ[env_var]
438 #os.unsetenv(env_var)
439
Daniel Malea361eb432013-02-15 21:31:37 +0000440 # only print the args if being verbose (and parsable is off)
441 if args.v and not args.q:
Enrico Granata2d329242012-10-23 22:52:49 +0000442 print args
Greg Clayton4793e942012-09-04 15:42:49 +0000443
444 if args.h:
445 do_help = True
446
447 if args.archs:
448 archs = args.archs
449 else:
450 if platform_system == 'Darwin' and platform_machine == 'x86_64':
451 archs = ['x86_64', 'i386']
Johnny Chenaf149a02010-09-16 17:11:30 +0000452 else:
Greg Clayton4793e942012-09-04 15:42:49 +0000453 archs = [platform_machine]
454
Enrico Granataac3a8e22012-09-21 19:10:53 +0000455 if args.categoriesList:
456 for category in args.categoriesList:
457 if not(category in validCategories):
Enrico Granata2d329242012-10-23 22:52:49 +0000458 print "fatal error: category '" + category + "' is not a valid category"
459 print "if you have added a new category, please edit dotest.py, adding your new category to validCategories"
460 print "else, please specify one or more of the following: " + str(validCategories.keys())
Enrico Granataac3a8e22012-09-21 19:10:53 +0000461 sys.exit(1)
462 categoriesList = set(args.categoriesList)
463 useCategories = True
464 else:
465 categoriesList = []
466
Greg Clayton4793e942012-09-04 15:42:49 +0000467 if args.compilers:
468 compilers = args.compilers
469 else:
470 compilers = ['clang']
471
472 if args.D:
473 dumpSysPath = True
474
475 if args.E:
476 cflags_extras = args.E
477 os.environ['CFLAGS_EXTRAS'] = cflags_extras
478
479 # argparse makes sure we have correct options
480 if args.N == 'dwarf':
481 dont_do_dwarf_test = True
482 elif args.N == 'dsym':
483 dont_do_dsym_test = True
484
485 if args.a:
486 dont_do_python_api_test = True
487
488 if args.plus_a:
489 if dont_do_python_api_test:
490 print "Warning: -a and +a can't both be specified! Using only -a"
491 else:
492 just_do_python_api_test = True
493
494 if args.plus_b:
495 just_do_benchmarks_test = True
496
497 if args.b:
498 if args.b.startswith('-'):
499 usage(parser)
500 blacklistFile = args.b
501 if not os.path.isfile(blacklistFile):
502 print 'Blacklist file:', blacklistFile, 'does not exist!'
503 usage(parser)
504 # Now read the blacklist contents and assign it to blacklist.
505 execfile(blacklistFile, globals(), blacklistConfig)
506 blacklist = blacklistConfig.get('blacklist')
507
508 if args.c:
509 if args.c.startswith('-'):
510 usage(parser)
511 configFile = args.c
512 if not os.path.isfile(configFile):
513 print 'Config file:', configFile, 'does not exist!'
514 usage(parser)
515
516 if args.d:
517 delay = True
518
519 if args.e:
520 if args.e.startswith('-'):
521 usage(parser)
522 bmExecutable = args.e
523 if not is_exe(bmExecutable):
524 usage(parser)
525
526 if args.F:
527 failfast = True
528
529 if args.f:
Enrico Granata58b03a42012-12-14 00:07:09 +0000530 if any([x.startswith('-') for x in args.f]):
Greg Clayton4793e942012-09-04 15:42:49 +0000531 usage(parser)
Enrico Granata58b03a42012-12-14 00:07:09 +0000532 filters.extend(args.f)
Greg Clayton4793e942012-09-04 15:42:49 +0000533
534 if args.g:
535 fs4all = False
536
537 if args.i:
538 ignore = True
539
540 if args.k:
541 runHooks.extend(args.k)
542
543 if args.l:
544 skip_long_running_test = False
545
Sean Callanan0acf4c62012-10-24 22:45:39 +0000546 if args.framework:
547 lldbFrameworkPath = args.framework
548
549 if args.executable:
550 lldbExecutablePath = args.executable
551
Greg Clayton4793e942012-09-04 15:42:49 +0000552 if args.n:
553 noHeaders = True
554
555 if args.p:
556 if args.p.startswith('-'):
557 usage(parser)
558 regexp = args.p
559
Daniel Malea361eb432013-02-15 21:31:37 +0000560 if args.q:
561 noHeaders = True
562 parsable = True
563
Jim Ingham75f260a2013-02-19 20:39:27 +0000564 if args.P:
565 progress_bar = True
566 verbose = 0
567
Greg Clayton4793e942012-09-04 15:42:49 +0000568 if args.R:
569 if args.R.startswith('-'):
570 usage(parser)
571 rdir = os.path.abspath(args.R)
572 if os.path.exists(rdir):
573 import shutil
574 print 'Removing tree:', rdir
575 shutil.rmtree(rdir)
576
577 if args.r:
578 if args.r.startswith('-'):
579 usage(parser)
580 rdir = os.path.abspath(args.r)
581 if os.path.exists(rdir):
582 print 'Relocated directory:', rdir, 'must not exist!'
583 usage(parser)
584
585 if args.S:
586 skip_build_and_cleanup = True
587
588 if args.s:
589 if args.s.startswith('-'):
590 usage(parser)
591 sdir_name = args.s
592
593 if args.t:
594 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
595
Greg Clayton4793e942012-09-04 15:42:49 +0000596 if args.v:
597 verbose = 2
598
599 if args.w:
600 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
601
602 if args.X:
603 if args.X.startswith('-'):
604 usage(parser)
605 excluded.add(args.X)
606
607 if args.x:
608 if args.x.startswith('-'):
609 usage(parser)
610 bmBreakpointSpec = args.x
611
612 # argparse makes sure we have a number
613 if args.y:
614 bmIterationCount = args.y
615
616 # argparse makes sure we have a number
617 if args.sharp:
618 count = args.sharp
Johnny Chenaf149a02010-09-16 17:11:30 +0000619
Jim Ingham4f347cb2011-04-13 21:11:41 +0000620 if do_help == True:
Greg Clayton4793e942012-09-04 15:42:49 +0000621 usage(parser)
Jim Ingham4f347cb2011-04-13 21:11:41 +0000622
Johnny Chencc659ad2010-12-10 19:02:23 +0000623 # Do not specify both '-a' and '+a' at the same time.
624 if dont_do_python_api_test and just_do_python_api_test:
Greg Clayton4793e942012-09-04 15:42:49 +0000625 usage(parser)
Johnny Chencc659ad2010-12-10 19:02:23 +0000626
Johnny Chenaf149a02010-09-16 17:11:30 +0000627 # Gather all the dirs passed on the command line.
Greg Clayton4793e942012-09-04 15:42:49 +0000628 if len(args.args) > 0:
629 testdirs = map(os.path.abspath, args.args)
Johnny Chenaf149a02010-09-16 17:11:30 +0000630
Johnny Chen548aefd2010-10-11 22:25:46 +0000631 # If '-r dir' is specified, the tests should be run under the relocated
632 # directory. Let's copy the testdirs over.
633 if rdir:
634 from shutil import copytree, ignore_patterns
635
636 tmpdirs = []
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000637 orig_testdirs = testdirs[:]
Johnny Chen548aefd2010-10-11 22:25:46 +0000638 for srcdir in testdirs:
Johnny Chen1abe4c02012-03-20 00:33:51 +0000639 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
640 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
641 # Utilize the relative path to the 'test' directory to make our destination dir path.
Greg Clayton4793e942012-09-04 15:42:49 +0000642 if ("test" + os.sep) in srcdir:
643 to_split_on = "test" + os.sep
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000644 else:
645 to_split_on = "test"
646 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
647 dstdir = dstdir.rstrip(os.sep)
Johnny Chen548aefd2010-10-11 22:25:46 +0000648 # Don't copy the *.pyc and .svn stuffs.
649 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
650 tmpdirs.append(dstdir)
651
652 # This will be our modified testdirs.
653 testdirs = tmpdirs
654
655 # With '-r dir' specified, there's no cleanup of intermediate test files.
656 os.environ["LLDB_DO_CLEANUP"] = 'NO'
657
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000658 # If the original testdirs is ['test'], the make directory has already been copied
Johnny Chen548aefd2010-10-11 22:25:46 +0000659 # recursively and is contained within the rdir/test dir. For anything
660 # else, we would need to copy over the make directory and its contents,
661 # so that, os.listdir(rdir) looks like, for example:
662 #
663 # array_types conditional_break make
664 #
665 # where the make directory contains the Makefile.rules file.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000666 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000667 scriptdir = os.path.dirname(__file__)
Johnny Chen548aefd2010-10-11 22:25:46 +0000668 # Don't copy the .svn stuffs.
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000669 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
Johnny Chen548aefd2010-10-11 22:25:46 +0000670 ignore=ignore_patterns('.svn'))
671
672 #print "testdirs:", testdirs
673
Johnny Chenb40056b2010-09-21 00:09:27 +0000674 # Source the configFile if specified.
675 # The side effect, if any, will be felt from this point on. An example
676 # config file may be these simple two lines:
677 #
678 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
679 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
680 #
681 # which will reassign the two file objects to sys.stderr and sys.stdout,
682 # respectively.
683 #
Johnny Chen8c130642012-08-22 17:53:02 +0000684 # See also lldb-trunk/examples/test/usage-config.
Johnny Chenac97a6b2012-04-16 18:55:15 +0000685 global config, pre_flight, post_flight
Johnny Chenb40056b2010-09-21 00:09:27 +0000686 if configFile:
687 # Pass config (a dictionary) as the locals namespace for side-effect.
688 execfile(configFile, globals(), config)
Johnny Chenac97a6b2012-04-16 18:55:15 +0000689 print "config:", config
690 if "pre_flight" in config:
691 pre_flight = config["pre_flight"]
692 if not callable(pre_flight):
693 print "fatal error: pre_flight is not callable, exiting."
694 sys.exit(1)
695 if "post_flight" in config:
696 post_flight = config["post_flight"]
697 if not callable(post_flight):
698 print "fatal error: post_flight is not callable, exiting."
699 sys.exit(1)
Johnny Chenb40056b2010-09-21 00:09:27 +0000700 #print "sys.stderr:", sys.stderr
701 #print "sys.stdout:", sys.stdout
702
Johnny Chenaf149a02010-09-16 17:11:30 +0000703
Johnny Chen9707bb62010-06-25 21:14:08 +0000704def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000705 """
706 Add LLDB.framework/Resources/Python to the search paths for modules.
707 As a side effect, we also discover the 'lldb' executable and export it here.
708 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000709
Johnny Chen548aefd2010-10-11 22:25:46 +0000710 global rdir
711 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000712 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000713 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000714 global svn_info
Sean Callanan0acf4c62012-10-24 22:45:39 +0000715 global lldbFrameworkPath
716 global lldbExecutablePath
Johnny Chen548aefd2010-10-11 22:25:46 +0000717
Johnny Chen9707bb62010-06-25 21:14:08 +0000718 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000719 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 +0000720 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
721 else:
722 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000723 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000724 print "This script expects to reside in lldb's test directory."
725 sys.exit(-1)
726
Johnny Chen548aefd2010-10-11 22:25:46 +0000727 if rdir:
728 # Set up the LLDB_TEST environment variable appropriately, so that the
729 # individual tests can be located relatively.
730 #
731 # See also lldbtest.TestBase.setUpClass(cls).
732 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
733 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
734 else:
735 os.environ["LLDB_TEST"] = rdir
736 else:
737 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000738
739 # Set up the LLDB_SRC environment variable, so that the tests can locate
740 # the LLDB source code.
741 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
742
Johnny Chen9de4ede2010-08-31 17:42:54 +0000743 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000744 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000745
Johnny Chen8a3c0432011-03-11 20:13:06 +0000746 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000747 sys.path.append(scriptPath)
748 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000749 sys.path.append(pexpectPath)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000750
Johnny Chen26901c82011-03-11 19:47:23 +0000751 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000752 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000753
Johnny Chen26901c82011-03-11 19:47:23 +0000754 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000755 xcode3_build_dir = ['build']
756 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
757 dbg = ['Debug']
Sean Callanand9d94632012-09-26 21:16:15 +0000758 dbc = ['DebugClang']
Johnny Chen6a564a42011-02-15 18:50:19 +0000759 rel = ['Release']
760 bai = ['BuildAndIntegration']
761 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000762
763 # Some of the tests can invoke the 'lldb' command directly.
764 # We'll try to locate the appropriate executable right here.
765
Sean Callanan0acf4c62012-10-24 22:45:39 +0000766 lldbExec = None
767 if lldbExecutablePath:
768 if is_exe(lldbExecutablePath):
769 lldbExec = lldbExecutablePath
Sean Callanan502000d2012-11-01 21:23:21 +0000770 lldbHere = lldbExec
Sean Callanan0acf4c62012-10-24 22:45:39 +0000771 else:
772 print lldbExecutablePath + " is not an executable"
773 sys.exit(-1)
Johnny Chen6033bed2011-08-26 00:00:01 +0000774 else:
Sean Callanan0acf4c62012-10-24 22:45:39 +0000775 # First, you can define an environment variable LLDB_EXEC specifying the
776 # full pathname of the lldb executable.
777 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
778 lldbExec = os.environ["LLDB_EXEC"]
779 else:
780 lldbExec = None
781
782 executable = ['lldb']
783 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
784 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
785 dbcExec = os.path.join(base, *(xcode3_build_dir + dbc + executable))
786 dbcExec2 = os.path.join(base, *(xcode4_build_dir + dbc + executable))
787 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
788 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
789 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
790 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
791
792 # The 'lldb' executable built here in the source tree.
793 lldbHere = None
794 if is_exe(dbgExec):
795 lldbHere = dbgExec
796 elif is_exe(dbgExec2):
797 lldbHere = dbgExec2
798 elif is_exe(dbcExec):
799 lldbHere = dbcExec
800 elif is_exe(dbcExec2):
801 lldbHere = dbcExec2
802 elif is_exe(relExec):
803 lldbHere = relExec
804 elif is_exe(relExec2):
805 lldbHere = relExec2
806 elif is_exe(baiExec):
807 lldbHere = baiExec
808 elif is_exe(baiExec2):
809 lldbHere = baiExec2
810 elif lldbExec:
811 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000812
Sean Callanan0acf4c62012-10-24 22:45:39 +0000813 # One last chance to locate the 'lldb' executable.
814 if not lldbExec:
815 lldbExec = which('lldb')
816 if lldbHere and not lldbExec:
817 lldbExec = lldbHere
Daniel Malea2777b012013-02-06 16:55:07 +0000818 if lldbExec and not lldbHere:
819 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000820
821 if lldbHere:
822 os.environ["LLDB_HERE"] = lldbHere
Matt Kopeca964b092013-02-20 20:54:10 +0000823 os.environ["LLDB_LIB_DIR"] = os.path.split(lldbHere)[0]
Sean Callanan502000d2012-11-01 21:23:21 +0000824 if not noHeaders:
Matt Kopeca964b092013-02-20 20:54:10 +0000825 print "LLDB library dir:", os.environ["LLDB_LIB_DIR"]
Sean Callanan502000d2012-11-01 21:23:21 +0000826 os.system('%s -v' % lldbHere)
Johnny Chen26901c82011-03-11 19:47:23 +0000827
828 if not lldbExec:
829 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
830 else:
831 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000832 #print "The 'lldb' from PATH env variable", lldbExec
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000833
Johnny Chenb264c9b2011-06-24 22:52:05 +0000834 if os.path.isdir(os.path.join(base, '.svn')):
835 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
836 svn_info = pipe.stdout.read()
837 elif os.path.isdir(os.path.join(base, '.git')):
838 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
839 svn_info = pipe.stdout.read()
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000840 if not noHeaders:
841 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000842
843 global ignore
844
Johnny Chen9707bb62010-06-25 21:14:08 +0000845 lldbPath = None
Sean Callanan0acf4c62012-10-24 22:45:39 +0000846 if lldbFrameworkPath:
847 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python')
848 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
849 lldbPath = candidatePath
850 if not lldbPath:
851 print 'Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath
852 sys.exit(-1)
853 else:
854 # The '-i' option is used to skip looking for lldb.py in the build tree.
855 if ignore:
856 return
Jim Inghamaa93c932012-12-21 22:22:26 +0000857
858 # If our lldb supports the -P option, use it to find the python path:
859 init_in_python_dir = 'lldb/__init__.py'
860 import pexpect
861 lldb_dash_p_result = None
862
863 if lldbHere:
864 lldb_dash_p_result = pexpect.run("%s -P"%(lldbHere))
865 elif lldbExec:
866 lldb_dash_p_result = pexpect.run("%s -P"%(lldbExec))
867
868 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")):
869 lines = lldb_dash_p_result.splitlines()
870 if len(lines) == 1 and os.path.isfile(os.path.join(lines[0], init_in_python_dir)):
871 lldbPath = lines[0]
Daniel Malea21e32a62013-01-04 23:35:13 +0000872 if "linux" in sys.platform:
Matt Kopeca964b092013-02-20 20:54:10 +0000873 os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPath, '..', '..')
Jim Inghamaa93c932012-12-21 22:22:26 +0000874
875 if not lldbPath:
876 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
877 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
878 dbcPath = os.path.join(base, *(xcode3_build_dir + dbc + python_resource_dir))
879 dbcPath2 = os.path.join(base, *(xcode4_build_dir + dbc + python_resource_dir))
880 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
881 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
882 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
883 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Sean Callanan0acf4c62012-10-24 22:45:39 +0000884
Jim Inghamaa93c932012-12-21 22:22:26 +0000885 if os.path.isfile(os.path.join(dbgPath, init_in_python_dir)):
886 lldbPath = dbgPath
887 elif os.path.isfile(os.path.join(dbgPath2, init_in_python_dir)):
888 lldbPath = dbgPath2
889 elif os.path.isfile(os.path.join(dbcPath, init_in_python_dir)):
890 lldbPath = dbcPath
891 elif os.path.isfile(os.path.join(dbcPath2, init_in_python_dir)):
892 lldbPath = dbcPath2
893 elif os.path.isfile(os.path.join(relPath, init_in_python_dir)):
894 lldbPath = relPath
895 elif os.path.isfile(os.path.join(relPath2, init_in_python_dir)):
896 lldbPath = relPath2
897 elif os.path.isfile(os.path.join(baiPath, init_in_python_dir)):
898 lldbPath = baiPath
899 elif os.path.isfile(os.path.join(baiPath2, init_in_python_dir)):
900 lldbPath = baiPath2
901
Sean Callanan0acf4c62012-10-24 22:45:39 +0000902 if not lldbPath:
903 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
904 print relPath + ', or ' + baiPath
905 sys.exit(-1)
Johnny Chen9707bb62010-06-25 21:14:08 +0000906
Jim Inghamaa93c932012-12-21 22:22:26 +0000907 # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
908 # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
909 (before, frameWithVersion, after) = lldbPath.rpartition("LLDB.framework/Versions/A")
910 if frameWithVersion != "" :
911 lldbPath = before + "LLDB.framework" + after
912
Enrico Granata01458ca2012-10-23 00:09:02 +0000913 # If tests need to find LLDB_FRAMEWORK, now they can do it
914 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPath))
915
Johnny Chenaf149a02010-09-16 17:11:30 +0000916 # This is to locate the lldb.py module. Insert it right after sys.path[0].
917 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000918 if dumpSysPath:
919 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000920
Johnny Chen9707bb62010-06-25 21:14:08 +0000921
Johnny Chencd0279d2010-09-20 18:07:50 +0000922def doDelay(delta):
923 """Delaying startup for delta-seconds to facilitate debugger attachment."""
924 def alarm_handler(*args):
925 raise Exception("timeout")
926
927 signal.signal(signal.SIGALRM, alarm_handler)
928 signal.alarm(delta)
929 sys.stdout.write("pid=%d\n" % os.getpid())
930 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
931 delta)
932 sys.stdout.flush()
933 try:
934 text = sys.stdin.readline()
935 except:
936 text = ""
937 signal.alarm(0)
938 sys.stdout.write("proceeding...\n")
939 pass
940
941
Johnny Chen9707bb62010-06-25 21:14:08 +0000942def visit(prefix, dir, names):
943 """Visitor function for os.path.walk(path, visit, arg)."""
944
945 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000946 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000947 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000948 global fs4all
Johnny Chene9eae812012-01-18 05:15:00 +0000949 global excluded
950
951 if set(dir.split(os.sep)).intersection(excluded):
952 #print "Detected an excluded dir component: %s" % dir
953 return
Johnny Chen9707bb62010-06-25 21:14:08 +0000954
955 for name in names:
956 if os.path.isdir(os.path.join(dir, name)):
957 continue
958
959 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000960 # Try to match the regexp pattern, if specified.
961 if regexp:
962 import re
963 if re.search(regexp, name):
964 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
965 pass
966 else:
967 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
968 continue
969
Johnny Chen953864a2010-10-12 21:35:54 +0000970 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000971
972 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000973 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000974 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000975 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000976
977 # Thoroughly check the filterspec against the base module and admit
978 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000979 filterspec = None
980 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000981 # Optimistically set the flag to True.
982 filtered = True
983 module = __import__(base)
984 parts = filterspec.split('.')
985 obj = module
986 for part in parts:
987 try:
988 parent, obj = obj, getattr(obj, part)
989 except AttributeError:
990 # The filterspec has failed.
991 filtered = False
992 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000993
Johnny Chendb4be602011-08-12 23:55:07 +0000994 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000995 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +0000996 #print "adding filter spec %s to module %s" % (filterspec, module)
997 suite.addTests(
998 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
999 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +00001000
1001 # Forgo this module if the (base, filterspec) combo is invalid
1002 # and no '-g' option is specified
1003 if filters and fs4all and not filtered:
1004 continue
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001005
Johnny Chendb4be602011-08-12 23:55:07 +00001006 # Add either the filtered test case(s) (which is done before) or the entire test class.
1007 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +00001008 # A simple case of just the module name. Also the failover case
1009 # from the filterspec branch when the (base, filterspec) combo
1010 # doesn't make sense.
1011 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +00001012
1013
Johnny Chencd0279d2010-09-20 18:07:50 +00001014def lldbLoggings():
1015 """Check and do lldb loggings if necessary."""
1016
1017 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
1018 # defined. Use ${LLDB_LOG} to specify the log file.
1019 ci = lldb.DBG.GetCommandInterpreter()
1020 res = lldb.SBCommandReturnObject()
1021 if ("LLDB_LOG" in os.environ):
1022 if ("LLDB_LOG_OPTION" in os.environ):
1023 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
1024 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +00001025 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +00001026 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +00001027 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +00001028 res)
1029 if not res.Succeeded():
1030 raise Exception('log enable failed (check LLDB_LOG env variable.')
1031 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
1032 # Use ${GDB_REMOTE_LOG} to specify the log file.
1033 if ("GDB_REMOTE_LOG" in os.environ):
1034 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
1035 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
1036 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +00001037 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +00001038 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +00001039 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +00001040 + gdb_remote_log_option,
1041 res)
1042 if not res.Succeeded():
1043 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
1044
Johnny Chen067022b2011-01-19 19:31:46 +00001045def getMyCommandLine():
Johnny Chen067022b2011-01-19 19:31:46 +00001046 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
1047 lines = ps.split('\n')
1048 cmd_line = lines[1]
1049 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +00001050
Johnny Chend96b5682010-11-05 17:30:53 +00001051# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001052# #
1053# Execution of the test driver starts here #
1054# #
Johnny Chend96b5682010-11-05 17:30:53 +00001055# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001056
Johnny Chen2891bb02011-09-16 01:04:26 +00001057def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +00001058 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1059 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1060 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +00001061 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +00001062 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +00001063 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +00001064 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
1065 print "Exiting..."
1066 sys.exit(0)
1067
1068# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1069# does not exist before proceeding to running the test suite.
1070if sys.platform.startswith("darwin"):
1071 checkDsymForUUIDIsNotOn()
1072
Johnny Chen9707bb62010-06-25 21:14:08 +00001073#
Johnny Chenaf149a02010-09-16 17:11:30 +00001074# Start the actions by first parsing the options while setting up the test
1075# directories, followed by setting up the search paths for lldb utilities;
1076# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +00001077#
Johnny Chenaf149a02010-09-16 17:11:30 +00001078parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +00001079setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +00001080
1081#
1082# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
1083#
1084if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +00001085 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +00001086
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001087#
Johnny Chen41998192010-10-01 22:59:49 +00001088# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +00001089if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +00001090 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1091
1092#
Johnny Chen79723352010-10-12 15:53:22 +00001093# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001094#
Johnny Chen9707bb62010-06-25 21:14:08 +00001095for testdir in testdirs:
1096 os.path.walk(testdir, visit, 'Test')
1097
Johnny Chenb40056b2010-09-21 00:09:27 +00001098#
Johnny Chen9707bb62010-06-25 21:14:08 +00001099# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +00001100#
Johnny Chencd0279d2010-09-20 18:07:50 +00001101
Johnny Chen1bfbd412010-06-29 19:44:16 +00001102# For the time being, let's bracket the test runner within the
1103# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001104import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +00001105# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
1106# there's no need to call it a second time.
1107#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001108atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +00001109
Johnny Chen909e5a62010-07-01 22:52:57 +00001110# Create a singleton SBDebugger in the lldb namespace.
1111lldb.DBG = lldb.SBDebugger.Create()
1112
Johnny Chen4f93bf12010-12-10 00:51:23 +00001113# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +00001114lldb.blacklist = blacklist
1115
Johnny Chenac97a6b2012-04-16 18:55:15 +00001116# The pre_flight and post_flight come from reading a config file.
1117lldb.pre_flight = pre_flight
1118lldb.post_flight = post_flight
1119def getsource_if_available(obj):
1120 """
1121 Return the text of the source code for an object if available. Otherwise,
1122 a print representation is returned.
1123 """
1124 import inspect
1125 try:
1126 return inspect.getsource(obj)
1127 except:
1128 return repr(obj)
1129
Daniel Malea361eb432013-02-15 21:31:37 +00001130if not noHeaders:
1131 print "lldb.pre_flight:", getsource_if_available(lldb.pre_flight)
1132 print "lldb.post_flight:", getsource_if_available(lldb.post_flight)
Johnny Chenac97a6b2012-04-16 18:55:15 +00001133
Johnny Chena3ed7d82012-04-06 00:56:05 +00001134# Put all these test decorators in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +00001135lldb.dont_do_python_api_test = dont_do_python_api_test
1136lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +00001137lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +00001138lldb.dont_do_dsym_test = dont_do_dsym_test
1139lldb.dont_do_dwarf_test = dont_do_dwarf_test
Johnny Chen4f93bf12010-12-10 00:51:23 +00001140
Johnny Chen028d8eb2011-11-17 19:57:27 +00001141# Do we need to skip build and cleanup?
1142lldb.skip_build_and_cleanup = skip_build_and_cleanup
1143
Johnny Chen5f2ed172011-10-20 18:43:28 +00001144# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +00001145lldb.bmExecutable = bmExecutable
1146lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +00001147lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +00001148
Johnny Chen38f823c2011-10-11 01:30:27 +00001149# And don't forget the runHooks!
1150lldb.runHooks = runHooks
1151
Johnny Chencd0279d2010-09-20 18:07:50 +00001152# Turn on lldb loggings if necessary.
1153lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +00001154
Johnny Chen7987ac92010-08-09 20:40:52 +00001155# Install the control-c handler.
1156unittest2.signals.installHandler()
1157
Johnny Chen125fc2b2010-10-21 16:55:35 +00001158# If sdir_name is not specified through the '-s sdir_name' option, get a
1159# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1160# be used when/if we want to dump the session info of individual test cases
1161# later on.
Johnny Chence681462010-10-19 00:25:01 +00001162#
1163# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chena73ad662012-08-16 19:15:21 +00001164import datetime
1165# The windows platforms don't like ':' in the pathname.
1166timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +00001167if not sdir_name:
Johnny Chena73ad662012-08-16 19:15:21 +00001168 sdir_name = timestamp_started
Peter Collingbourne132476f2011-06-20 23:55:53 +00001169os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +00001170
Johnny Chenfe5f1ed2011-10-21 18:33:27 +00001171if not noHeaders:
1172 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1173 " will go into directory '%s'\n" % sdir_name)
1174 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +00001175
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001176if not os.path.isdir(sdir_name):
1177 os.mkdir(sdir_name)
Johnny Chena73ad662012-08-16 19:15:21 +00001178fname = os.path.join(sdir_name, "TestStarted")
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001179with open(fname, "w") as f:
Johnny Chena73ad662012-08-16 19:15:21 +00001180 print >> f, "Test started at: %s\n" % timestamp_started
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001181 print >> f, svn_info
1182 print >> f, "Command invoked: %s\n" % getMyCommandLine()
1183
Johnny Chenb40056b2010-09-21 00:09:27 +00001184#
1185# Invoke the default TextTestRunner to run the test suite, possibly iterating
1186# over different configurations.
1187#
1188
Johnny Chenb40056b2010-09-21 00:09:27 +00001189iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +00001190iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001191
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001192if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001193 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001194
1195if isinstance(archs, list) and len(archs) >= 1:
1196 iterArchs = True
1197
1198if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001199 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001200
Johnny Chen92693b52012-03-09 02:11:37 +00001201#
1202# Add some intervention here to sanity check that the compilers requested are sane.
1203# If found not to be an executable program, the invalid one is dropped from the list.
1204for i in range(len(compilers)):
1205 c = compilers[i]
1206 if which(c):
1207 continue
1208 else:
1209 if sys.platform.startswith("darwin"):
1210 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1211 cmd_output = pipe.stdout.read()
1212 if cmd_output:
1213 if "not found" in cmd_output:
1214 print "dropping %s from the compilers used" % c
1215 compilers.remove(i)
1216 else:
1217 compilers[i] = cmd_output.split('\n')[0]
1218 print "'xcrun -find %s' returning %s" % (c, compilers[i])
1219
Daniel Malea361eb432013-02-15 21:31:37 +00001220if not parsable:
1221 print "compilers=%s" % str(compilers)
Johnny Chen92693b52012-03-09 02:11:37 +00001222
1223if not compilers or len(compilers) == 0:
1224 print "No eligible compiler found, exiting."
1225 sys.exit(1)
1226
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001227if isinstance(compilers, list) and len(compilers) >= 1:
1228 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001229
Johnny Chen953864a2010-10-12 21:35:54 +00001230# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1231# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001232if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001233 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001234# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1235if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001236 old_stderr = sys.stderr
1237 old_stdout = sys.stdout
1238 new_stderr = None
1239 new_stdout = None
1240
Johnny Chend96b5682010-11-05 17:30:53 +00001241# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001242for ia in range(len(archs) if iterArchs else 1):
1243 archConfig = ""
1244 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001245 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001246 archConfig = "arch=%s" % archs[ia]
1247 for ic in range(len(compilers) if iterCompilers else 1):
1248 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001249 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001250 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1251 else:
1252 configString = archConfig
1253
Johnny Chenb40056b2010-09-21 00:09:27 +00001254 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001255 # Translate ' ' to '-' for pathname component.
1256 from string import maketrans
1257 tbl = maketrans(' ', '-')
1258 configPostfix = configString.translate(tbl)
1259
1260 # Check whether we need to split stderr/stdout into configuration
1261 # specific files.
1262 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1263 if new_stderr:
1264 new_stderr.close()
1265 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1266 sys.stderr = new_stderr
1267 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1268 if new_stdout:
1269 new_stdout.close()
1270 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1271 sys.stdout = new_stdout
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001272
Johnny Chen953864a2010-10-12 21:35:54 +00001273 # If we specified a relocated directory to run the test suite, do
1274 # the extra housekeeping to copy the testdirs to a configStringified
1275 # directory and to update sys.path before invoking the test runner.
1276 # The purpose is to separate the configuration-specific directories
1277 # from each other.
1278 if rdir:
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001279 from shutil import copytree, rmtree, ignore_patterns
Johnny Chen953864a2010-10-12 21:35:54 +00001280
Johnny Chen953864a2010-10-12 21:35:54 +00001281 newrdir = "%s.%s" % (rdir, configPostfix)
1282
1283 # Copy the tree to a new directory with postfix name configPostfix.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001284 if os.path.exists(newrdir):
1285 rmtree(newrdir)
Johnny Chen953864a2010-10-12 21:35:54 +00001286 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1287
Filipe Cabecinhas0e1d06d2012-08-08 15:23:24 +00001288 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001289 # level test directory.
1290 #
1291 # See also lldbtest.TestBase.setUpClass(cls).
1292 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1293 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1294 else:
1295 os.environ["LLDB_TEST"] = newrdir
1296
1297 # And update the Python search paths for modules.
1298 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1299
1300 # Output the configuration.
Daniel Malea361eb432013-02-15 21:31:37 +00001301 if not parsable:
1302 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001303
1304 #print "sys.stderr name is", sys.stderr.name
1305 #print "sys.stdout name is", sys.stdout.name
1306
1307 # First, write out the number of collected test cases.
Daniel Malea361eb432013-02-15 21:31:37 +00001308 if not parsable:
1309 sys.stderr.write(separator + "\n")
1310 sys.stderr.write("Collected %d test%s\n\n"
1311 % (suite.countTestCases(),
1312 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001313
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001314 class LLDBTestResult(unittest2.TextTestResult):
1315 """
Johnny Chen26be4532010-11-09 23:56:14 +00001316 Enforce a singleton pattern to allow introspection of test progress.
1317
1318 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1319 to enable each test instance to track its failure/error status. It
1320 is used in the LLDB test framework to emit detailed trace messages
1321 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001322 """
1323 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001324 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001325
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001326 @staticmethod
1327 def getTerminalSize():
1328 import os
1329 env = os.environ
1330 def ioctl_GWINSZ(fd):
1331 try:
1332 import fcntl, termios, struct, os
1333 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
1334 '1234'))
1335 except:
1336 return
1337 return cr
1338 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
1339 if not cr:
1340 try:
1341 fd = os.open(os.ctermid(), os.O_RDONLY)
1342 cr = ioctl_GWINSZ(fd)
1343 os.close(fd)
1344 except:
1345 pass
1346 if not cr:
1347 cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
1348 return int(cr[1]), int(cr[0])
1349
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001350 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001351 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001352 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001353 super(LLDBTestResult, self).__init__(*args)
1354 LLDBTestResult.__singleton__ = self
1355 # Now put this singleton into the lldb module namespace.
1356 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001357 # Computes the format string for displaying the counter.
1358 global suite
1359 counterWidth = len(str(suite.countTestCases()))
1360 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001361 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001362 # This counts from 1 .. suite.countTestCases().
1363 self.counter = 0
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001364 (width, height) = LLDBTestResult.getTerminalSize()
Enrico Granata77215892013-02-15 00:32:05 +00001365 self.progressbar = None
Jim Ingham75f260a2013-02-19 20:39:27 +00001366 global progress_bar
Daniel Malea361eb432013-02-15 21:31:37 +00001367 if width > 10 and not parsable and progress_bar:
Enrico Granata77215892013-02-15 00:32:05 +00001368 try:
1369 self.progressbar = progress.ProgressWithEvents(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10)
1370 except:
1371 self.progressbar = None
Johnny Chen810042e2011-01-05 20:24:11 +00001372
Daniel Malea361eb432013-02-15 21:31:37 +00001373 def _config_string(self, test):
1374 compiler = getattr(test, "getCompiler", None)
1375 arch = getattr(test, "getArchitecture", None)
1376 return "%s-%s" % (compiler() if compiler else "", arch() if arch else "")
1377
Johnny Chenbe452272012-04-19 21:33:55 +00001378 def _exc_info_to_string(self, err, test):
1379 """Overrides superclass TestResult's method in order to append
1380 our test config info string to the exception info string."""
1381 modified_exc_string = '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1382 test.getArchitecture(),
1383 test.getCompiler())
1384 return modified_exc_string
1385
Johnny Chenc87fd492011-01-05 22:50:11 +00001386 def getDescription(self, test):
1387 doc_first_line = test.shortDescription()
1388 if self.descriptions and doc_first_line:
1389 return '\n'.join((str(test), self.indentation + doc_first_line))
1390 else:
1391 return str(test)
1392
Enrico Granataac3a8e22012-09-21 19:10:53 +00001393 def getCategoriesForTest(self,test):
1394 if hasattr(test,"getCategories"):
1395 test_categories = test.getCategories()
1396 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1397 test_categories = test.__self__.getCategories()
1398 else:
1399 test_categories = []
1400 if test_categories == None:
1401 test_categories = []
1402 return test_categories
1403
1404 def shouldSkipBecauseOfCategories(self,test):
1405 global useCategories
1406 import inspect
1407 if useCategories:
1408 global categoriesList
1409 test_categories = self.getCategoriesForTest(test)
1410 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
1411 return True
1412 return False
1413
1414 def hardMarkAsSkipped(self,test):
1415 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1416 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1417
Johnny Chen810042e2011-01-05 20:24:11 +00001418 def startTest(self, test):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001419 if self.shouldSkipBecauseOfCategories(test):
1420 self.hardMarkAsSkipped(test)
Johnny Chen810042e2011-01-05 20:24:11 +00001421 self.counter += 1
1422 if self.showAll:
1423 self.stream.write(self.fmt % self.counter)
1424 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001425
Daniel Malea361eb432013-02-15 21:31:37 +00001426 def addSuccess(self, test):
1427 global parsable
1428 super(LLDBTestResult, self).addSuccess(test)
1429 if parsable:
1430 self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1431
Johnny Chence681462010-10-19 00:25:01 +00001432 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001433 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001434 global parsable
Johnny Chen63c2cba2010-10-29 22:20:36 +00001435 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001436 super(LLDBTestResult, self).addError(test, err)
1437 method = getattr(test, "markError", None)
1438 if method:
1439 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001440 if parsable:
1441 self.stream.write("ERROR: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Johnny Chence681462010-10-19 00:25:01 +00001442
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001443 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001444 global sdir_has_content
Enrico Granataac3a8e22012-09-21 19:10:53 +00001445 global failuresPerCategory
Daniel Malea361eb432013-02-15 21:31:37 +00001446 global parsable
Johnny Chen63c2cba2010-10-29 22:20:36 +00001447 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001448 super(LLDBTestResult, self).addFailure(test, err)
1449 method = getattr(test, "markFailure", None)
1450 if method:
1451 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001452 if parsable:
1453 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Enrico Granataac3a8e22012-09-21 19:10:53 +00001454 if useCategories:
1455 test_categories = self.getCategoriesForTest(test)
1456 for category in test_categories:
1457 if category in failuresPerCategory:
1458 failuresPerCategory[category] = failuresPerCategory[category] + 1
1459 else:
1460 failuresPerCategory[category] = 1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001461
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001462 def addExpectedFailure(self, test, err):
1463 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001464 global parsable
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001465 sdir_has_content = True
1466 super(LLDBTestResult, self).addExpectedFailure(test, err)
1467 method = getattr(test, "markExpectedFailure", None)
1468 if method:
1469 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001470 if parsable:
1471 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001472
Johnny Chenf5b89092011-08-15 23:09:08 +00001473 def addSkip(self, test, reason):
1474 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001475 global parsable
Johnny Chenf5b89092011-08-15 23:09:08 +00001476 sdir_has_content = True
1477 super(LLDBTestResult, self).addSkip(test, reason)
1478 method = getattr(test, "markSkippedTest", None)
1479 if method:
1480 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001481 if parsable:
1482 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason))
Johnny Chenf5b89092011-08-15 23:09:08 +00001483
Johnny Chenab2f0662011-05-06 20:30:22 +00001484 def addUnexpectedSuccess(self, test):
1485 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001486 global parsable
Johnny Chenab2f0662011-05-06 20:30:22 +00001487 sdir_has_content = True
1488 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1489 method = getattr(test, "markUnexpectedSuccess", None)
1490 if method:
1491 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001492 if parsable:
1493 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1494
1495 if parsable:
1496 v = 0
1497 elif progress_bar:
1498 v = 1
1499 else:
1500 v = verbose
Johnny Chenab2f0662011-05-06 20:30:22 +00001501
Johnny Chen26be4532010-11-09 23:56:14 +00001502 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001503 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001504 result = unittest2.TextTestRunner(stream=sys.stderr,
Daniel Malea361eb432013-02-15 21:31:37 +00001505 verbosity=v,
Johnny Chen7d6d8442010-12-03 19:59:35 +00001506 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001507 resultclass=LLDBTestResult).run(suite)
1508 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001509 # We are invoking the same test suite more than once. In this case,
1510 # mark __ignore_singleton__ flag as True so the signleton pattern is
1511 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001512 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001513 for i in range(count):
Daniel Malea361eb432013-02-15 21:31:37 +00001514
Johnny Chen7d6d8442010-12-03 19:59:35 +00001515 result = unittest2.TextTestRunner(stream=sys.stderr,
Daniel Malea361eb432013-02-15 21:31:37 +00001516 verbosity=v,
Johnny Chen7d6d8442010-12-03 19:59:35 +00001517 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001518 resultclass=LLDBTestResult).run(suite)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001519
Daniel Malea24765572013-02-20 20:12:11 +00001520 failed = failed or not result.wasSuccessful()
Johnny Chen1bfbd412010-06-29 19:44:16 +00001521
Daniel Malea361eb432013-02-15 21:31:37 +00001522if sdir_has_content and not parsable:
Johnny Chenab2f0662011-05-06 20:30:22 +00001523 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1524 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001525
Enrico Granataac3a8e22012-09-21 19:10:53 +00001526if useCategories and len(failuresPerCategory) > 0:
1527 sys.stderr.write("Failures per category:\n")
1528 for category in failuresPerCategory:
1529 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
1530
Johnny Chena73ad662012-08-16 19:15:21 +00001531fname = os.path.join(sdir_name, "TestFinished")
1532with open(fname, "w") as f:
1533 print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1534
Johnny Chencd0279d2010-09-20 18:07:50 +00001535# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1536# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001537if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001538 print "Terminating Test suite..."
1539 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1540
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001541# Exiting.
Daniel Malea24765572013-02-20 20:12:11 +00001542sys.exit(failed)