blob: 599bfda264906ad4d9aa375901196e801370fee7 [file] [log] [blame]
Johnny Chen9707bb62010-06-25 21:14:08 +00001#!/usr/bin/env python
2
3"""
4A simple testing framework for lldb using python's unit testing framework.
5
6Tests for lldb are written as python scripts which take advantage of the script
7bridging provided by LLDB.framework to interact with lldb core.
8
9A specific naming pattern is followed by the .py script to be recognized as
10a module which implements a test scenario, namely, Test*.py.
11
12To specify the directories where "Test*.py" python test scripts are located,
13you need to pass in a list of directory names. By default, the current
14working directory is searched if nothing is specified on the command line.
Johnny Chen872aee12010-09-16 15:44:23 +000015
16Type:
17
18./dotest.py -h
19
20for available options.
Johnny Chen9707bb62010-06-25 21:14:08 +000021"""
22
Greg Clayton4793e942012-09-04 15:42:49 +000023import argparse
24import os
25import platform
26import signal
Johnny Chen2891bb02011-09-16 01:04:26 +000027import subprocess
Greg Clayton4793e942012-09-04 15:42:49 +000028import sys
29import textwrap
30import time
Johnny Chen75e28f92010-08-05 23:42:46 +000031import unittest2
Enrico Granatabc0c5a62013-02-08 23:39:18 +000032import progress
Johnny Chen9707bb62010-06-25 21:14:08 +000033
Johnny Chen26901c82011-03-11 19:47:23 +000034def is_exe(fpath):
Johnny Chenf2c7b282011-04-26 23:10:51 +000035 """Returns true if fpath is an executable."""
Johnny Chen26901c82011-03-11 19:47:23 +000036 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
37
Johnny Chen26901c82011-03-11 19:47:23 +000038def which(program):
Johnny Chenf2c7b282011-04-26 23:10:51 +000039 """Returns the full path to a program; None otherwise."""
Johnny Chen26901c82011-03-11 19:47:23 +000040 fpath, fname = os.path.split(program)
41 if fpath:
42 if is_exe(program):
43 return program
44 else:
45 for path in os.environ["PATH"].split(os.pathsep):
46 exe_file = os.path.join(path, program)
47 if is_exe(exe_file):
48 return exe_file
49 return None
50
Johnny Chen877c7e42010-08-07 00:16:07 +000051class _WritelnDecorator(object):
52 """Used to decorate file-like objects with a handy 'writeln' method"""
53 def __init__(self,stream):
54 self.stream = stream
55
56 def __getattr__(self, attr):
57 if attr in ('stream', '__getstate__'):
58 raise AttributeError(attr)
59 return getattr(self.stream,attr)
60
61 def writeln(self, arg=None):
62 if arg:
63 self.write(arg)
64 self.write('\n') # text-mode streams translate to \r\n if needed
65
Johnny Chen9707bb62010-06-25 21:14:08 +000066#
67# Global variables:
68#
69
Enrico Granataac3a8e22012-09-21 19:10:53 +000070# Dictionary of categories
71# When you define a new category for your testcases, be sure to add it here, or the test suite
72# will gladly complain as soon as you try to use it. This allows us to centralize which categories
73# exist, and to provide a description for each one
74validCategories = {
75'dataformatters':'Tests related to the type command and the data formatters subsystem',
76'expression':'Tests related to the expression parser',
77'objc':'Tests related to the Objective-C programming language support',
78'pyapi':'Tests related to the Python API'
79}
80
Johnny Chen9707bb62010-06-25 21:14:08 +000081# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000082suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000083
Johnny Chen4f93bf12010-12-10 00:51:23 +000084# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000085# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
86# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000087dont_do_python_api_test = False
88
89# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000090just_do_python_api_test = False
91
Johnny Chen82ccf402011-07-30 01:39:58 +000092# By default, benchmarks tests are not run.
93just_do_benchmarks_test = False
94
Johnny Chena3ed7d82012-04-06 00:56:05 +000095# By default, both dsym and dwarf tests are performed.
96# Use @dsym_test or @dwarf_test decorators, defined in lldbtest.py, to mark a test
97# as a dsym or dwarf test. Use '-N dsym' or '-N dwarf' to exclude dsym or dwarf
98# tests from running.
Daniel Maleab8106282012-11-20 16:07:33 +000099dont_do_dsym_test = "linux" in sys.platform
Johnny Chena3ed7d82012-04-06 00:56:05 +0000100dont_do_dwarf_test = False
101
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000102# The blacklist is optional (-b blacklistFile) and allows a central place to skip
103# testclass's and/or testclass.testmethod's.
104blacklist = None
105
106# The dictionary as a result of sourcing blacklistFile.
107blacklistConfig = {}
108
Enrico Granataac3a8e22012-09-21 19:10:53 +0000109# The list of categories we said we care about
110categoriesList = None
111# set to true if we are going to use categories for cherry-picking test cases
112useCategories = False
113# use this to track per-category failures
114failuresPerCategory = {}
115
Sean Callanan0acf4c62012-10-24 22:45:39 +0000116# The path to LLDB.framework is optional.
117lldbFrameworkPath = None
118
119# The path to lldb is optional
120lldbExecutablePath = None
121
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000122# The config file is optional.
123configFile = None
124
Johnny Chend2acdb32010-11-16 22:42:58 +0000125# Test suite repeat count. Can be overwritten with '-# count'.
126count = 1
127
Johnny Chenb40056b2010-09-21 00:09:27 +0000128# The dictionary as a result of sourcing configFile.
129config = {}
Johnny Chenac97a6b2012-04-16 18:55:15 +0000130# The pre_flight and post_flight functions come from reading a config file.
131pre_flight = None
132post_flight = None
Johnny Chenb40056b2010-09-21 00:09:27 +0000133
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000134# The 'archs' and 'compilers' can be specified via either command line or configFile,
Greg Clayton4793e942012-09-04 15:42:49 +0000135# with the command line overriding the configFile. The corresponding options can be
136# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386']
137# and "-C gcc -C clang" => compilers=['gcc', 'clang'].
138archs = None # Must be initialized after option parsing
139compilers = None # Must be initialized after option parsing
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000140
Johnny Chen1abe4c02012-03-20 00:33:51 +0000141# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
142# the inferior programs. The global variable cflags_extras provides a hook to do
143# just that.
144cflags_extras = ''
145
Johnny Chen91960d32010-09-08 20:56:16 +0000146# Delay startup in order for the debugger to attach.
147delay = False
148
Johnny Chend5362332011-01-29 01:21:04 +0000149# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000150dumpSysPath = False
151
Johnny Chene00c9302011-10-10 22:03:44 +0000152# Full path of the benchmark executable, as specified by the '-e' option.
153bmExecutable = None
154# The breakpoint specification of bmExecutable, as specified by the '-x' option.
155bmBreakpointSpec = None
Johnny Chen5f2ed172011-10-20 18:43:28 +0000156# The benchamrk iteration count, as specified by the '-y' option.
157bmIterationCount = -1
Johnny Chene00c9302011-10-10 22:03:44 +0000158
Johnny Chene9eae812012-01-18 05:15:00 +0000159# By default, don't exclude any directories. Use '-X' to add one excluded directory.
160excluded = set(['.svn', '.git'])
161
Johnny Chen7d6d8442010-12-03 19:59:35 +0000162# By default, failfast is False. Use '-F' to overwrite it.
163failfast = False
164
Johnny Chenc5fa0052011-07-29 22:54:56 +0000165# The filters (testclass.testmethod) used to admit tests into our test suite.
166filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000167
Johnny Chen38f823c2011-10-11 01:30:27 +0000168# The runhooks is a list of lldb commands specifically for the debugger.
169# Use '-k' to specify a runhook.
170runHooks = []
171
Johnny Chena224cd12010-11-08 01:21:03 +0000172# If '-g' is specified, the filterspec is not exclusive. If a test module does
173# not contain testclass.testmethod which matches the filterspec, the whole test
174# module is still admitted into our test suite. fs4all flag defaults to True.
175fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000176
Johnny Chenaf149a02010-09-16 17:11:30 +0000177# Ignore the build search path relative to this script to locate the lldb.py module.
178ignore = False
179
Johnny Chen028d8eb2011-11-17 19:57:27 +0000180# By default, we do not skip build and cleanup. Use '-S' option to override.
181skip_build_and_cleanup = False
182
Johnny Chen548aefd2010-10-11 22:25:46 +0000183# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000184skip_long_running_test = True
Johnny Chen41998192010-10-01 22:59:49 +0000185
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000186# By default, we print the build dir, lldb version, and svn info. Use '-n' option to
187# turn it off.
188noHeaders = False
189
Johnny Chen7c52ff12010-09-27 23:29:54 +0000190# The regular expression pattern to match against eligible filenames as our test cases.
191regexp = None
192
Johnny Chen548aefd2010-10-11 22:25:46 +0000193# By default, tests are executed in place and cleanups are performed afterwards.
194# Use '-r dir' option to relocate the tests and their intermediate files to a
195# different directory and to forgo any cleanups. The directory specified must
196# not exist yet.
197rdir = None
198
Johnny Chen125fc2b2010-10-21 16:55:35 +0000199# By default, recorded session info for errored/failed test are dumped into its
200# own file under a session directory named after the timestamp of the test suite
201# run. Use '-s session-dir-name' to specify a specific dir name.
202sdir_name = None
203
Johnny Chen63c2cba2010-10-29 22:20:36 +0000204# Set this flag if there is any session info dumped during the test run.
205sdir_has_content = False
206
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000207# svn_info stores the output from 'svn info lldb.base.dir'.
208svn_info = ''
209
Johnny Chen9707bb62010-06-25 21:14:08 +0000210# Default verbosity is 0.
211verbose = 0
212
Johnny Chen08967192011-11-18 00:19:29 +0000213# Set to True only if verbose is 0 and LLDB trace mode is off.
214progress_bar = False
215
Peter Collingbourne61aca482011-06-20 19:06:29 +0000216# By default, search from the script directory.
217testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000218
Johnny Chen877c7e42010-08-07 00:16:07 +0000219# Separator string.
220separator = '-' * 70
221
Johnny Chen9707bb62010-06-25 21:14:08 +0000222
Greg Clayton4793e942012-09-04 15:42:49 +0000223def usage(parser):
224 parser.print_help()
Jim Ingham4f347cb2011-04-13 21:11:41 +0000225 if verbose > 0:
226 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000227Examples:
228
Johnny Chena224cd12010-11-08 01:21:03 +0000229This is an example of using the -f option to pinpoint to a specfic test class
230and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000231
Johnny Chena224cd12010-11-08 01:21:03 +0000232$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000233----------------------------------------------------------------------
234Collected 1 test
235
236test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
237Test 'frame variable this' when stopped on a class constructor. ... ok
238
239----------------------------------------------------------------------
240Ran 1 test in 1.396s
241
242OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000243
244And this is an example of using the -p option to run a single file (the filename
245matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
246
247$ ./dotest.py -v -p ObjC
248----------------------------------------------------------------------
249Collected 4 tests
250
251test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000252Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000253test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000254Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000255test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
256Lookup objective-c data types and evaluate expressions. ... ok
257test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
258Lookup objective-c data types and evaluate expressions. ... ok
259
260----------------------------------------------------------------------
261Ran 4 tests in 16.661s
262
263OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000264
Johnny Chen58f93922010-06-29 23:10:39 +0000265Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000266individual test cases can locate their supporting files correctly. The script
267tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000268relative to this script. See also the '-i' option in the following example.
269
270Finally, this is an example of using the lldb.py module distributed/installed by
271Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
272option to add some delay between two tests. It uses ARCH=x86_64 to specify that
273as the architecture and CC=clang to specify the compiler used for the test run:
274
275$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
276
277Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
278----------------------------------------------------------------------
279Collected 2 tests
280
281test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
282Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
283test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
284Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
285
286----------------------------------------------------------------------
287Ran 2 tests in 5.659s
288
289OK
290
291The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
292notify the directory containing the session logs for test failures or errors.
293In case there is any test failure/error, a similar message is appended at the
294end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000295
296Environment variables related to loggings:
297
298o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
299 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
300
301o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
302 'process.gdb-remote' subsystem with a default option of 'packets' if
303 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000304"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000305 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000306
307
Johnny Chenaf149a02010-09-16 17:11:30 +0000308def parseOptionsAndInitTestdirs():
309 """Initialize the list of directories containing our unittest scripts.
310
311 '-h/--help as the first option prints out usage info and exit the program.
312 """
313
Johnny Chen4f93bf12010-12-10 00:51:23 +0000314 global dont_do_python_api_test
315 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000316 global just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +0000317 global dont_do_dsym_test
318 global dont_do_dwarf_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000319 global blacklist
320 global blacklistConfig
Enrico Granataac3a8e22012-09-21 19:10:53 +0000321 global categoriesList
322 global validCategories
323 global useCategories
Sean Callanan0acf4c62012-10-24 22:45:39 +0000324 global lldbFrameworkPath
325 global lldbExecutablePath
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000326 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000327 global archs
328 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000329 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000330 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000331 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000332 global bmExecutable
333 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000334 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000335 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000336 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000337 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000338 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000339 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000340 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000341 global skip_build_and_cleanup
342 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000343 global noHeaders
Johnny Chen7c52ff12010-09-27 23:29:54 +0000344 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000345 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000346 global sdir_name
Johnny Chenaf149a02010-09-16 17:11:30 +0000347 global verbose
348 global testdirs
349
Jim Ingham4f347cb2011-04-13 21:11:41 +0000350 do_help = False
351
Greg Clayton4793e942012-09-04 15:42:49 +0000352 parser = argparse.ArgumentParser(description='description', prefix_chars='+-', add_help=False)
353 group = None
Johnny Chenaf149a02010-09-16 17:11:30 +0000354
Greg Clayton4793e942012-09-04 15:42:49 +0000355 # Helper function for boolean options (group will point to the current group when executing X)
356 X = lambda optstr, helpstr, **kwargs: group.add_argument(optstr, help=helpstr, action='store_true', **kwargs)
357
358 group = parser.add_argument_group('Help')
359 group.add_argument('-h', '--help', dest='h', action='store_true', help="Print this help message and exit. Add '-v' for more detailed help.")
360
361 # C and Python toolchain options
362 group = parser.add_argument_group('Toolchain options')
363 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'''))
364 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.'''))
365 # FIXME? This won't work for different extra flags according to each arch.
366 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
367 suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
368 X('-D', 'Dump the Python sys.path variable')
369
370 # Test filtering options
371 group = parser.add_argument_group('Test filtering options')
372 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")
373 X('-a', "Don't do lldb Python API tests")
374 X('+a', "Just do lldb Python API tests. Do not specify along with '+a'", dest='plus_a')
375 X('+b', 'Just do benchmark tests', dest='plus_b')
376 group.add_argument('-b', metavar='blacklist', help='Read a blacklist file specified after this option')
Enrico Granata58b03a42012-12-14 00:07:09 +0000377 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 +0000378 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')
379 X('-l', "Don't skip long running tests")
380 group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite')
381 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 +0000382 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 +0000383
384 # Configuration options
385 group = parser.add_argument_group('Configuration options')
386 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 +0000387 group.add_argument('--framework', metavar='framework-path', help='The path to LLDB.framework')
388 group.add_argument('--executable', metavar='executable-path', help='The path to the lldb executable')
Greg Clayton4793e942012-09-04 15:42:49 +0000389 group.add_argument('-e', metavar='benchmark-exe', help='Specify the full path of an executable used for benchmark purposes (see also: -x)')
390 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")
391 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')
392 group.add_argument('-r', metavar='dir', help="Similar to '-R', except that the directory must not exist before running this test driver")
393 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')
394 group.add_argument('-x', metavar='breakpoint-spec', help='Specify the breakpoint specification for the benchmark executable')
395 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.")
396 group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times')
397
398 # Test-suite behaviour
399 group = parser.add_argument_group('Runtime behaviour options')
400 X('-d', 'Delay startup for 10 seconds (in order for the debugger to attach)')
401 X('-F', 'Fail fast. Stop the test suite on the first error/failure')
402 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")
403 X('-n', "Don't print the headers like build dir, lldb version, and svn info at all")
404 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")
405 X('-t', 'Turn on tracing of lldb command and other detailed test executions')
Greg Claytonb85785c2013-02-08 21:52:32 +0000406 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 +0000407 X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
408 X('-w', 'Insert some wait time (currently 0.5 sec) between consecutive test cases')
409
410 # Remove the reference to our helper function
411 del X
412
413 group = parser.add_argument_group('Test directories')
414 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.')
415 args = parser.parse_args()
416
417 platform_system = platform.system()
418 platform_machine = platform.machine()
Enrico Granata2d329242012-10-23 22:52:49 +0000419
Greg Claytonb85785c2013-02-08 21:52:32 +0000420 if args.unset_env_varnames:
421 for env_var in args.unset_env_varnames:
422 if env_var in os.environ:
423 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
424 # is automatically translated into a corresponding call to unsetenv().
425 del os.environ[env_var]
426 #os.unsetenv(env_var)
427
Enrico Granata2d329242012-10-23 22:52:49 +0000428 # only print the args if being verbose
429 if args.v:
430 print args
Greg Clayton4793e942012-09-04 15:42:49 +0000431
432 if args.h:
433 do_help = True
434
435 if args.archs:
436 archs = args.archs
437 else:
438 if platform_system == 'Darwin' and platform_machine == 'x86_64':
439 archs = ['x86_64', 'i386']
Johnny Chenaf149a02010-09-16 17:11:30 +0000440 else:
Greg Clayton4793e942012-09-04 15:42:49 +0000441 archs = [platform_machine]
442
Enrico Granataac3a8e22012-09-21 19:10:53 +0000443 if args.categoriesList:
444 for category in args.categoriesList:
445 if not(category in validCategories):
Enrico Granata2d329242012-10-23 22:52:49 +0000446 print "fatal error: category '" + category + "' is not a valid category"
447 print "if you have added a new category, please edit dotest.py, adding your new category to validCategories"
448 print "else, please specify one or more of the following: " + str(validCategories.keys())
Enrico Granataac3a8e22012-09-21 19:10:53 +0000449 sys.exit(1)
450 categoriesList = set(args.categoriesList)
451 useCategories = True
452 else:
453 categoriesList = []
454
Greg Clayton4793e942012-09-04 15:42:49 +0000455 if args.compilers:
456 compilers = args.compilers
457 else:
458 compilers = ['clang']
459
460 if args.D:
461 dumpSysPath = True
462
463 if args.E:
464 cflags_extras = args.E
465 os.environ['CFLAGS_EXTRAS'] = cflags_extras
466
467 # argparse makes sure we have correct options
468 if args.N == 'dwarf':
469 dont_do_dwarf_test = True
470 elif args.N == 'dsym':
471 dont_do_dsym_test = True
472
473 if args.a:
474 dont_do_python_api_test = True
475
476 if args.plus_a:
477 if dont_do_python_api_test:
478 print "Warning: -a and +a can't both be specified! Using only -a"
479 else:
480 just_do_python_api_test = True
481
482 if args.plus_b:
483 just_do_benchmarks_test = True
484
485 if args.b:
486 if args.b.startswith('-'):
487 usage(parser)
488 blacklistFile = args.b
489 if not os.path.isfile(blacklistFile):
490 print 'Blacklist file:', blacklistFile, 'does not exist!'
491 usage(parser)
492 # Now read the blacklist contents and assign it to blacklist.
493 execfile(blacklistFile, globals(), blacklistConfig)
494 blacklist = blacklistConfig.get('blacklist')
495
496 if args.c:
497 if args.c.startswith('-'):
498 usage(parser)
499 configFile = args.c
500 if not os.path.isfile(configFile):
501 print 'Config file:', configFile, 'does not exist!'
502 usage(parser)
503
504 if args.d:
505 delay = True
506
507 if args.e:
508 if args.e.startswith('-'):
509 usage(parser)
510 bmExecutable = args.e
511 if not is_exe(bmExecutable):
512 usage(parser)
513
514 if args.F:
515 failfast = True
516
517 if args.f:
Enrico Granata58b03a42012-12-14 00:07:09 +0000518 if any([x.startswith('-') for x in args.f]):
Greg Clayton4793e942012-09-04 15:42:49 +0000519 usage(parser)
Enrico Granata58b03a42012-12-14 00:07:09 +0000520 filters.extend(args.f)
Greg Clayton4793e942012-09-04 15:42:49 +0000521
522 if args.g:
523 fs4all = False
524
525 if args.i:
526 ignore = True
527
528 if args.k:
529 runHooks.extend(args.k)
530
531 if args.l:
532 skip_long_running_test = False
533
Sean Callanan0acf4c62012-10-24 22:45:39 +0000534 if args.framework:
535 lldbFrameworkPath = args.framework
536
537 if args.executable:
538 lldbExecutablePath = args.executable
539
Greg Clayton4793e942012-09-04 15:42:49 +0000540 if args.n:
541 noHeaders = True
542
543 if args.p:
544 if args.p.startswith('-'):
545 usage(parser)
546 regexp = args.p
547
548 if args.R:
549 if args.R.startswith('-'):
550 usage(parser)
551 rdir = os.path.abspath(args.R)
552 if os.path.exists(rdir):
553 import shutil
554 print 'Removing tree:', rdir
555 shutil.rmtree(rdir)
556
557 if args.r:
558 if args.r.startswith('-'):
559 usage(parser)
560 rdir = os.path.abspath(args.r)
561 if os.path.exists(rdir):
562 print 'Relocated directory:', rdir, 'must not exist!'
563 usage(parser)
564
565 if args.S:
566 skip_build_and_cleanup = True
567
568 if args.s:
569 if args.s.startswith('-'):
570 usage(parser)
571 sdir_name = args.s
572
573 if args.t:
574 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
575
Greg Clayton4793e942012-09-04 15:42:49 +0000576 if args.v:
577 verbose = 2
578
579 if args.w:
580 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
581
582 if args.X:
583 if args.X.startswith('-'):
584 usage(parser)
585 excluded.add(args.X)
586
587 if args.x:
588 if args.x.startswith('-'):
589 usage(parser)
590 bmBreakpointSpec = args.x
591
592 # argparse makes sure we have a number
593 if args.y:
594 bmIterationCount = args.y
595
596 # argparse makes sure we have a number
597 if args.sharp:
598 count = args.sharp
Johnny Chenaf149a02010-09-16 17:11:30 +0000599
Jim Ingham4f347cb2011-04-13 21:11:41 +0000600 if do_help == True:
Greg Clayton4793e942012-09-04 15:42:49 +0000601 usage(parser)
Jim Ingham4f347cb2011-04-13 21:11:41 +0000602
Johnny Chencc659ad2010-12-10 19:02:23 +0000603 # Do not specify both '-a' and '+a' at the same time.
604 if dont_do_python_api_test and just_do_python_api_test:
Greg Clayton4793e942012-09-04 15:42:49 +0000605 usage(parser)
Johnny Chencc659ad2010-12-10 19:02:23 +0000606
Johnny Chen08967192011-11-18 00:19:29 +0000607 # The simple progress bar is turned on only if verbose == 0 and LLDB_COMMAND_TRACE is not 'YES'
Greg Clayton4793e942012-09-04 15:42:49 +0000608 if ("LLDB_COMMAND_TRACE" not in os.environ or os.environ["LLDB_COMMAND_TRACE"] != "YES") and verbose == 0:
Johnny Chen08967192011-11-18 00:19:29 +0000609 progress_bar = True
610
Johnny Chenaf149a02010-09-16 17:11:30 +0000611 # Gather all the dirs passed on the command line.
Greg Clayton4793e942012-09-04 15:42:49 +0000612 if len(args.args) > 0:
613 testdirs = map(os.path.abspath, args.args)
Johnny Chenaf149a02010-09-16 17:11:30 +0000614
Johnny Chen548aefd2010-10-11 22:25:46 +0000615 # If '-r dir' is specified, the tests should be run under the relocated
616 # directory. Let's copy the testdirs over.
617 if rdir:
618 from shutil import copytree, ignore_patterns
619
620 tmpdirs = []
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000621 orig_testdirs = testdirs[:]
Johnny Chen548aefd2010-10-11 22:25:46 +0000622 for srcdir in testdirs:
Johnny Chen1abe4c02012-03-20 00:33:51 +0000623 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
624 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
625 # Utilize the relative path to the 'test' directory to make our destination dir path.
Greg Clayton4793e942012-09-04 15:42:49 +0000626 if ("test" + os.sep) in srcdir:
627 to_split_on = "test" + os.sep
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000628 else:
629 to_split_on = "test"
630 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
631 dstdir = dstdir.rstrip(os.sep)
Johnny Chen548aefd2010-10-11 22:25:46 +0000632 # Don't copy the *.pyc and .svn stuffs.
633 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
634 tmpdirs.append(dstdir)
635
636 # This will be our modified testdirs.
637 testdirs = tmpdirs
638
639 # With '-r dir' specified, there's no cleanup of intermediate test files.
640 os.environ["LLDB_DO_CLEANUP"] = 'NO'
641
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000642 # If the original testdirs is ['test'], the make directory has already been copied
Johnny Chen548aefd2010-10-11 22:25:46 +0000643 # recursively and is contained within the rdir/test dir. For anything
644 # else, we would need to copy over the make directory and its contents,
645 # so that, os.listdir(rdir) looks like, for example:
646 #
647 # array_types conditional_break make
648 #
649 # where the make directory contains the Makefile.rules file.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000650 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000651 scriptdir = os.path.dirname(__file__)
Johnny Chen548aefd2010-10-11 22:25:46 +0000652 # Don't copy the .svn stuffs.
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000653 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
Johnny Chen548aefd2010-10-11 22:25:46 +0000654 ignore=ignore_patterns('.svn'))
655
656 #print "testdirs:", testdirs
657
Johnny Chenb40056b2010-09-21 00:09:27 +0000658 # Source the configFile if specified.
659 # The side effect, if any, will be felt from this point on. An example
660 # config file may be these simple two lines:
661 #
662 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
663 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
664 #
665 # which will reassign the two file objects to sys.stderr and sys.stdout,
666 # respectively.
667 #
Johnny Chen8c130642012-08-22 17:53:02 +0000668 # See also lldb-trunk/examples/test/usage-config.
Johnny Chenac97a6b2012-04-16 18:55:15 +0000669 global config, pre_flight, post_flight
Johnny Chenb40056b2010-09-21 00:09:27 +0000670 if configFile:
671 # Pass config (a dictionary) as the locals namespace for side-effect.
672 execfile(configFile, globals(), config)
Johnny Chenac97a6b2012-04-16 18:55:15 +0000673 print "config:", config
674 if "pre_flight" in config:
675 pre_flight = config["pre_flight"]
676 if not callable(pre_flight):
677 print "fatal error: pre_flight is not callable, exiting."
678 sys.exit(1)
679 if "post_flight" in config:
680 post_flight = config["post_flight"]
681 if not callable(post_flight):
682 print "fatal error: post_flight is not callable, exiting."
683 sys.exit(1)
Johnny Chenb40056b2010-09-21 00:09:27 +0000684 #print "sys.stderr:", sys.stderr
685 #print "sys.stdout:", sys.stdout
686
Johnny Chenaf149a02010-09-16 17:11:30 +0000687
Johnny Chen9707bb62010-06-25 21:14:08 +0000688def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000689 """
690 Add LLDB.framework/Resources/Python to the search paths for modules.
691 As a side effect, we also discover the 'lldb' executable and export it here.
692 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000693
Johnny Chen548aefd2010-10-11 22:25:46 +0000694 global rdir
695 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000696 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000697 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000698 global svn_info
Sean Callanan0acf4c62012-10-24 22:45:39 +0000699 global lldbFrameworkPath
700 global lldbExecutablePath
Johnny Chen548aefd2010-10-11 22:25:46 +0000701
Johnny Chen9707bb62010-06-25 21:14:08 +0000702 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000703 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 +0000704 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
705 else:
706 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000707 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000708 print "This script expects to reside in lldb's test directory."
709 sys.exit(-1)
710
Johnny Chen548aefd2010-10-11 22:25:46 +0000711 if rdir:
712 # Set up the LLDB_TEST environment variable appropriately, so that the
713 # individual tests can be located relatively.
714 #
715 # See also lldbtest.TestBase.setUpClass(cls).
716 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
717 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
718 else:
719 os.environ["LLDB_TEST"] = rdir
720 else:
721 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000722
723 # Set up the LLDB_SRC environment variable, so that the tests can locate
724 # the LLDB source code.
725 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
726
Johnny Chen9de4ede2010-08-31 17:42:54 +0000727 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000728 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000729
Johnny Chen8a3c0432011-03-11 20:13:06 +0000730 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000731 sys.path.append(scriptPath)
732 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000733 sys.path.append(pexpectPath)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000734
Johnny Chen26901c82011-03-11 19:47:23 +0000735 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000736 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000737
Johnny Chen26901c82011-03-11 19:47:23 +0000738 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000739 xcode3_build_dir = ['build']
740 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
741 dbg = ['Debug']
Sean Callanand9d94632012-09-26 21:16:15 +0000742 dbc = ['DebugClang']
Johnny Chen6a564a42011-02-15 18:50:19 +0000743 rel = ['Release']
744 bai = ['BuildAndIntegration']
745 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000746
747 # Some of the tests can invoke the 'lldb' command directly.
748 # We'll try to locate the appropriate executable right here.
749
Sean Callanan0acf4c62012-10-24 22:45:39 +0000750 lldbExec = None
751 if lldbExecutablePath:
752 if is_exe(lldbExecutablePath):
753 lldbExec = lldbExecutablePath
Sean Callanan502000d2012-11-01 21:23:21 +0000754 lldbHere = lldbExec
Sean Callanan0acf4c62012-10-24 22:45:39 +0000755 else:
756 print lldbExecutablePath + " is not an executable"
757 sys.exit(-1)
Johnny Chen6033bed2011-08-26 00:00:01 +0000758 else:
Sean Callanan0acf4c62012-10-24 22:45:39 +0000759 # First, you can define an environment variable LLDB_EXEC specifying the
760 # full pathname of the lldb executable.
761 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
762 lldbExec = os.environ["LLDB_EXEC"]
763 else:
764 lldbExec = None
765
766 executable = ['lldb']
767 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
768 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
769 dbcExec = os.path.join(base, *(xcode3_build_dir + dbc + executable))
770 dbcExec2 = os.path.join(base, *(xcode4_build_dir + dbc + executable))
771 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
772 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
773 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
774 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
775
776 # The 'lldb' executable built here in the source tree.
777 lldbHere = None
778 if is_exe(dbgExec):
779 lldbHere = dbgExec
780 elif is_exe(dbgExec2):
781 lldbHere = dbgExec2
782 elif is_exe(dbcExec):
783 lldbHere = dbcExec
784 elif is_exe(dbcExec2):
785 lldbHere = dbcExec2
786 elif is_exe(relExec):
787 lldbHere = relExec
788 elif is_exe(relExec2):
789 lldbHere = relExec2
790 elif is_exe(baiExec):
791 lldbHere = baiExec
792 elif is_exe(baiExec2):
793 lldbHere = baiExec2
794 elif lldbExec:
795 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000796
Sean Callanan0acf4c62012-10-24 22:45:39 +0000797 # One last chance to locate the 'lldb' executable.
798 if not lldbExec:
799 lldbExec = which('lldb')
800 if lldbHere and not lldbExec:
801 lldbExec = lldbHere
Daniel Malea2777b012013-02-06 16:55:07 +0000802 if lldbExec and not lldbHere:
803 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000804
805 if lldbHere:
806 os.environ["LLDB_HERE"] = lldbHere
807 os.environ["LLDB_BUILD_DIR"] = os.path.split(lldbHere)[0]
808 if not noHeaders:
809 print "LLDB build dir:", os.environ["LLDB_BUILD_DIR"]
810 os.system('%s -v' % lldbHere)
Johnny Chen26901c82011-03-11 19:47:23 +0000811
812 if not lldbExec:
813 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
814 else:
815 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000816 #print "The 'lldb' from PATH env variable", lldbExec
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000817
Johnny Chenb264c9b2011-06-24 22:52:05 +0000818 if os.path.isdir(os.path.join(base, '.svn')):
819 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
820 svn_info = pipe.stdout.read()
821 elif os.path.isdir(os.path.join(base, '.git')):
822 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
823 svn_info = pipe.stdout.read()
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000824 if not noHeaders:
825 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000826
827 global ignore
828
Johnny Chen9707bb62010-06-25 21:14:08 +0000829 lldbPath = None
Sean Callanan0acf4c62012-10-24 22:45:39 +0000830 if lldbFrameworkPath:
831 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python')
832 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
833 lldbPath = candidatePath
834 if not lldbPath:
835 print 'Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath
836 sys.exit(-1)
837 else:
838 # The '-i' option is used to skip looking for lldb.py in the build tree.
839 if ignore:
840 return
Jim Inghamaa93c932012-12-21 22:22:26 +0000841
842 # If our lldb supports the -P option, use it to find the python path:
843 init_in_python_dir = 'lldb/__init__.py'
844 import pexpect
845 lldb_dash_p_result = None
846
847 if lldbHere:
848 lldb_dash_p_result = pexpect.run("%s -P"%(lldbHere))
849 elif lldbExec:
850 lldb_dash_p_result = pexpect.run("%s -P"%(lldbExec))
851
852 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")):
853 lines = lldb_dash_p_result.splitlines()
854 if len(lines) == 1 and os.path.isfile(os.path.join(lines[0], init_in_python_dir)):
855 lldbPath = lines[0]
Daniel Malea21e32a62013-01-04 23:35:13 +0000856 if "linux" in sys.platform:
857 os.environ['LLDB_BUILD_DIR'] = os.path.join(lldbPath, 'lldb')
Jim Inghamaa93c932012-12-21 22:22:26 +0000858
859 if not lldbPath:
860 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
861 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
862 dbcPath = os.path.join(base, *(xcode3_build_dir + dbc + python_resource_dir))
863 dbcPath2 = os.path.join(base, *(xcode4_build_dir + dbc + python_resource_dir))
864 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
865 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
866 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
867 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Sean Callanan0acf4c62012-10-24 22:45:39 +0000868
Jim Inghamaa93c932012-12-21 22:22:26 +0000869 if os.path.isfile(os.path.join(dbgPath, init_in_python_dir)):
870 lldbPath = dbgPath
871 elif os.path.isfile(os.path.join(dbgPath2, init_in_python_dir)):
872 lldbPath = dbgPath2
873 elif os.path.isfile(os.path.join(dbcPath, init_in_python_dir)):
874 lldbPath = dbcPath
875 elif os.path.isfile(os.path.join(dbcPath2, init_in_python_dir)):
876 lldbPath = dbcPath2
877 elif os.path.isfile(os.path.join(relPath, init_in_python_dir)):
878 lldbPath = relPath
879 elif os.path.isfile(os.path.join(relPath2, init_in_python_dir)):
880 lldbPath = relPath2
881 elif os.path.isfile(os.path.join(baiPath, init_in_python_dir)):
882 lldbPath = baiPath
883 elif os.path.isfile(os.path.join(baiPath2, init_in_python_dir)):
884 lldbPath = baiPath2
885
Sean Callanan0acf4c62012-10-24 22:45:39 +0000886 if not lldbPath:
887 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
888 print relPath + ', or ' + baiPath
889 sys.exit(-1)
Johnny Chen9707bb62010-06-25 21:14:08 +0000890
Jim Inghamaa93c932012-12-21 22:22:26 +0000891 # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
892 # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
893 (before, frameWithVersion, after) = lldbPath.rpartition("LLDB.framework/Versions/A")
894 if frameWithVersion != "" :
895 lldbPath = before + "LLDB.framework" + after
896
Enrico Granata01458ca2012-10-23 00:09:02 +0000897 # If tests need to find LLDB_FRAMEWORK, now they can do it
898 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPath))
899
Johnny Chenaf149a02010-09-16 17:11:30 +0000900 # This is to locate the lldb.py module. Insert it right after sys.path[0].
901 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000902 if dumpSysPath:
903 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000904
Johnny Chen9707bb62010-06-25 21:14:08 +0000905
Johnny Chencd0279d2010-09-20 18:07:50 +0000906def doDelay(delta):
907 """Delaying startup for delta-seconds to facilitate debugger attachment."""
908 def alarm_handler(*args):
909 raise Exception("timeout")
910
911 signal.signal(signal.SIGALRM, alarm_handler)
912 signal.alarm(delta)
913 sys.stdout.write("pid=%d\n" % os.getpid())
914 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
915 delta)
916 sys.stdout.flush()
917 try:
918 text = sys.stdin.readline()
919 except:
920 text = ""
921 signal.alarm(0)
922 sys.stdout.write("proceeding...\n")
923 pass
924
925
Johnny Chen9707bb62010-06-25 21:14:08 +0000926def visit(prefix, dir, names):
927 """Visitor function for os.path.walk(path, visit, arg)."""
928
929 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000930 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000931 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000932 global fs4all
Johnny Chene9eae812012-01-18 05:15:00 +0000933 global excluded
934
935 if set(dir.split(os.sep)).intersection(excluded):
936 #print "Detected an excluded dir component: %s" % dir
937 return
Johnny Chen9707bb62010-06-25 21:14:08 +0000938
939 for name in names:
940 if os.path.isdir(os.path.join(dir, name)):
941 continue
942
943 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000944 # Try to match the regexp pattern, if specified.
945 if regexp:
946 import re
947 if re.search(regexp, name):
948 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
949 pass
950 else:
951 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
952 continue
953
Johnny Chen953864a2010-10-12 21:35:54 +0000954 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000955
956 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000957 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000958 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000959 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000960
961 # Thoroughly check the filterspec against the base module and admit
962 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000963 filterspec = None
964 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000965 # Optimistically set the flag to True.
966 filtered = True
967 module = __import__(base)
968 parts = filterspec.split('.')
969 obj = module
970 for part in parts:
971 try:
972 parent, obj = obj, getattr(obj, part)
973 except AttributeError:
974 # The filterspec has failed.
975 filtered = False
976 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000977
Johnny Chendb4be602011-08-12 23:55:07 +0000978 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000979 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +0000980 #print "adding filter spec %s to module %s" % (filterspec, module)
981 suite.addTests(
982 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
983 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +0000984
985 # Forgo this module if the (base, filterspec) combo is invalid
986 # and no '-g' option is specified
987 if filters and fs4all and not filtered:
988 continue
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000989
Johnny Chendb4be602011-08-12 23:55:07 +0000990 # Add either the filtered test case(s) (which is done before) or the entire test class.
991 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +0000992 # A simple case of just the module name. Also the failover case
993 # from the filterspec branch when the (base, filterspec) combo
994 # doesn't make sense.
995 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000996
997
Johnny Chencd0279d2010-09-20 18:07:50 +0000998def lldbLoggings():
999 """Check and do lldb loggings if necessary."""
1000
1001 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
1002 # defined. Use ${LLDB_LOG} to specify the log file.
1003 ci = lldb.DBG.GetCommandInterpreter()
1004 res = lldb.SBCommandReturnObject()
1005 if ("LLDB_LOG" in os.environ):
1006 if ("LLDB_LOG_OPTION" in os.environ):
1007 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
1008 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +00001009 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +00001010 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +00001011 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +00001012 res)
1013 if not res.Succeeded():
1014 raise Exception('log enable failed (check LLDB_LOG env variable.')
1015 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
1016 # Use ${GDB_REMOTE_LOG} to specify the log file.
1017 if ("GDB_REMOTE_LOG" in os.environ):
1018 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
1019 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
1020 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +00001021 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +00001022 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +00001023 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +00001024 + gdb_remote_log_option,
1025 res)
1026 if not res.Succeeded():
1027 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
1028
Johnny Chen067022b2011-01-19 19:31:46 +00001029def getMyCommandLine():
Johnny Chen067022b2011-01-19 19:31:46 +00001030 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
1031 lines = ps.split('\n')
1032 cmd_line = lines[1]
1033 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +00001034
Johnny Chend96b5682010-11-05 17:30:53 +00001035# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001036# #
1037# Execution of the test driver starts here #
1038# #
Johnny Chend96b5682010-11-05 17:30:53 +00001039# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001040
Johnny Chen2891bb02011-09-16 01:04:26 +00001041def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +00001042 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1043 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1044 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +00001045 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +00001046 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +00001047 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +00001048 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
1049 print "Exiting..."
1050 sys.exit(0)
1051
1052# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1053# does not exist before proceeding to running the test suite.
1054if sys.platform.startswith("darwin"):
1055 checkDsymForUUIDIsNotOn()
1056
Johnny Chen9707bb62010-06-25 21:14:08 +00001057#
Johnny Chenaf149a02010-09-16 17:11:30 +00001058# Start the actions by first parsing the options while setting up the test
1059# directories, followed by setting up the search paths for lldb utilities;
1060# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +00001061#
Johnny Chenaf149a02010-09-16 17:11:30 +00001062parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +00001063setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +00001064
1065#
1066# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
1067#
1068if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +00001069 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +00001070
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001071#
Johnny Chen41998192010-10-01 22:59:49 +00001072# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +00001073if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +00001074 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1075
1076#
Johnny Chen79723352010-10-12 15:53:22 +00001077# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001078#
Johnny Chen9707bb62010-06-25 21:14:08 +00001079for testdir in testdirs:
1080 os.path.walk(testdir, visit, 'Test')
1081
Johnny Chenb40056b2010-09-21 00:09:27 +00001082#
Johnny Chen9707bb62010-06-25 21:14:08 +00001083# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +00001084#
Johnny Chencd0279d2010-09-20 18:07:50 +00001085
Johnny Chen1bfbd412010-06-29 19:44:16 +00001086# For the time being, let's bracket the test runner within the
1087# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001088import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +00001089# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
1090# there's no need to call it a second time.
1091#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001092atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +00001093
Johnny Chen909e5a62010-07-01 22:52:57 +00001094# Create a singleton SBDebugger in the lldb namespace.
1095lldb.DBG = lldb.SBDebugger.Create()
1096
Johnny Chen4f93bf12010-12-10 00:51:23 +00001097# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +00001098lldb.blacklist = blacklist
1099
Johnny Chenac97a6b2012-04-16 18:55:15 +00001100# The pre_flight and post_flight come from reading a config file.
1101lldb.pre_flight = pre_flight
1102lldb.post_flight = post_flight
1103def getsource_if_available(obj):
1104 """
1105 Return the text of the source code for an object if available. Otherwise,
1106 a print representation is returned.
1107 """
1108 import inspect
1109 try:
1110 return inspect.getsource(obj)
1111 except:
1112 return repr(obj)
1113
1114print "lldb.pre_flight:", getsource_if_available(lldb.pre_flight)
1115print "lldb.post_flight:", getsource_if_available(lldb.post_flight)
1116
Johnny Chena3ed7d82012-04-06 00:56:05 +00001117# Put all these test decorators in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +00001118lldb.dont_do_python_api_test = dont_do_python_api_test
1119lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +00001120lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +00001121lldb.dont_do_dsym_test = dont_do_dsym_test
1122lldb.dont_do_dwarf_test = dont_do_dwarf_test
Johnny Chen4f93bf12010-12-10 00:51:23 +00001123
Johnny Chen028d8eb2011-11-17 19:57:27 +00001124# Do we need to skip build and cleanup?
1125lldb.skip_build_and_cleanup = skip_build_and_cleanup
1126
Johnny Chen5f2ed172011-10-20 18:43:28 +00001127# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +00001128lldb.bmExecutable = bmExecutable
1129lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +00001130lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +00001131
Johnny Chen38f823c2011-10-11 01:30:27 +00001132# And don't forget the runHooks!
1133lldb.runHooks = runHooks
1134
Johnny Chencd0279d2010-09-20 18:07:50 +00001135# Turn on lldb loggings if necessary.
1136lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +00001137
Johnny Chen7987ac92010-08-09 20:40:52 +00001138# Install the control-c handler.
1139unittest2.signals.installHandler()
1140
Johnny Chen125fc2b2010-10-21 16:55:35 +00001141# If sdir_name is not specified through the '-s sdir_name' option, get a
1142# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1143# be used when/if we want to dump the session info of individual test cases
1144# later on.
Johnny Chence681462010-10-19 00:25:01 +00001145#
1146# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chena73ad662012-08-16 19:15:21 +00001147import datetime
1148# The windows platforms don't like ':' in the pathname.
1149timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +00001150if not sdir_name:
Johnny Chena73ad662012-08-16 19:15:21 +00001151 sdir_name = timestamp_started
Peter Collingbourne132476f2011-06-20 23:55:53 +00001152os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +00001153
Johnny Chenfe5f1ed2011-10-21 18:33:27 +00001154if not noHeaders:
1155 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1156 " will go into directory '%s'\n" % sdir_name)
1157 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +00001158
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001159if not os.path.isdir(sdir_name):
1160 os.mkdir(sdir_name)
Johnny Chena73ad662012-08-16 19:15:21 +00001161fname = os.path.join(sdir_name, "TestStarted")
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001162with open(fname, "w") as f:
Johnny Chena73ad662012-08-16 19:15:21 +00001163 print >> f, "Test started at: %s\n" % timestamp_started
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001164 print >> f, svn_info
1165 print >> f, "Command invoked: %s\n" % getMyCommandLine()
1166
Johnny Chenb40056b2010-09-21 00:09:27 +00001167#
1168# Invoke the default TextTestRunner to run the test suite, possibly iterating
1169# over different configurations.
1170#
1171
Johnny Chenb40056b2010-09-21 00:09:27 +00001172iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +00001173iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001174
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001175if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001176 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001177
1178if isinstance(archs, list) and len(archs) >= 1:
1179 iterArchs = True
1180
1181if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001182 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001183
Johnny Chen92693b52012-03-09 02:11:37 +00001184#
1185# Add some intervention here to sanity check that the compilers requested are sane.
1186# If found not to be an executable program, the invalid one is dropped from the list.
1187for i in range(len(compilers)):
1188 c = compilers[i]
1189 if which(c):
1190 continue
1191 else:
1192 if sys.platform.startswith("darwin"):
1193 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1194 cmd_output = pipe.stdout.read()
1195 if cmd_output:
1196 if "not found" in cmd_output:
1197 print "dropping %s from the compilers used" % c
1198 compilers.remove(i)
1199 else:
1200 compilers[i] = cmd_output.split('\n')[0]
1201 print "'xcrun -find %s' returning %s" % (c, compilers[i])
1202
1203print "compilers=%s" % str(compilers)
1204
1205if not compilers or len(compilers) == 0:
1206 print "No eligible compiler found, exiting."
1207 sys.exit(1)
1208
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001209if isinstance(compilers, list) and len(compilers) >= 1:
1210 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001211
Johnny Chen953864a2010-10-12 21:35:54 +00001212# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1213# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001214if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001215 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001216# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1217if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001218 old_stderr = sys.stderr
1219 old_stdout = sys.stdout
1220 new_stderr = None
1221 new_stdout = None
1222
Johnny Chend96b5682010-11-05 17:30:53 +00001223# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001224for ia in range(len(archs) if iterArchs else 1):
1225 archConfig = ""
1226 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001227 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001228 archConfig = "arch=%s" % archs[ia]
1229 for ic in range(len(compilers) if iterCompilers else 1):
1230 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001231 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001232 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1233 else:
1234 configString = archConfig
1235
Johnny Chenb40056b2010-09-21 00:09:27 +00001236 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001237 # Translate ' ' to '-' for pathname component.
1238 from string import maketrans
1239 tbl = maketrans(' ', '-')
1240 configPostfix = configString.translate(tbl)
1241
1242 # Check whether we need to split stderr/stdout into configuration
1243 # specific files.
1244 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1245 if new_stderr:
1246 new_stderr.close()
1247 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1248 sys.stderr = new_stderr
1249 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1250 if new_stdout:
1251 new_stdout.close()
1252 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1253 sys.stdout = new_stdout
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001254
Johnny Chen953864a2010-10-12 21:35:54 +00001255 # If we specified a relocated directory to run the test suite, do
1256 # the extra housekeeping to copy the testdirs to a configStringified
1257 # directory and to update sys.path before invoking the test runner.
1258 # The purpose is to separate the configuration-specific directories
1259 # from each other.
1260 if rdir:
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001261 from shutil import copytree, rmtree, ignore_patterns
Johnny Chen953864a2010-10-12 21:35:54 +00001262
Johnny Chen953864a2010-10-12 21:35:54 +00001263 newrdir = "%s.%s" % (rdir, configPostfix)
1264
1265 # Copy the tree to a new directory with postfix name configPostfix.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001266 if os.path.exists(newrdir):
1267 rmtree(newrdir)
Johnny Chen953864a2010-10-12 21:35:54 +00001268 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1269
Filipe Cabecinhas0e1d06d2012-08-08 15:23:24 +00001270 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001271 # level test directory.
1272 #
1273 # See also lldbtest.TestBase.setUpClass(cls).
1274 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1275 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1276 else:
1277 os.environ["LLDB_TEST"] = newrdir
1278
1279 # And update the Python search paths for modules.
1280 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1281
1282 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +00001283 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001284
1285 #print "sys.stderr name is", sys.stderr.name
1286 #print "sys.stdout name is", sys.stdout.name
1287
1288 # First, write out the number of collected test cases.
Johnny Chen08967192011-11-18 00:19:29 +00001289 sys.stderr.write(separator + "\n")
1290 sys.stderr.write("Collected %d test%s\n\n"
1291 % (suite.countTestCases(),
1292 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001293
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001294 class LLDBTestResult(unittest2.TextTestResult):
1295 """
Johnny Chen26be4532010-11-09 23:56:14 +00001296 Enforce a singleton pattern to allow introspection of test progress.
1297
1298 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1299 to enable each test instance to track its failure/error status. It
1300 is used in the LLDB test framework to emit detailed trace messages
1301 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001302 """
1303 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001304 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001305
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001306 @staticmethod
1307 def getTerminalSize():
1308 import os
1309 env = os.environ
1310 def ioctl_GWINSZ(fd):
1311 try:
1312 import fcntl, termios, struct, os
1313 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
1314 '1234'))
1315 except:
1316 return
1317 return cr
1318 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
1319 if not cr:
1320 try:
1321 fd = os.open(os.ctermid(), os.O_RDONLY)
1322 cr = ioctl_GWINSZ(fd)
1323 os.close(fd)
1324 except:
1325 pass
1326 if not cr:
1327 cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
1328 return int(cr[1]), int(cr[0])
1329
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001330 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001331 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001332 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001333 super(LLDBTestResult, self).__init__(*args)
1334 LLDBTestResult.__singleton__ = self
1335 # Now put this singleton into the lldb module namespace.
1336 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001337 # Computes the format string for displaying the counter.
1338 global suite
1339 counterWidth = len(str(suite.countTestCases()))
1340 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001341 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001342 # This counts from 1 .. suite.countTestCases().
1343 self.counter = 0
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001344 (width, height) = LLDBTestResult.getTerminalSize()
1345 if width > 10:
1346 self.progressbar = progress.AnimatedProgressBar(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10)
Johnny Chen810042e2011-01-05 20:24:11 +00001347
Johnny Chenbe452272012-04-19 21:33:55 +00001348 def _exc_info_to_string(self, err, test):
1349 """Overrides superclass TestResult's method in order to append
1350 our test config info string to the exception info string."""
1351 modified_exc_string = '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1352 test.getArchitecture(),
1353 test.getCompiler())
1354 return modified_exc_string
1355
Johnny Chenc87fd492011-01-05 22:50:11 +00001356 def getDescription(self, test):
1357 doc_first_line = test.shortDescription()
1358 if self.descriptions and doc_first_line:
1359 return '\n'.join((str(test), self.indentation + doc_first_line))
1360 else:
1361 return str(test)
1362
Enrico Granataac3a8e22012-09-21 19:10:53 +00001363 def getCategoriesForTest(self,test):
1364 if hasattr(test,"getCategories"):
1365 test_categories = test.getCategories()
1366 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1367 test_categories = test.__self__.getCategories()
1368 else:
1369 test_categories = []
1370 if test_categories == None:
1371 test_categories = []
1372 return test_categories
1373
1374 def shouldSkipBecauseOfCategories(self,test):
1375 global useCategories
1376 import inspect
1377 if useCategories:
1378 global categoriesList
1379 test_categories = self.getCategoriesForTest(test)
1380 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
1381 return True
1382 return False
1383
1384 def hardMarkAsSkipped(self,test):
1385 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1386 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1387
Johnny Chen810042e2011-01-05 20:24:11 +00001388 def startTest(self, test):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001389 if self.shouldSkipBecauseOfCategories(test):
1390 self.hardMarkAsSkipped(test)
Johnny Chen810042e2011-01-05 20:24:11 +00001391 self.counter += 1
1392 if self.showAll:
1393 self.stream.write(self.fmt % self.counter)
1394 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001395
Johnny Chence681462010-10-19 00:25:01 +00001396 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001397 global sdir_has_content
1398 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001399 super(LLDBTestResult, self).addError(test, err)
1400 method = getattr(test, "markError", None)
1401 if method:
1402 method()
1403
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001404 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001405 global sdir_has_content
Enrico Granataac3a8e22012-09-21 19:10:53 +00001406 global failuresPerCategory
Johnny Chen63c2cba2010-10-29 22:20:36 +00001407 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001408 super(LLDBTestResult, self).addFailure(test, err)
1409 method = getattr(test, "markFailure", None)
1410 if method:
1411 method()
Enrico Granataac3a8e22012-09-21 19:10:53 +00001412 if useCategories:
1413 test_categories = self.getCategoriesForTest(test)
1414 for category in test_categories:
1415 if category in failuresPerCategory:
1416 failuresPerCategory[category] = failuresPerCategory[category] + 1
1417 else:
1418 failuresPerCategory[category] = 1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001419
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001420 def addExpectedFailure(self, test, err):
1421 global sdir_has_content
1422 sdir_has_content = True
1423 super(LLDBTestResult, self).addExpectedFailure(test, err)
1424 method = getattr(test, "markExpectedFailure", None)
1425 if method:
1426 method()
1427
Johnny Chenf5b89092011-08-15 23:09:08 +00001428 def addSkip(self, test, reason):
1429 global sdir_has_content
1430 sdir_has_content = True
1431 super(LLDBTestResult, self).addSkip(test, reason)
1432 method = getattr(test, "markSkippedTest", None)
1433 if method:
1434 method()
1435
Johnny Chenab2f0662011-05-06 20:30:22 +00001436 def addUnexpectedSuccess(self, test):
1437 global sdir_has_content
1438 sdir_has_content = True
1439 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1440 method = getattr(test, "markUnexpectedSuccess", None)
1441 if method:
1442 method()
1443
Johnny Chen26be4532010-11-09 23:56:14 +00001444 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001445 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001446 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001447 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001448 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001449 resultclass=LLDBTestResult).run(suite)
1450 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001451 # We are invoking the same test suite more than once. In this case,
1452 # mark __ignore_singleton__ flag as True so the signleton pattern is
1453 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001454 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001455 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +00001456 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001457 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001458 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001459 resultclass=LLDBTestResult).run(suite)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001460
Johnny Chen1bfbd412010-06-29 19:44:16 +00001461
Johnny Chen63c2cba2010-10-29 22:20:36 +00001462if sdir_has_content:
Johnny Chenab2f0662011-05-06 20:30:22 +00001463 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1464 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001465
Enrico Granataac3a8e22012-09-21 19:10:53 +00001466if useCategories and len(failuresPerCategory) > 0:
1467 sys.stderr.write("Failures per category:\n")
1468 for category in failuresPerCategory:
1469 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
1470
Johnny Chena73ad662012-08-16 19:15:21 +00001471fname = os.path.join(sdir_name, "TestFinished")
1472with open(fname, "w") as f:
1473 print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1474
Johnny Chencd0279d2010-09-20 18:07:50 +00001475# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1476# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001477if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001478 print "Terminating Test suite..."
1479 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1480
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001481# Exiting.
Daniel Malea2777b012013-02-06 16:55:07 +00001482sys.exit(not result.wasSuccessful())