blob: e9b60a32ab1ea20b1826b501180bcf451d4fd8a3 [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',
Jim Ingham60139f32013-02-25 23:51:06 +000082'pyapi':'Tests related to the Python API',
Enrico Granata3cb3fe32013-06-18 00:22:27 +000083'basic_process': 'Basic process execution sniff tests.',
84'cmdline' : 'Tests related to the LLDB command-line interface'
Enrico Granataac3a8e22012-09-21 19:10:53 +000085}
86
Johnny Chen9707bb62010-06-25 21:14:08 +000087# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000088suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000089
Johnny Chen4f93bf12010-12-10 00:51:23 +000090# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000091# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
92# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000093dont_do_python_api_test = False
94
95# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000096just_do_python_api_test = False
97
Johnny Chen82ccf402011-07-30 01:39:58 +000098# By default, benchmarks tests are not run.
99just_do_benchmarks_test = False
100
Johnny Chena3ed7d82012-04-06 00:56:05 +0000101# By default, both dsym and dwarf tests are performed.
102# Use @dsym_test or @dwarf_test decorators, defined in lldbtest.py, to mark a test
103# as a dsym or dwarf test. Use '-N dsym' or '-N dwarf' to exclude dsym or dwarf
104# tests from running.
Ed Mastebd5505c2013-06-25 19:59:56 +0000105dont_do_dsym_test = "linux" in sys.platform or "freebsd" in sys.platform
Johnny Chena3ed7d82012-04-06 00:56:05 +0000106dont_do_dwarf_test = False
107
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000108# The blacklist is optional (-b blacklistFile) and allows a central place to skip
109# testclass's and/or testclass.testmethod's.
110blacklist = None
111
112# The dictionary as a result of sourcing blacklistFile.
113blacklistConfig = {}
114
Enrico Granataac3a8e22012-09-21 19:10:53 +0000115# The list of categories we said we care about
116categoriesList = None
117# set to true if we are going to use categories for cherry-picking test cases
118useCategories = False
119# use this to track per-category failures
120failuresPerCategory = {}
121
Sean Callanan0acf4c62012-10-24 22:45:39 +0000122# The path to LLDB.framework is optional.
123lldbFrameworkPath = None
124
125# The path to lldb is optional
126lldbExecutablePath = None
127
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000128# The config file is optional.
129configFile = None
130
Johnny Chend2acdb32010-11-16 22:42:58 +0000131# Test suite repeat count. Can be overwritten with '-# count'.
132count = 1
133
Johnny Chenb40056b2010-09-21 00:09:27 +0000134# The dictionary as a result of sourcing configFile.
135config = {}
Johnny Chenac97a6b2012-04-16 18:55:15 +0000136# The pre_flight and post_flight functions come from reading a config file.
137pre_flight = None
138post_flight = None
Johnny Chenb40056b2010-09-21 00:09:27 +0000139
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000140# The 'archs' and 'compilers' can be specified via either command line or configFile,
Greg Clayton4793e942012-09-04 15:42:49 +0000141# with the command line overriding the configFile. The corresponding options can be
Filipe Cabecinhasd3eb8372013-02-16 09:05:23 +0000142# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386']
Greg Clayton4793e942012-09-04 15:42:49 +0000143# and "-C gcc -C clang" => compilers=['gcc', 'clang'].
144archs = None # Must be initialized after option parsing
145compilers = None # Must be initialized after option parsing
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000146
Johnny Chen1abe4c02012-03-20 00:33:51 +0000147# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
148# the inferior programs. The global variable cflags_extras provides a hook to do
149# just that.
150cflags_extras = ''
151
Johnny Chen91960d32010-09-08 20:56:16 +0000152# Delay startup in order for the debugger to attach.
153delay = False
154
Johnny Chend5362332011-01-29 01:21:04 +0000155# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000156dumpSysPath = False
157
Johnny Chene00c9302011-10-10 22:03:44 +0000158# Full path of the benchmark executable, as specified by the '-e' option.
159bmExecutable = None
160# The breakpoint specification of bmExecutable, as specified by the '-x' option.
161bmBreakpointSpec = None
Johnny Chen5f2ed172011-10-20 18:43:28 +0000162# The benchamrk iteration count, as specified by the '-y' option.
163bmIterationCount = -1
Johnny Chene00c9302011-10-10 22:03:44 +0000164
Johnny Chene9eae812012-01-18 05:15:00 +0000165# By default, don't exclude any directories. Use '-X' to add one excluded directory.
166excluded = set(['.svn', '.git'])
167
Johnny Chen7d6d8442010-12-03 19:59:35 +0000168# By default, failfast is False. Use '-F' to overwrite it.
169failfast = False
170
Johnny Chenc5fa0052011-07-29 22:54:56 +0000171# The filters (testclass.testmethod) used to admit tests into our test suite.
172filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000173
Johnny Chen38f823c2011-10-11 01:30:27 +0000174# The runhooks is a list of lldb commands specifically for the debugger.
175# Use '-k' to specify a runhook.
176runHooks = []
177
Johnny Chena224cd12010-11-08 01:21:03 +0000178# If '-g' is specified, the filterspec is not exclusive. If a test module does
179# not contain testclass.testmethod which matches the filterspec, the whole test
180# module is still admitted into our test suite. fs4all flag defaults to True.
181fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000182
Johnny Chenaf149a02010-09-16 17:11:30 +0000183# Ignore the build search path relative to this script to locate the lldb.py module.
184ignore = False
185
Johnny Chen028d8eb2011-11-17 19:57:27 +0000186# By default, we do not skip build and cleanup. Use '-S' option to override.
187skip_build_and_cleanup = False
188
Johnny Chen548aefd2010-10-11 22:25:46 +0000189# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000190skip_long_running_test = True
Johnny Chen41998192010-10-01 22:59:49 +0000191
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000192# By default, we print the build dir, lldb version, and svn info. Use '-n' option to
193# turn it off.
194noHeaders = False
195
Daniel Malea361eb432013-02-15 21:31:37 +0000196# Parsable mode silences headers, and any other output this script might generate, and instead
197# prints machine-readable output similar to what clang tests produce.
198parsable = False
199
Johnny Chen7c52ff12010-09-27 23:29:54 +0000200# The regular expression pattern to match against eligible filenames as our test cases.
201regexp = None
202
Johnny Chen548aefd2010-10-11 22:25:46 +0000203# By default, tests are executed in place and cleanups are performed afterwards.
204# Use '-r dir' option to relocate the tests and their intermediate files to a
205# different directory and to forgo any cleanups. The directory specified must
206# not exist yet.
207rdir = None
208
Johnny Chen125fc2b2010-10-21 16:55:35 +0000209# By default, recorded session info for errored/failed test are dumped into its
210# own file under a session directory named after the timestamp of the test suite
211# run. Use '-s session-dir-name' to specify a specific dir name.
212sdir_name = None
213
Johnny Chen63c2cba2010-10-29 22:20:36 +0000214# Set this flag if there is any session info dumped during the test run.
215sdir_has_content = False
216
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000217# svn_info stores the output from 'svn info lldb.base.dir'.
218svn_info = ''
219
Enrico Granata814c8132013-04-11 23:48:00 +0000220# svn_silent means do not try to obtain svn status
221svn_silent = True
222
Johnny Chen9707bb62010-06-25 21:14:08 +0000223# Default verbosity is 0.
Jim Ingham75f260a2013-02-19 20:39:27 +0000224verbose = 1
Johnny Chen9707bb62010-06-25 21:14:08 +0000225
Johnny Chen08967192011-11-18 00:19:29 +0000226# Set to True only if verbose is 0 and LLDB trace mode is off.
227progress_bar = False
228
Peter Collingbourne61aca482011-06-20 19:06:29 +0000229# By default, search from the script directory.
230testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000231
Johnny Chen877c7e42010-08-07 00:16:07 +0000232# Separator string.
233separator = '-' * 70
234
Daniel Malea24765572013-02-20 20:12:11 +0000235failed = False
Johnny Chen9707bb62010-06-25 21:14:08 +0000236
Greg Clayton4793e942012-09-04 15:42:49 +0000237def usage(parser):
238 parser.print_help()
Jim Ingham4f347cb2011-04-13 21:11:41 +0000239 if verbose > 0:
240 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000241Examples:
242
Johnny Chena224cd12010-11-08 01:21:03 +0000243This is an example of using the -f option to pinpoint to a specfic test class
244and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000245
Johnny Chena224cd12010-11-08 01:21:03 +0000246$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000247----------------------------------------------------------------------
248Collected 1 test
249
250test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
251Test 'frame variable this' when stopped on a class constructor. ... ok
252
253----------------------------------------------------------------------
254Ran 1 test in 1.396s
255
256OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000257
258And this is an example of using the -p option to run a single file (the filename
259matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
260
261$ ./dotest.py -v -p ObjC
262----------------------------------------------------------------------
263Collected 4 tests
264
265test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000266Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000267test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000268Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000269test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
270Lookup objective-c data types and evaluate expressions. ... ok
271test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
272Lookup objective-c data types and evaluate expressions. ... ok
273
274----------------------------------------------------------------------
275Ran 4 tests in 16.661s
276
277OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000278
Johnny Chen58f93922010-06-29 23:10:39 +0000279Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000280individual test cases can locate their supporting files correctly. The script
281tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000282relative to this script. See also the '-i' option in the following example.
283
284Finally, this is an example of using the lldb.py module distributed/installed by
285Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
286option to add some delay between two tests. It uses ARCH=x86_64 to specify that
287as the architecture and CC=clang to specify the compiler used for the test run:
288
289$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
290
291Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
292----------------------------------------------------------------------
293Collected 2 tests
294
295test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
296Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
297test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
298Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
299
300----------------------------------------------------------------------
301Ran 2 tests in 5.659s
302
303OK
304
305The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
306notify the directory containing the session logs for test failures or errors.
307In case there is any test failure/error, a similar message is appended at the
308end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000309
310Environment variables related to loggings:
311
312o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
313 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
314
315o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
316 'process.gdb-remote' subsystem with a default option of 'packets' if
317 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000318"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000319 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000320
321
Enrico Granata69d7c102013-05-07 00:36:28 +0000322def unique_string_match(yourentry,list):
323 candidate = None
324 for item in list:
325 if item.startswith(yourentry):
326 if candidate:
327 return None
328 candidate = item
329 return candidate
330
Enrico Granata6fa3c502013-06-22 00:15:25 +0000331class ArgParseNamespace(object):
332 pass
333
Johnny Chenaf149a02010-09-16 17:11:30 +0000334def parseOptionsAndInitTestdirs():
335 """Initialize the list of directories containing our unittest scripts.
336
337 '-h/--help as the first option prints out usage info and exit the program.
338 """
339
Johnny Chen4f93bf12010-12-10 00:51:23 +0000340 global dont_do_python_api_test
341 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000342 global just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +0000343 global dont_do_dsym_test
344 global dont_do_dwarf_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000345 global blacklist
346 global blacklistConfig
Enrico Granataac3a8e22012-09-21 19:10:53 +0000347 global categoriesList
348 global validCategories
349 global useCategories
Sean Callanan0acf4c62012-10-24 22:45:39 +0000350 global lldbFrameworkPath
351 global lldbExecutablePath
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000352 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000353 global archs
354 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000355 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000356 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000357 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000358 global bmExecutable
359 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000360 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000361 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000362 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000363 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000364 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000365 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000366 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000367 global skip_build_and_cleanup
368 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000369 global noHeaders
Daniel Malea361eb432013-02-15 21:31:37 +0000370 global parsable
Johnny Chen7c52ff12010-09-27 23:29:54 +0000371 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000372 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000373 global sdir_name
Enrico Granata814c8132013-04-11 23:48:00 +0000374 global svn_silent
Johnny Chenaf149a02010-09-16 17:11:30 +0000375 global verbose
376 global testdirs
377
Jim Ingham4f347cb2011-04-13 21:11:41 +0000378 do_help = False
379
Greg Clayton4793e942012-09-04 15:42:49 +0000380 parser = argparse.ArgumentParser(description='description', prefix_chars='+-', add_help=False)
381 group = None
Johnny Chenaf149a02010-09-16 17:11:30 +0000382
Greg Clayton4793e942012-09-04 15:42:49 +0000383 # Helper function for boolean options (group will point to the current group when executing X)
384 X = lambda optstr, helpstr, **kwargs: group.add_argument(optstr, help=helpstr, action='store_true', **kwargs)
385
386 group = parser.add_argument_group('Help')
387 group.add_argument('-h', '--help', dest='h', action='store_true', help="Print this help message and exit. Add '-v' for more detailed help.")
388
389 # C and Python toolchain options
390 group = parser.add_argument_group('Toolchain options')
391 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'''))
392 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.'''))
393 # FIXME? This won't work for different extra flags according to each arch.
394 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
395 suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
396 X('-D', 'Dump the Python sys.path variable')
397
398 # Test filtering options
399 group = parser.add_argument_group('Test filtering options')
400 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")
401 X('-a', "Don't do lldb Python API tests")
402 X('+a', "Just do lldb Python API tests. Do not specify along with '+a'", dest='plus_a')
403 X('+b', 'Just do benchmark tests', dest='plus_b')
404 group.add_argument('-b', metavar='blacklist', help='Read a blacklist file specified after this option')
Enrico Granata58b03a42012-12-14 00:07:09 +0000405 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 +0000406 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')
407 X('-l', "Don't skip long running tests")
408 group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite')
409 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 +0000410 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 +0000411
412 # Configuration options
413 group = parser.add_argument_group('Configuration options')
414 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 +0000415 group.add_argument('--framework', metavar='framework-path', help='The path to LLDB.framework')
416 group.add_argument('--executable', metavar='executable-path', help='The path to the lldb executable')
Greg Clayton4793e942012-09-04 15:42:49 +0000417 group.add_argument('-e', metavar='benchmark-exe', help='Specify the full path of an executable used for benchmark purposes (see also: -x)')
418 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")
419 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')
420 group.add_argument('-r', metavar='dir', help="Similar to '-R', except that the directory must not exist before running this test driver")
421 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')
422 group.add_argument('-x', metavar='breakpoint-spec', help='Specify the breakpoint specification for the benchmark executable')
423 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.")
424 group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times')
425
426 # Test-suite behaviour
427 group = parser.add_argument_group('Runtime behaviour options')
428 X('-d', 'Delay startup for 10 seconds (in order for the debugger to attach)')
429 X('-F', 'Fail fast. Stop the test suite on the first error/failure')
430 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")
431 X('-n', "Don't print the headers like build dir, lldb version, and svn info at all")
Jim Ingham75f260a2013-02-19 20:39:27 +0000432 X('-P', "Use the graphic progress bar.")
Daniel Malea361eb432013-02-15 21:31:37 +0000433 X('-q', "Don't print extra output from this script.")
Greg Clayton4793e942012-09-04 15:42:49 +0000434 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")
435 X('-t', 'Turn on tracing of lldb command and other detailed test executions')
Greg Claytonb85785c2013-02-08 21:52:32 +0000436 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 +0000437 X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
438 X('-w', 'Insert some wait time (currently 0.5 sec) between consecutive test cases')
Enrico Granata814c8132013-04-11 23:48:00 +0000439 X('-T', 'Obtain and dump svn information for this checkout of LLDB (off by default)')
Greg Clayton4793e942012-09-04 15:42:49 +0000440
441 # Remove the reference to our helper function
442 del X
443
444 group = parser.add_argument_group('Test directories')
445 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.')
Enrico Granata6fa3c502013-06-22 00:15:25 +0000446
447 args = ArgParseNamespace()
448
449 if ('LLDB_TEST_ARGUMENTS' in os.environ):
450 print "Arguments passed through environment: '%s'" % os.environ['LLDB_TEST_ARGUMENTS']
451 args = parser.parse_args([sys.argv[0]].__add__(os.environ['LLDB_TEST_ARGUMENTS'].split()),namespace=args)
452
453 args = parser.parse_args(namespace=args)
Greg Clayton4793e942012-09-04 15:42:49 +0000454
455 platform_system = platform.system()
456 platform_machine = platform.machine()
Enrico Granata2d329242012-10-23 22:52:49 +0000457
Greg Claytonb85785c2013-02-08 21:52:32 +0000458 if args.unset_env_varnames:
459 for env_var in args.unset_env_varnames:
460 if env_var in os.environ:
461 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
462 # is automatically translated into a corresponding call to unsetenv().
463 del os.environ[env_var]
464 #os.unsetenv(env_var)
465
Daniel Malea361eb432013-02-15 21:31:37 +0000466 # only print the args if being verbose (and parsable is off)
467 if args.v and not args.q:
Enrico Granata2d329242012-10-23 22:52:49 +0000468 print args
Greg Clayton4793e942012-09-04 15:42:49 +0000469
470 if args.h:
471 do_help = True
472
473 if args.archs:
474 archs = args.archs
475 else:
476 if platform_system == 'Darwin' and platform_machine == 'x86_64':
477 archs = ['x86_64', 'i386']
Johnny Chenaf149a02010-09-16 17:11:30 +0000478 else:
Greg Clayton4793e942012-09-04 15:42:49 +0000479 archs = [platform_machine]
480
Enrico Granataac3a8e22012-09-21 19:10:53 +0000481 if args.categoriesList:
Enrico Granata69d7c102013-05-07 00:36:28 +0000482 finalCategoriesList = []
Enrico Granataac3a8e22012-09-21 19:10:53 +0000483 for category in args.categoriesList:
Enrico Granata69d7c102013-05-07 00:36:28 +0000484 origCategory = category
Enrico Granataac3a8e22012-09-21 19:10:53 +0000485 if not(category in validCategories):
Enrico Granata69d7c102013-05-07 00:36:28 +0000486 category = unique_string_match(category,validCategories)
487 if not(category in validCategories) or category == None:
488 print "fatal error: category '" + origCategory + "' is not a valid category"
Enrico Granata2d329242012-10-23 22:52:49 +0000489 print "if you have added a new category, please edit dotest.py, adding your new category to validCategories"
490 print "else, please specify one or more of the following: " + str(validCategories.keys())
Enrico Granataac3a8e22012-09-21 19:10:53 +0000491 sys.exit(1)
Enrico Granata69d7c102013-05-07 00:36:28 +0000492 finalCategoriesList.append(category)
493 categoriesList = set(finalCategoriesList)
Enrico Granataac3a8e22012-09-21 19:10:53 +0000494 useCategories = True
495 else:
496 categoriesList = []
497
Greg Clayton4793e942012-09-04 15:42:49 +0000498 if args.compilers:
499 compilers = args.compilers
500 else:
501 compilers = ['clang']
502
503 if args.D:
504 dumpSysPath = True
505
506 if args.E:
507 cflags_extras = args.E
508 os.environ['CFLAGS_EXTRAS'] = cflags_extras
509
510 # argparse makes sure we have correct options
511 if args.N == 'dwarf':
512 dont_do_dwarf_test = True
513 elif args.N == 'dsym':
514 dont_do_dsym_test = True
515
516 if args.a:
517 dont_do_python_api_test = True
518
519 if args.plus_a:
520 if dont_do_python_api_test:
521 print "Warning: -a and +a can't both be specified! Using only -a"
522 else:
523 just_do_python_api_test = True
524
525 if args.plus_b:
526 just_do_benchmarks_test = True
527
528 if args.b:
529 if args.b.startswith('-'):
530 usage(parser)
531 blacklistFile = args.b
532 if not os.path.isfile(blacklistFile):
533 print 'Blacklist file:', blacklistFile, 'does not exist!'
534 usage(parser)
535 # Now read the blacklist contents and assign it to blacklist.
536 execfile(blacklistFile, globals(), blacklistConfig)
537 blacklist = blacklistConfig.get('blacklist')
538
539 if args.c:
540 if args.c.startswith('-'):
541 usage(parser)
542 configFile = args.c
543 if not os.path.isfile(configFile):
544 print 'Config file:', configFile, 'does not exist!'
545 usage(parser)
546
547 if args.d:
548 delay = True
549
550 if args.e:
551 if args.e.startswith('-'):
552 usage(parser)
553 bmExecutable = args.e
554 if not is_exe(bmExecutable):
555 usage(parser)
556
557 if args.F:
558 failfast = True
559
560 if args.f:
Enrico Granata58b03a42012-12-14 00:07:09 +0000561 if any([x.startswith('-') for x in args.f]):
Greg Clayton4793e942012-09-04 15:42:49 +0000562 usage(parser)
Enrico Granata58b03a42012-12-14 00:07:09 +0000563 filters.extend(args.f)
Greg Clayton4793e942012-09-04 15:42:49 +0000564
565 if args.g:
566 fs4all = False
567
568 if args.i:
569 ignore = True
570
571 if args.k:
572 runHooks.extend(args.k)
573
574 if args.l:
575 skip_long_running_test = False
576
Sean Callanan0acf4c62012-10-24 22:45:39 +0000577 if args.framework:
578 lldbFrameworkPath = args.framework
579
580 if args.executable:
581 lldbExecutablePath = args.executable
582
Greg Clayton4793e942012-09-04 15:42:49 +0000583 if args.n:
584 noHeaders = True
585
586 if args.p:
587 if args.p.startswith('-'):
588 usage(parser)
589 regexp = args.p
590
Daniel Malea361eb432013-02-15 21:31:37 +0000591 if args.q:
592 noHeaders = True
593 parsable = True
594
Jim Ingham75f260a2013-02-19 20:39:27 +0000595 if args.P:
596 progress_bar = True
597 verbose = 0
598
Greg Clayton4793e942012-09-04 15:42:49 +0000599 if args.R:
600 if args.R.startswith('-'):
601 usage(parser)
602 rdir = os.path.abspath(args.R)
603 if os.path.exists(rdir):
604 import shutil
605 print 'Removing tree:', rdir
606 shutil.rmtree(rdir)
607
608 if args.r:
609 if args.r.startswith('-'):
610 usage(parser)
611 rdir = os.path.abspath(args.r)
612 if os.path.exists(rdir):
613 print 'Relocated directory:', rdir, 'must not exist!'
614 usage(parser)
615
616 if args.S:
617 skip_build_and_cleanup = True
618
619 if args.s:
620 if args.s.startswith('-'):
621 usage(parser)
622 sdir_name = args.s
623
624 if args.t:
625 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
626
Enrico Granata814c8132013-04-11 23:48:00 +0000627 if args.T:
628 svn_silent = False
629
Greg Clayton4793e942012-09-04 15:42:49 +0000630 if args.v:
631 verbose = 2
632
633 if args.w:
634 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
635
636 if args.X:
637 if args.X.startswith('-'):
638 usage(parser)
639 excluded.add(args.X)
640
641 if args.x:
642 if args.x.startswith('-'):
643 usage(parser)
644 bmBreakpointSpec = args.x
645
646 # argparse makes sure we have a number
647 if args.y:
648 bmIterationCount = args.y
649
650 # argparse makes sure we have a number
651 if args.sharp:
652 count = args.sharp
Johnny Chenaf149a02010-09-16 17:11:30 +0000653
Jim Ingham4f347cb2011-04-13 21:11:41 +0000654 if do_help == True:
Greg Clayton4793e942012-09-04 15:42:49 +0000655 usage(parser)
Jim Ingham4f347cb2011-04-13 21:11:41 +0000656
Johnny Chencc659ad2010-12-10 19:02:23 +0000657 # Do not specify both '-a' and '+a' at the same time.
658 if dont_do_python_api_test and just_do_python_api_test:
Greg Clayton4793e942012-09-04 15:42:49 +0000659 usage(parser)
Johnny Chencc659ad2010-12-10 19:02:23 +0000660
Johnny Chenaf149a02010-09-16 17:11:30 +0000661 # Gather all the dirs passed on the command line.
Greg Clayton4793e942012-09-04 15:42:49 +0000662 if len(args.args) > 0:
663 testdirs = map(os.path.abspath, args.args)
Johnny Chenaf149a02010-09-16 17:11:30 +0000664
Johnny Chen548aefd2010-10-11 22:25:46 +0000665 # If '-r dir' is specified, the tests should be run under the relocated
666 # directory. Let's copy the testdirs over.
667 if rdir:
668 from shutil import copytree, ignore_patterns
669
670 tmpdirs = []
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000671 orig_testdirs = testdirs[:]
Johnny Chen548aefd2010-10-11 22:25:46 +0000672 for srcdir in testdirs:
Johnny Chen1abe4c02012-03-20 00:33:51 +0000673 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
674 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
675 # Utilize the relative path to the 'test' directory to make our destination dir path.
Greg Clayton4793e942012-09-04 15:42:49 +0000676 if ("test" + os.sep) in srcdir:
677 to_split_on = "test" + os.sep
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000678 else:
679 to_split_on = "test"
680 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
681 dstdir = dstdir.rstrip(os.sep)
Johnny Chen548aefd2010-10-11 22:25:46 +0000682 # Don't copy the *.pyc and .svn stuffs.
683 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
684 tmpdirs.append(dstdir)
685
686 # This will be our modified testdirs.
687 testdirs = tmpdirs
688
689 # With '-r dir' specified, there's no cleanup of intermediate test files.
690 os.environ["LLDB_DO_CLEANUP"] = 'NO'
691
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000692 # If the original testdirs is ['test'], the make directory has already been copied
Johnny Chen548aefd2010-10-11 22:25:46 +0000693 # recursively and is contained within the rdir/test dir. For anything
694 # else, we would need to copy over the make directory and its contents,
695 # so that, os.listdir(rdir) looks like, for example:
696 #
697 # array_types conditional_break make
698 #
699 # where the make directory contains the Makefile.rules file.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000700 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000701 scriptdir = os.path.dirname(__file__)
Johnny Chen548aefd2010-10-11 22:25:46 +0000702 # Don't copy the .svn stuffs.
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000703 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
Johnny Chen548aefd2010-10-11 22:25:46 +0000704 ignore=ignore_patterns('.svn'))
705
706 #print "testdirs:", testdirs
707
Johnny Chenb40056b2010-09-21 00:09:27 +0000708 # Source the configFile if specified.
709 # The side effect, if any, will be felt from this point on. An example
710 # config file may be these simple two lines:
711 #
712 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
713 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
714 #
715 # which will reassign the two file objects to sys.stderr and sys.stdout,
716 # respectively.
717 #
Johnny Chen8c130642012-08-22 17:53:02 +0000718 # See also lldb-trunk/examples/test/usage-config.
Johnny Chenac97a6b2012-04-16 18:55:15 +0000719 global config, pre_flight, post_flight
Johnny Chenb40056b2010-09-21 00:09:27 +0000720 if configFile:
721 # Pass config (a dictionary) as the locals namespace for side-effect.
722 execfile(configFile, globals(), config)
Johnny Chenac97a6b2012-04-16 18:55:15 +0000723 print "config:", config
724 if "pre_flight" in config:
725 pre_flight = config["pre_flight"]
726 if not callable(pre_flight):
727 print "fatal error: pre_flight is not callable, exiting."
728 sys.exit(1)
729 if "post_flight" in config:
730 post_flight = config["post_flight"]
731 if not callable(post_flight):
732 print "fatal error: post_flight is not callable, exiting."
733 sys.exit(1)
Johnny Chenb40056b2010-09-21 00:09:27 +0000734 #print "sys.stderr:", sys.stderr
735 #print "sys.stdout:", sys.stdout
736
Johnny Chenaf149a02010-09-16 17:11:30 +0000737
Johnny Chen9707bb62010-06-25 21:14:08 +0000738def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000739 """
740 Add LLDB.framework/Resources/Python to the search paths for modules.
741 As a side effect, we also discover the 'lldb' executable and export it here.
742 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000743
Johnny Chen548aefd2010-10-11 22:25:46 +0000744 global rdir
745 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000746 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000747 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000748 global svn_info
Enrico Granata814c8132013-04-11 23:48:00 +0000749 global svn_silent
Sean Callanan0acf4c62012-10-24 22:45:39 +0000750 global lldbFrameworkPath
751 global lldbExecutablePath
Johnny Chen548aefd2010-10-11 22:25:46 +0000752
Johnny Chen9707bb62010-06-25 21:14:08 +0000753 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000754 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 +0000755 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
756 else:
757 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000758 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000759 print "This script expects to reside in lldb's test directory."
760 sys.exit(-1)
761
Johnny Chen548aefd2010-10-11 22:25:46 +0000762 if rdir:
763 # Set up the LLDB_TEST environment variable appropriately, so that the
764 # individual tests can be located relatively.
765 #
766 # See also lldbtest.TestBase.setUpClass(cls).
767 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
768 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
769 else:
770 os.environ["LLDB_TEST"] = rdir
771 else:
772 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000773
774 # Set up the LLDB_SRC environment variable, so that the tests can locate
775 # the LLDB source code.
776 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
777
Johnny Chen9de4ede2010-08-31 17:42:54 +0000778 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000779 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000780
Johnny Chen8a3c0432011-03-11 20:13:06 +0000781 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000782 sys.path.append(scriptPath)
783 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000784 sys.path.append(pexpectPath)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000785
Johnny Chen26901c82011-03-11 19:47:23 +0000786 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000787 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000788
Johnny Chen26901c82011-03-11 19:47:23 +0000789 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000790 xcode3_build_dir = ['build']
791 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
792 dbg = ['Debug']
Sean Callanand9d94632012-09-26 21:16:15 +0000793 dbc = ['DebugClang']
Johnny Chen6a564a42011-02-15 18:50:19 +0000794 rel = ['Release']
795 bai = ['BuildAndIntegration']
796 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000797
798 # Some of the tests can invoke the 'lldb' command directly.
799 # We'll try to locate the appropriate executable right here.
800
Sean Callanan0acf4c62012-10-24 22:45:39 +0000801 lldbExec = None
802 if lldbExecutablePath:
803 if is_exe(lldbExecutablePath):
804 lldbExec = lldbExecutablePath
Sean Callanan502000d2012-11-01 21:23:21 +0000805 lldbHere = lldbExec
Sean Callanan0acf4c62012-10-24 22:45:39 +0000806 else:
807 print lldbExecutablePath + " is not an executable"
808 sys.exit(-1)
Johnny Chen6033bed2011-08-26 00:00:01 +0000809 else:
Sean Callanan0acf4c62012-10-24 22:45:39 +0000810 # First, you can define an environment variable LLDB_EXEC specifying the
811 # full pathname of the lldb executable.
812 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
813 lldbExec = os.environ["LLDB_EXEC"]
814 else:
815 lldbExec = None
816
817 executable = ['lldb']
818 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
819 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
820 dbcExec = os.path.join(base, *(xcode3_build_dir + dbc + executable))
821 dbcExec2 = os.path.join(base, *(xcode4_build_dir + dbc + executable))
822 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
823 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
824 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
825 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
826
827 # The 'lldb' executable built here in the source tree.
828 lldbHere = None
829 if is_exe(dbgExec):
830 lldbHere = dbgExec
831 elif is_exe(dbgExec2):
832 lldbHere = dbgExec2
833 elif is_exe(dbcExec):
834 lldbHere = dbcExec
835 elif is_exe(dbcExec2):
836 lldbHere = dbcExec2
837 elif is_exe(relExec):
838 lldbHere = relExec
839 elif is_exe(relExec2):
840 lldbHere = relExec2
841 elif is_exe(baiExec):
842 lldbHere = baiExec
843 elif is_exe(baiExec2):
844 lldbHere = baiExec2
845 elif lldbExec:
846 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000847
Sean Callanan0acf4c62012-10-24 22:45:39 +0000848 # One last chance to locate the 'lldb' executable.
849 if not lldbExec:
850 lldbExec = which('lldb')
851 if lldbHere and not lldbExec:
852 lldbExec = lldbHere
Daniel Malea2777b012013-02-06 16:55:07 +0000853 if lldbExec and not lldbHere:
854 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000855
856 if lldbHere:
857 os.environ["LLDB_HERE"] = lldbHere
Matt Kopeca964b092013-02-20 20:54:10 +0000858 os.environ["LLDB_LIB_DIR"] = os.path.split(lldbHere)[0]
Sean Callanan502000d2012-11-01 21:23:21 +0000859 if not noHeaders:
Matt Kopeca964b092013-02-20 20:54:10 +0000860 print "LLDB library dir:", os.environ["LLDB_LIB_DIR"]
Sean Callanan502000d2012-11-01 21:23:21 +0000861 os.system('%s -v' % lldbHere)
Johnny Chen26901c82011-03-11 19:47:23 +0000862
863 if not lldbExec:
864 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
865 else:
866 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000867 #print "The 'lldb' from PATH env variable", lldbExec
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000868
Daniel Malea2b606ab2013-03-13 20:50:05 +0000869 # Skip printing svn/git information when running in parsable (lit-test compatibility) mode
Enrico Granata814c8132013-04-11 23:48:00 +0000870 if not svn_silent and not parsable:
Daniel Malea2b606ab2013-03-13 20:50:05 +0000871 if os.path.isdir(os.path.join(base, '.svn')) and which("svn") is not None:
872 pipe = subprocess.Popen([which("svn"), "info", base], stdout = subprocess.PIPE)
873 svn_info = pipe.stdout.read()
874 elif os.path.isdir(os.path.join(base, '.git')) and which("git") is not None:
875 pipe = subprocess.Popen([which("git"), "svn", "info", base], stdout = subprocess.PIPE)
876 svn_info = pipe.stdout.read()
877 if not noHeaders:
878 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000879
880 global ignore
881
Johnny Chen9707bb62010-06-25 21:14:08 +0000882 lldbPath = None
Sean Callanan0acf4c62012-10-24 22:45:39 +0000883 if lldbFrameworkPath:
884 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python')
885 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
886 lldbPath = candidatePath
887 if not lldbPath:
888 print 'Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath
889 sys.exit(-1)
890 else:
891 # The '-i' option is used to skip looking for lldb.py in the build tree.
892 if ignore:
893 return
Jim Inghamaa93c932012-12-21 22:22:26 +0000894
895 # If our lldb supports the -P option, use it to find the python path:
896 init_in_python_dir = 'lldb/__init__.py'
897 import pexpect
898 lldb_dash_p_result = None
899
900 if lldbHere:
901 lldb_dash_p_result = pexpect.run("%s -P"%(lldbHere))
902 elif lldbExec:
903 lldb_dash_p_result = pexpect.run("%s -P"%(lldbExec))
904
905 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")):
906 lines = lldb_dash_p_result.splitlines()
907 if len(lines) == 1 and os.path.isfile(os.path.join(lines[0], init_in_python_dir)):
908 lldbPath = lines[0]
Daniel Malea21e32a62013-01-04 23:35:13 +0000909 if "linux" in sys.platform:
Matt Kopeca964b092013-02-20 20:54:10 +0000910 os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPath, '..', '..')
Jim Inghamaa93c932012-12-21 22:22:26 +0000911
912 if not lldbPath:
913 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
914 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
915 dbcPath = os.path.join(base, *(xcode3_build_dir + dbc + python_resource_dir))
916 dbcPath2 = os.path.join(base, *(xcode4_build_dir + dbc + python_resource_dir))
917 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
918 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
919 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
920 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Sean Callanan0acf4c62012-10-24 22:45:39 +0000921
Jim Inghamaa93c932012-12-21 22:22:26 +0000922 if os.path.isfile(os.path.join(dbgPath, init_in_python_dir)):
923 lldbPath = dbgPath
924 elif os.path.isfile(os.path.join(dbgPath2, init_in_python_dir)):
925 lldbPath = dbgPath2
926 elif os.path.isfile(os.path.join(dbcPath, init_in_python_dir)):
927 lldbPath = dbcPath
928 elif os.path.isfile(os.path.join(dbcPath2, init_in_python_dir)):
929 lldbPath = dbcPath2
930 elif os.path.isfile(os.path.join(relPath, init_in_python_dir)):
931 lldbPath = relPath
932 elif os.path.isfile(os.path.join(relPath2, init_in_python_dir)):
933 lldbPath = relPath2
934 elif os.path.isfile(os.path.join(baiPath, init_in_python_dir)):
935 lldbPath = baiPath
936 elif os.path.isfile(os.path.join(baiPath2, init_in_python_dir)):
937 lldbPath = baiPath2
938
Sean Callanan0acf4c62012-10-24 22:45:39 +0000939 if not lldbPath:
940 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
941 print relPath + ', or ' + baiPath
942 sys.exit(-1)
Johnny Chen9707bb62010-06-25 21:14:08 +0000943
Jim Inghamaa93c932012-12-21 22:22:26 +0000944 # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
945 # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
946 (before, frameWithVersion, after) = lldbPath.rpartition("LLDB.framework/Versions/A")
947 if frameWithVersion != "" :
948 lldbPath = before + "LLDB.framework" + after
949
Enrico Granata0ad92972013-04-11 23:40:59 +0000950 lldbPath = os.path.abspath(lldbPath)
951
Enrico Granata01458ca2012-10-23 00:09:02 +0000952 # If tests need to find LLDB_FRAMEWORK, now they can do it
953 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPath))
954
Johnny Chenaf149a02010-09-16 17:11:30 +0000955 # This is to locate the lldb.py module. Insert it right after sys.path[0].
956 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000957 if dumpSysPath:
958 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000959
Johnny Chen9707bb62010-06-25 21:14:08 +0000960
Johnny Chencd0279d2010-09-20 18:07:50 +0000961def doDelay(delta):
962 """Delaying startup for delta-seconds to facilitate debugger attachment."""
963 def alarm_handler(*args):
964 raise Exception("timeout")
965
966 signal.signal(signal.SIGALRM, alarm_handler)
967 signal.alarm(delta)
968 sys.stdout.write("pid=%d\n" % os.getpid())
969 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
970 delta)
971 sys.stdout.flush()
972 try:
973 text = sys.stdin.readline()
974 except:
975 text = ""
976 signal.alarm(0)
977 sys.stdout.write("proceeding...\n")
978 pass
979
980
Johnny Chen9707bb62010-06-25 21:14:08 +0000981def visit(prefix, dir, names):
982 """Visitor function for os.path.walk(path, visit, arg)."""
983
984 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000985 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000986 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000987 global fs4all
Johnny Chene9eae812012-01-18 05:15:00 +0000988 global excluded
989
990 if set(dir.split(os.sep)).intersection(excluded):
991 #print "Detected an excluded dir component: %s" % dir
992 return
Johnny Chen9707bb62010-06-25 21:14:08 +0000993
994 for name in names:
995 if os.path.isdir(os.path.join(dir, name)):
996 continue
997
998 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000999 # Try to match the regexp pattern, if specified.
1000 if regexp:
1001 import re
1002 if re.search(regexp, name):
1003 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
1004 pass
1005 else:
1006 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
1007 continue
1008
Johnny Chen953864a2010-10-12 21:35:54 +00001009 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +00001010
1011 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +00001012 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +00001013 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +00001014 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +00001015
1016 # Thoroughly check the filterspec against the base module and admit
1017 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +00001018 filterspec = None
1019 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +00001020 # Optimistically set the flag to True.
1021 filtered = True
1022 module = __import__(base)
1023 parts = filterspec.split('.')
1024 obj = module
1025 for part in parts:
1026 try:
1027 parent, obj = obj, getattr(obj, part)
1028 except AttributeError:
1029 # The filterspec has failed.
1030 filtered = False
1031 break
Johnny Chenc5fa0052011-07-29 22:54:56 +00001032
Johnny Chendb4be602011-08-12 23:55:07 +00001033 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +00001034 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +00001035 #print "adding filter spec %s to module %s" % (filterspec, module)
1036 suite.addTests(
1037 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
1038 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +00001039
1040 # Forgo this module if the (base, filterspec) combo is invalid
1041 # and no '-g' option is specified
1042 if filters and fs4all and not filtered:
1043 continue
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001044
Johnny Chendb4be602011-08-12 23:55:07 +00001045 # Add either the filtered test case(s) (which is done before) or the entire test class.
1046 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +00001047 # A simple case of just the module name. Also the failover case
1048 # from the filterspec branch when the (base, filterspec) combo
1049 # doesn't make sense.
1050 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +00001051
1052
Johnny Chencd0279d2010-09-20 18:07:50 +00001053def lldbLoggings():
1054 """Check and do lldb loggings if necessary."""
1055
1056 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
1057 # defined. Use ${LLDB_LOG} to specify the log file.
1058 ci = lldb.DBG.GetCommandInterpreter()
1059 res = lldb.SBCommandReturnObject()
1060 if ("LLDB_LOG" in os.environ):
1061 if ("LLDB_LOG_OPTION" in os.environ):
1062 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
1063 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +00001064 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +00001065 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +00001066 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +00001067 res)
1068 if not res.Succeeded():
1069 raise Exception('log enable failed (check LLDB_LOG env variable.')
1070 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
1071 # Use ${GDB_REMOTE_LOG} to specify the log file.
1072 if ("GDB_REMOTE_LOG" in os.environ):
1073 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
1074 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
1075 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +00001076 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +00001077 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +00001078 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +00001079 + gdb_remote_log_option,
1080 res)
1081 if not res.Succeeded():
1082 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
1083
Johnny Chen067022b2011-01-19 19:31:46 +00001084def getMyCommandLine():
Daniel Malea782e4742013-05-30 21:48:58 +00001085 ps = subprocess.Popen([which('ps'), '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
Johnny Chen067022b2011-01-19 19:31:46 +00001086 lines = ps.split('\n')
1087 cmd_line = lines[1]
1088 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +00001089
Johnny Chend96b5682010-11-05 17:30:53 +00001090# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001091# #
1092# Execution of the test driver starts here #
1093# #
Johnny Chend96b5682010-11-05 17:30:53 +00001094# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001095
Johnny Chen2891bb02011-09-16 01:04:26 +00001096def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +00001097 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1098 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1099 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +00001100 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +00001101 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +00001102 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +00001103 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
1104 print "Exiting..."
1105 sys.exit(0)
1106
1107# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1108# does not exist before proceeding to running the test suite.
1109if sys.platform.startswith("darwin"):
1110 checkDsymForUUIDIsNotOn()
1111
Johnny Chen9707bb62010-06-25 21:14:08 +00001112#
Johnny Chenaf149a02010-09-16 17:11:30 +00001113# Start the actions by first parsing the options while setting up the test
1114# directories, followed by setting up the search paths for lldb utilities;
1115# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +00001116#
Johnny Chenaf149a02010-09-16 17:11:30 +00001117parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +00001118setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +00001119
1120#
1121# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
1122#
1123if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +00001124 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +00001125
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001126#
Johnny Chen41998192010-10-01 22:59:49 +00001127# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +00001128if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +00001129 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1130
1131#
Johnny Chen79723352010-10-12 15:53:22 +00001132# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001133#
Johnny Chen9707bb62010-06-25 21:14:08 +00001134for testdir in testdirs:
1135 os.path.walk(testdir, visit, 'Test')
1136
Johnny Chenb40056b2010-09-21 00:09:27 +00001137#
Johnny Chen9707bb62010-06-25 21:14:08 +00001138# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +00001139#
Johnny Chencd0279d2010-09-20 18:07:50 +00001140
Johnny Chen1bfbd412010-06-29 19:44:16 +00001141# For the time being, let's bracket the test runner within the
1142# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001143import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +00001144# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
1145# there's no need to call it a second time.
1146#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001147atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +00001148
Johnny Chen909e5a62010-07-01 22:52:57 +00001149# Create a singleton SBDebugger in the lldb namespace.
1150lldb.DBG = lldb.SBDebugger.Create()
1151
Johnny Chen4f93bf12010-12-10 00:51:23 +00001152# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +00001153lldb.blacklist = blacklist
1154
Johnny Chenac97a6b2012-04-16 18:55:15 +00001155# The pre_flight and post_flight come from reading a config file.
1156lldb.pre_flight = pre_flight
1157lldb.post_flight = post_flight
1158def getsource_if_available(obj):
1159 """
1160 Return the text of the source code for an object if available. Otherwise,
1161 a print representation is returned.
1162 """
1163 import inspect
1164 try:
1165 return inspect.getsource(obj)
1166 except:
1167 return repr(obj)
1168
Daniel Malea361eb432013-02-15 21:31:37 +00001169if not noHeaders:
1170 print "lldb.pre_flight:", getsource_if_available(lldb.pre_flight)
1171 print "lldb.post_flight:", getsource_if_available(lldb.post_flight)
Johnny Chenac97a6b2012-04-16 18:55:15 +00001172
Johnny Chena3ed7d82012-04-06 00:56:05 +00001173# Put all these test decorators in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +00001174lldb.dont_do_python_api_test = dont_do_python_api_test
1175lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +00001176lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +00001177lldb.dont_do_dsym_test = dont_do_dsym_test
1178lldb.dont_do_dwarf_test = dont_do_dwarf_test
Johnny Chen4f93bf12010-12-10 00:51:23 +00001179
Johnny Chen028d8eb2011-11-17 19:57:27 +00001180# Do we need to skip build and cleanup?
1181lldb.skip_build_and_cleanup = skip_build_and_cleanup
1182
Johnny Chen5f2ed172011-10-20 18:43:28 +00001183# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +00001184lldb.bmExecutable = bmExecutable
1185lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +00001186lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +00001187
Johnny Chen38f823c2011-10-11 01:30:27 +00001188# And don't forget the runHooks!
1189lldb.runHooks = runHooks
1190
Johnny Chencd0279d2010-09-20 18:07:50 +00001191# Turn on lldb loggings if necessary.
1192lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +00001193
Johnny Chen7987ac92010-08-09 20:40:52 +00001194# Install the control-c handler.
1195unittest2.signals.installHandler()
1196
Johnny Chen125fc2b2010-10-21 16:55:35 +00001197# If sdir_name is not specified through the '-s sdir_name' option, get a
1198# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1199# be used when/if we want to dump the session info of individual test cases
1200# later on.
Johnny Chence681462010-10-19 00:25:01 +00001201#
1202# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chena73ad662012-08-16 19:15:21 +00001203import datetime
1204# The windows platforms don't like ':' in the pathname.
1205timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +00001206if not sdir_name:
Johnny Chena73ad662012-08-16 19:15:21 +00001207 sdir_name = timestamp_started
Peter Collingbourne132476f2011-06-20 23:55:53 +00001208os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +00001209
Johnny Chenfe5f1ed2011-10-21 18:33:27 +00001210if not noHeaders:
1211 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1212 " will go into directory '%s'\n" % sdir_name)
1213 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +00001214
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001215if not os.path.isdir(sdir_name):
1216 os.mkdir(sdir_name)
Enrico Granata571358f2013-06-19 21:48:09 +00001217where_to_save_session = os.getcwd()
Johnny Chena73ad662012-08-16 19:15:21 +00001218fname = os.path.join(sdir_name, "TestStarted")
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001219with open(fname, "w") as f:
Johnny Chena73ad662012-08-16 19:15:21 +00001220 print >> f, "Test started at: %s\n" % timestamp_started
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001221 print >> f, svn_info
1222 print >> f, "Command invoked: %s\n" % getMyCommandLine()
1223
Johnny Chenb40056b2010-09-21 00:09:27 +00001224#
1225# Invoke the default TextTestRunner to run the test suite, possibly iterating
1226# over different configurations.
1227#
1228
Johnny Chenb40056b2010-09-21 00:09:27 +00001229iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +00001230iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001231
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001232if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001233 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001234
1235if isinstance(archs, list) and len(archs) >= 1:
1236 iterArchs = True
1237
1238if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001239 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001240
Johnny Chen92693b52012-03-09 02:11:37 +00001241#
1242# Add some intervention here to sanity check that the compilers requested are sane.
1243# If found not to be an executable program, the invalid one is dropped from the list.
1244for i in range(len(compilers)):
1245 c = compilers[i]
1246 if which(c):
1247 continue
1248 else:
1249 if sys.platform.startswith("darwin"):
1250 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1251 cmd_output = pipe.stdout.read()
1252 if cmd_output:
1253 if "not found" in cmd_output:
1254 print "dropping %s from the compilers used" % c
1255 compilers.remove(i)
1256 else:
1257 compilers[i] = cmd_output.split('\n')[0]
1258 print "'xcrun -find %s' returning %s" % (c, compilers[i])
1259
Daniel Malea361eb432013-02-15 21:31:37 +00001260if not parsable:
1261 print "compilers=%s" % str(compilers)
Johnny Chen92693b52012-03-09 02:11:37 +00001262
1263if not compilers or len(compilers) == 0:
1264 print "No eligible compiler found, exiting."
1265 sys.exit(1)
1266
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001267if isinstance(compilers, list) and len(compilers) >= 1:
1268 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001269
Johnny Chen953864a2010-10-12 21:35:54 +00001270# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1271# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001272if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001273 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001274# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1275if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001276 old_stderr = sys.stderr
1277 old_stdout = sys.stdout
1278 new_stderr = None
1279 new_stdout = None
1280
Johnny Chend96b5682010-11-05 17:30:53 +00001281# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001282for ia in range(len(archs) if iterArchs else 1):
1283 archConfig = ""
1284 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001285 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001286 archConfig = "arch=%s" % archs[ia]
1287 for ic in range(len(compilers) if iterCompilers else 1):
1288 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001289 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001290 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1291 else:
1292 configString = archConfig
1293
Johnny Chenb40056b2010-09-21 00:09:27 +00001294 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001295 # Translate ' ' to '-' for pathname component.
1296 from string import maketrans
1297 tbl = maketrans(' ', '-')
1298 configPostfix = configString.translate(tbl)
1299
1300 # Check whether we need to split stderr/stdout into configuration
1301 # specific files.
1302 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1303 if new_stderr:
1304 new_stderr.close()
1305 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1306 sys.stderr = new_stderr
1307 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1308 if new_stdout:
1309 new_stdout.close()
1310 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1311 sys.stdout = new_stdout
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001312
Johnny Chen953864a2010-10-12 21:35:54 +00001313 # If we specified a relocated directory to run the test suite, do
1314 # the extra housekeeping to copy the testdirs to a configStringified
1315 # directory and to update sys.path before invoking the test runner.
1316 # The purpose is to separate the configuration-specific directories
1317 # from each other.
1318 if rdir:
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001319 from shutil import copytree, rmtree, ignore_patterns
Johnny Chen953864a2010-10-12 21:35:54 +00001320
Johnny Chen953864a2010-10-12 21:35:54 +00001321 newrdir = "%s.%s" % (rdir, configPostfix)
1322
1323 # Copy the tree to a new directory with postfix name configPostfix.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001324 if os.path.exists(newrdir):
1325 rmtree(newrdir)
Johnny Chen953864a2010-10-12 21:35:54 +00001326 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1327
Filipe Cabecinhas0e1d06d2012-08-08 15:23:24 +00001328 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001329 # level test directory.
1330 #
1331 # See also lldbtest.TestBase.setUpClass(cls).
1332 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1333 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1334 else:
1335 os.environ["LLDB_TEST"] = newrdir
1336
1337 # And update the Python search paths for modules.
1338 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1339
1340 # Output the configuration.
Daniel Malea361eb432013-02-15 21:31:37 +00001341 if not parsable:
1342 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001343
1344 #print "sys.stderr name is", sys.stderr.name
1345 #print "sys.stdout name is", sys.stdout.name
1346
1347 # First, write out the number of collected test cases.
Daniel Malea361eb432013-02-15 21:31:37 +00001348 if not parsable:
1349 sys.stderr.write(separator + "\n")
1350 sys.stderr.write("Collected %d test%s\n\n"
1351 % (suite.countTestCases(),
1352 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001353
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001354 class LLDBTestResult(unittest2.TextTestResult):
1355 """
Johnny Chen26be4532010-11-09 23:56:14 +00001356 Enforce a singleton pattern to allow introspection of test progress.
1357
1358 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1359 to enable each test instance to track its failure/error status. It
1360 is used in the LLDB test framework to emit detailed trace messages
1361 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001362 """
1363 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001364 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001365
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001366 @staticmethod
1367 def getTerminalSize():
1368 import os
1369 env = os.environ
1370 def ioctl_GWINSZ(fd):
1371 try:
1372 import fcntl, termios, struct, os
1373 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
1374 '1234'))
1375 except:
1376 return
1377 return cr
1378 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
1379 if not cr:
1380 try:
1381 fd = os.open(os.ctermid(), os.O_RDONLY)
1382 cr = ioctl_GWINSZ(fd)
1383 os.close(fd)
1384 except:
1385 pass
1386 if not cr:
1387 cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
1388 return int(cr[1]), int(cr[0])
1389
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001390 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001391 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001392 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001393 super(LLDBTestResult, self).__init__(*args)
1394 LLDBTestResult.__singleton__ = self
1395 # Now put this singleton into the lldb module namespace.
1396 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001397 # Computes the format string for displaying the counter.
1398 global suite
1399 counterWidth = len(str(suite.countTestCases()))
1400 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001401 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001402 # This counts from 1 .. suite.countTestCases().
1403 self.counter = 0
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001404 (width, height) = LLDBTestResult.getTerminalSize()
Enrico Granata77215892013-02-15 00:32:05 +00001405 self.progressbar = None
Jim Ingham75f260a2013-02-19 20:39:27 +00001406 global progress_bar
Daniel Malea361eb432013-02-15 21:31:37 +00001407 if width > 10 and not parsable and progress_bar:
Enrico Granata77215892013-02-15 00:32:05 +00001408 try:
1409 self.progressbar = progress.ProgressWithEvents(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10)
1410 except:
1411 self.progressbar = None
Johnny Chen810042e2011-01-05 20:24:11 +00001412
Daniel Malea361eb432013-02-15 21:31:37 +00001413 def _config_string(self, test):
1414 compiler = getattr(test, "getCompiler", None)
1415 arch = getattr(test, "getArchitecture", None)
1416 return "%s-%s" % (compiler() if compiler else "", arch() if arch else "")
1417
Johnny Chenbe452272012-04-19 21:33:55 +00001418 def _exc_info_to_string(self, err, test):
1419 """Overrides superclass TestResult's method in order to append
1420 our test config info string to the exception info string."""
1421 modified_exc_string = '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1422 test.getArchitecture(),
1423 test.getCompiler())
1424 return modified_exc_string
1425
Johnny Chenc87fd492011-01-05 22:50:11 +00001426 def getDescription(self, test):
1427 doc_first_line = test.shortDescription()
1428 if self.descriptions and doc_first_line:
1429 return '\n'.join((str(test), self.indentation + doc_first_line))
1430 else:
1431 return str(test)
1432
Enrico Granataac3a8e22012-09-21 19:10:53 +00001433 def getCategoriesForTest(self,test):
Enrico Granata56e2c562013-02-27 02:37:12 +00001434 if hasattr(test,"_testMethodName"):
1435 test_method = getattr(test,"_testMethodName")
1436 test_method = getattr(test,test_method)
1437 else:
1438 test_method = None
1439 if test_method != None and hasattr(test_method,"getCategories"):
1440 test_categories = test_method.getCategories(test)
1441 elif hasattr(test,"getCategories"):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001442 test_categories = test.getCategories()
1443 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1444 test_categories = test.__self__.getCategories()
1445 else:
1446 test_categories = []
1447 if test_categories == None:
1448 test_categories = []
1449 return test_categories
1450
1451 def shouldSkipBecauseOfCategories(self,test):
1452 global useCategories
1453 import inspect
1454 if useCategories:
1455 global categoriesList
1456 test_categories = self.getCategoriesForTest(test)
1457 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
1458 return True
1459 return False
1460
1461 def hardMarkAsSkipped(self,test):
1462 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1463 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
Enrico Granata571358f2013-06-19 21:48:09 +00001464 test.__class__.__unittest_skip__ = True
1465 test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
Enrico Granataac3a8e22012-09-21 19:10:53 +00001466
Johnny Chen810042e2011-01-05 20:24:11 +00001467 def startTest(self, test):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001468 if self.shouldSkipBecauseOfCategories(test):
1469 self.hardMarkAsSkipped(test)
Johnny Chen810042e2011-01-05 20:24:11 +00001470 self.counter += 1
1471 if self.showAll:
1472 self.stream.write(self.fmt % self.counter)
1473 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001474
Daniel Malea361eb432013-02-15 21:31:37 +00001475 def addSuccess(self, test):
1476 global parsable
1477 super(LLDBTestResult, self).addSuccess(test)
1478 if parsable:
1479 self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1480
Johnny Chence681462010-10-19 00:25:01 +00001481 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001482 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001483 global parsable
Johnny Chen63c2cba2010-10-29 22:20:36 +00001484 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001485 super(LLDBTestResult, self).addError(test, err)
1486 method = getattr(test, "markError", None)
1487 if method:
1488 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001489 if parsable:
Daniel Maleae1dd3e52013-03-07 18:39:26 +00001490 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Johnny Chence681462010-10-19 00:25:01 +00001491
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001492 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001493 global sdir_has_content
Enrico Granataac3a8e22012-09-21 19:10:53 +00001494 global failuresPerCategory
Daniel Malea361eb432013-02-15 21:31:37 +00001495 global parsable
Johnny Chen63c2cba2010-10-29 22:20:36 +00001496 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001497 super(LLDBTestResult, self).addFailure(test, err)
1498 method = getattr(test, "markFailure", None)
1499 if method:
1500 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001501 if parsable:
1502 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Enrico Granataac3a8e22012-09-21 19:10:53 +00001503 if useCategories:
1504 test_categories = self.getCategoriesForTest(test)
1505 for category in test_categories:
1506 if category in failuresPerCategory:
1507 failuresPerCategory[category] = failuresPerCategory[category] + 1
1508 else:
1509 failuresPerCategory[category] = 1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001510
Enrico Granata21416a12013-02-23 01:05:23 +00001511 def addExpectedFailure(self, test, err, bugnumber):
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001512 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001513 global parsable
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001514 sdir_has_content = True
Enrico Granata21416a12013-02-23 01:05:23 +00001515 super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber)
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001516 method = getattr(test, "markExpectedFailure", None)
1517 if method:
Enrico Granata21416a12013-02-23 01:05:23 +00001518 method(err, bugnumber)
Daniel Malea361eb432013-02-15 21:31:37 +00001519 if parsable:
1520 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001521
Johnny Chenf5b89092011-08-15 23:09:08 +00001522 def addSkip(self, test, reason):
1523 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001524 global parsable
Johnny Chenf5b89092011-08-15 23:09:08 +00001525 sdir_has_content = True
1526 super(LLDBTestResult, self).addSkip(test, reason)
1527 method = getattr(test, "markSkippedTest", None)
1528 if method:
1529 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001530 if parsable:
1531 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason))
Johnny Chenf5b89092011-08-15 23:09:08 +00001532
Enrico Granata21416a12013-02-23 01:05:23 +00001533 def addUnexpectedSuccess(self, test, bugnumber):
Johnny Chenab2f0662011-05-06 20:30:22 +00001534 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001535 global parsable
Johnny Chenab2f0662011-05-06 20:30:22 +00001536 sdir_has_content = True
Enrico Granata21416a12013-02-23 01:05:23 +00001537 super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber)
Johnny Chenab2f0662011-05-06 20:30:22 +00001538 method = getattr(test, "markUnexpectedSuccess", None)
1539 if method:
Enrico Granata21416a12013-02-23 01:05:23 +00001540 method(bugnumber)
Daniel Malea361eb432013-02-15 21:31:37 +00001541 if parsable:
1542 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1543
1544 if parsable:
1545 v = 0
1546 elif progress_bar:
1547 v = 1
1548 else:
1549 v = verbose
Johnny Chenab2f0662011-05-06 20:30:22 +00001550
Johnny Chen26be4532010-11-09 23:56:14 +00001551 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001552 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001553 result = unittest2.TextTestRunner(stream=sys.stderr,
Daniel Malea361eb432013-02-15 21:31:37 +00001554 verbosity=v,
Johnny Chen7d6d8442010-12-03 19:59:35 +00001555 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001556 resultclass=LLDBTestResult).run(suite)
1557 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001558 # We are invoking the same test suite more than once. In this case,
1559 # mark __ignore_singleton__ flag as True so the signleton pattern is
1560 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001561 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001562 for i in range(count):
Daniel Malea361eb432013-02-15 21:31:37 +00001563
Johnny Chen7d6d8442010-12-03 19:59:35 +00001564 result = unittest2.TextTestRunner(stream=sys.stderr,
Daniel Malea361eb432013-02-15 21:31:37 +00001565 verbosity=v,
Johnny Chen7d6d8442010-12-03 19:59:35 +00001566 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001567 resultclass=LLDBTestResult).run(suite)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001568
Daniel Malea24765572013-02-20 20:12:11 +00001569 failed = failed or not result.wasSuccessful()
Johnny Chen1bfbd412010-06-29 19:44:16 +00001570
Daniel Malea361eb432013-02-15 21:31:37 +00001571if sdir_has_content and not parsable:
Johnny Chenab2f0662011-05-06 20:30:22 +00001572 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1573 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001574
Enrico Granataac3a8e22012-09-21 19:10:53 +00001575if useCategories and len(failuresPerCategory) > 0:
1576 sys.stderr.write("Failures per category:\n")
1577 for category in failuresPerCategory:
1578 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
1579
Enrico Granata571358f2013-06-19 21:48:09 +00001580os.chdir(where_to_save_session)
Johnny Chena73ad662012-08-16 19:15:21 +00001581fname = os.path.join(sdir_name, "TestFinished")
1582with open(fname, "w") as f:
1583 print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1584
Johnny Chencd0279d2010-09-20 18:07:50 +00001585# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1586# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001587if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001588 print "Terminating Test suite..."
1589 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1590
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001591# Exiting.
Daniel Malea24765572013-02-20 20:12:11 +00001592sys.exit(failed)