blob: 0330a3585cdc6e598ed0e460a0e9694fcd39272b [file] [log] [blame]
Johnny Chen9707bb62010-06-25 21:14:08 +00001#!/usr/bin/env python
2
3"""
4A simple testing framework for lldb using python's unit testing framework.
5
6Tests for lldb are written as python scripts which take advantage of the script
7bridging provided by LLDB.framework to interact with lldb core.
8
9A specific naming pattern is followed by the .py script to be recognized as
10a module which implements a test scenario, namely, Test*.py.
11
12To specify the directories where "Test*.py" python test scripts are located,
13you need to pass in a list of directory names. By default, the current
14working directory is searched if nothing is specified on the command line.
Johnny Chen872aee12010-09-16 15:44:23 +000015
16Type:
17
18./dotest.py -h
19
20for available options.
Johnny Chen9707bb62010-06-25 21:14:08 +000021"""
22
Greg Clayton4793e942012-09-04 15:42:49 +000023import argparse
24import os
25import platform
26import signal
Johnny Chen2891bb02011-09-16 01:04:26 +000027import subprocess
Greg Clayton4793e942012-09-04 15:42:49 +000028import sys
29import textwrap
30import time
Johnny Chen75e28f92010-08-05 23:42:46 +000031import unittest2
Johnny Chen9707bb62010-06-25 21:14:08 +000032
Johnny Chen26901c82011-03-11 19:47:23 +000033def is_exe(fpath):
Johnny Chenf2c7b282011-04-26 23:10:51 +000034 """Returns true if fpath is an executable."""
Johnny Chen26901c82011-03-11 19:47:23 +000035 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
36
Johnny Chen26901c82011-03-11 19:47:23 +000037def which(program):
Johnny Chenf2c7b282011-04-26 23:10:51 +000038 """Returns the full path to a program; None otherwise."""
Johnny Chen26901c82011-03-11 19:47:23 +000039 fpath, fname = os.path.split(program)
40 if fpath:
41 if is_exe(program):
42 return program
43 else:
44 for path in os.environ["PATH"].split(os.pathsep):
45 exe_file = os.path.join(path, program)
46 if is_exe(exe_file):
47 return exe_file
48 return None
49
Johnny Chen877c7e42010-08-07 00:16:07 +000050class _WritelnDecorator(object):
51 """Used to decorate file-like objects with a handy 'writeln' method"""
52 def __init__(self,stream):
53 self.stream = stream
54
55 def __getattr__(self, attr):
56 if attr in ('stream', '__getstate__'):
57 raise AttributeError(attr)
58 return getattr(self.stream,attr)
59
60 def writeln(self, arg=None):
61 if arg:
62 self.write(arg)
63 self.write('\n') # text-mode streams translate to \r\n if needed
64
Johnny Chen9707bb62010-06-25 21:14:08 +000065#
66# Global variables:
67#
68
Enrico Granataac3a8e22012-09-21 19:10:53 +000069# Dictionary of categories
70# When you define a new category for your testcases, be sure to add it here, or the test suite
71# will gladly complain as soon as you try to use it. This allows us to centralize which categories
72# exist, and to provide a description for each one
73validCategories = {
74'dataformatters':'Tests related to the type command and the data formatters subsystem',
75'expression':'Tests related to the expression parser',
76'objc':'Tests related to the Objective-C programming language support',
77'pyapi':'Tests related to the Python API'
78}
79
Johnny Chen9707bb62010-06-25 21:14:08 +000080# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +000081suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +000082
Johnny Chen4f93bf12010-12-10 00:51:23 +000083# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +000084# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
85# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +000086dont_do_python_api_test = False
87
88# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +000089just_do_python_api_test = False
90
Johnny Chen82ccf402011-07-30 01:39:58 +000091# By default, benchmarks tests are not run.
92just_do_benchmarks_test = False
93
Johnny Chena3ed7d82012-04-06 00:56:05 +000094# By default, both dsym and dwarf tests are performed.
95# Use @dsym_test or @dwarf_test decorators, defined in lldbtest.py, to mark a test
96# as a dsym or dwarf test. Use '-N dsym' or '-N dwarf' to exclude dsym or dwarf
97# tests from running.
Daniel Maleab8106282012-11-20 16:07:33 +000098dont_do_dsym_test = "linux" in sys.platform
Johnny Chena3ed7d82012-04-06 00:56:05 +000099dont_do_dwarf_test = False
100
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000101# The blacklist is optional (-b blacklistFile) and allows a central place to skip
102# testclass's and/or testclass.testmethod's.
103blacklist = None
104
105# The dictionary as a result of sourcing blacklistFile.
106blacklistConfig = {}
107
Enrico Granataac3a8e22012-09-21 19:10:53 +0000108# The list of categories we said we care about
109categoriesList = None
110# set to true if we are going to use categories for cherry-picking test cases
111useCategories = False
112# use this to track per-category failures
113failuresPerCategory = {}
114
Sean Callanan0acf4c62012-10-24 22:45:39 +0000115# The path to LLDB.framework is optional.
116lldbFrameworkPath = None
117
118# The path to lldb is optional
119lldbExecutablePath = None
120
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000121# The config file is optional.
122configFile = None
123
Johnny Chend2acdb32010-11-16 22:42:58 +0000124# Test suite repeat count. Can be overwritten with '-# count'.
125count = 1
126
Johnny Chenb40056b2010-09-21 00:09:27 +0000127# The dictionary as a result of sourcing configFile.
128config = {}
Johnny Chenac97a6b2012-04-16 18:55:15 +0000129# The pre_flight and post_flight functions come from reading a config file.
130pre_flight = None
131post_flight = None
Johnny Chenb40056b2010-09-21 00:09:27 +0000132
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000133# The 'archs' and 'compilers' can be specified via either command line or configFile,
Greg Clayton4793e942012-09-04 15:42:49 +0000134# with the command line overriding the configFile. The corresponding options can be
135# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386']
136# and "-C gcc -C clang" => compilers=['gcc', 'clang'].
137archs = None # Must be initialized after option parsing
138compilers = None # Must be initialized after option parsing
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000139
Johnny Chen1abe4c02012-03-20 00:33:51 +0000140# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
141# the inferior programs. The global variable cflags_extras provides a hook to do
142# just that.
143cflags_extras = ''
144
Johnny Chen91960d32010-09-08 20:56:16 +0000145# Delay startup in order for the debugger to attach.
146delay = False
147
Johnny Chend5362332011-01-29 01:21:04 +0000148# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000149dumpSysPath = False
150
Johnny Chene00c9302011-10-10 22:03:44 +0000151# Full path of the benchmark executable, as specified by the '-e' option.
152bmExecutable = None
153# The breakpoint specification of bmExecutable, as specified by the '-x' option.
154bmBreakpointSpec = None
Johnny Chen5f2ed172011-10-20 18:43:28 +0000155# The benchamrk iteration count, as specified by the '-y' option.
156bmIterationCount = -1
Johnny Chene00c9302011-10-10 22:03:44 +0000157
Johnny Chene9eae812012-01-18 05:15:00 +0000158# By default, don't exclude any directories. Use '-X' to add one excluded directory.
159excluded = set(['.svn', '.git'])
160
Johnny Chen7d6d8442010-12-03 19:59:35 +0000161# By default, failfast is False. Use '-F' to overwrite it.
162failfast = False
163
Johnny Chenc5fa0052011-07-29 22:54:56 +0000164# The filters (testclass.testmethod) used to admit tests into our test suite.
165filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000166
Johnny Chen38f823c2011-10-11 01:30:27 +0000167# The runhooks is a list of lldb commands specifically for the debugger.
168# Use '-k' to specify a runhook.
169runHooks = []
170
Johnny Chena224cd12010-11-08 01:21:03 +0000171# If '-g' is specified, the filterspec is not exclusive. If a test module does
172# not contain testclass.testmethod which matches the filterspec, the whole test
173# module is still admitted into our test suite. fs4all flag defaults to True.
174fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000175
Johnny Chenaf149a02010-09-16 17:11:30 +0000176# Ignore the build search path relative to this script to locate the lldb.py module.
177ignore = False
178
Johnny Chen028d8eb2011-11-17 19:57:27 +0000179# By default, we do not skip build and cleanup. Use '-S' option to override.
180skip_build_and_cleanup = False
181
Johnny Chen548aefd2010-10-11 22:25:46 +0000182# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000183skip_long_running_test = True
Johnny Chen41998192010-10-01 22:59:49 +0000184
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000185# By default, we print the build dir, lldb version, and svn info. Use '-n' option to
186# turn it off.
187noHeaders = False
188
Johnny Chen7c52ff12010-09-27 23:29:54 +0000189# The regular expression pattern to match against eligible filenames as our test cases.
190regexp = None
191
Johnny Chen548aefd2010-10-11 22:25:46 +0000192# By default, tests are executed in place and cleanups are performed afterwards.
193# Use '-r dir' option to relocate the tests and their intermediate files to a
194# different directory and to forgo any cleanups. The directory specified must
195# not exist yet.
196rdir = None
197
Johnny Chen125fc2b2010-10-21 16:55:35 +0000198# By default, recorded session info for errored/failed test are dumped into its
199# own file under a session directory named after the timestamp of the test suite
200# run. Use '-s session-dir-name' to specify a specific dir name.
201sdir_name = None
202
Johnny Chen63c2cba2010-10-29 22:20:36 +0000203# Set this flag if there is any session info dumped during the test run.
204sdir_has_content = False
205
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000206# svn_info stores the output from 'svn info lldb.base.dir'.
207svn_info = ''
208
Johnny Chen9707bb62010-06-25 21:14:08 +0000209# Default verbosity is 0.
210verbose = 0
211
Johnny Chen08967192011-11-18 00:19:29 +0000212# Set to True only if verbose is 0 and LLDB trace mode is off.
213progress_bar = False
214
Peter Collingbourne61aca482011-06-20 19:06:29 +0000215# By default, search from the script directory.
216testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000217
Johnny Chen877c7e42010-08-07 00:16:07 +0000218# Separator string.
219separator = '-' * 70
220
Johnny Chen9707bb62010-06-25 21:14:08 +0000221
Greg Clayton4793e942012-09-04 15:42:49 +0000222def usage(parser):
223 parser.print_help()
Jim Ingham4f347cb2011-04-13 21:11:41 +0000224 if verbose > 0:
225 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000226Examples:
227
Johnny Chena224cd12010-11-08 01:21:03 +0000228This is an example of using the -f option to pinpoint to a specfic test class
229and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000230
Johnny Chena224cd12010-11-08 01:21:03 +0000231$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000232----------------------------------------------------------------------
233Collected 1 test
234
235test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
236Test 'frame variable this' when stopped on a class constructor. ... ok
237
238----------------------------------------------------------------------
239Ran 1 test in 1.396s
240
241OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000242
243And this is an example of using the -p option to run a single file (the filename
244matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
245
246$ ./dotest.py -v -p ObjC
247----------------------------------------------------------------------
248Collected 4 tests
249
250test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000251Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000252test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000253Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000254test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
255Lookup objective-c data types and evaluate expressions. ... ok
256test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
257Lookup objective-c data types and evaluate expressions. ... ok
258
259----------------------------------------------------------------------
260Ran 4 tests in 16.661s
261
262OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000263
Johnny Chen58f93922010-06-29 23:10:39 +0000264Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000265individual test cases can locate their supporting files correctly. The script
266tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000267relative to this script. See also the '-i' option in the following example.
268
269Finally, this is an example of using the lldb.py module distributed/installed by
270Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
271option to add some delay between two tests. It uses ARCH=x86_64 to specify that
272as the architecture and CC=clang to specify the compiler used for the test run:
273
274$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
275
276Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
277----------------------------------------------------------------------
278Collected 2 tests
279
280test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
281Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
282test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
283Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
284
285----------------------------------------------------------------------
286Ran 2 tests in 5.659s
287
288OK
289
290The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
291notify the directory containing the session logs for test failures or errors.
292In case there is any test failure/error, a similar message is appended at the
293end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000294
295Environment variables related to loggings:
296
297o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
298 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
299
300o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
301 'process.gdb-remote' subsystem with a default option of 'packets' if
302 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000303"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000304 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000305
306
Johnny Chenaf149a02010-09-16 17:11:30 +0000307def parseOptionsAndInitTestdirs():
308 """Initialize the list of directories containing our unittest scripts.
309
310 '-h/--help as the first option prints out usage info and exit the program.
311 """
312
Johnny Chen4f93bf12010-12-10 00:51:23 +0000313 global dont_do_python_api_test
314 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000315 global just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +0000316 global dont_do_dsym_test
317 global dont_do_dwarf_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000318 global blacklist
319 global blacklistConfig
Enrico Granataac3a8e22012-09-21 19:10:53 +0000320 global categoriesList
321 global validCategories
322 global useCategories
Sean Callanan0acf4c62012-10-24 22:45:39 +0000323 global lldbFrameworkPath
324 global lldbExecutablePath
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000325 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000326 global archs
327 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000328 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000329 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000330 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000331 global bmExecutable
332 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000333 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000334 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000335 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000336 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000337 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000338 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000339 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000340 global skip_build_and_cleanup
341 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000342 global noHeaders
Johnny Chen7c52ff12010-09-27 23:29:54 +0000343 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000344 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000345 global sdir_name
Johnny Chenaf149a02010-09-16 17:11:30 +0000346 global verbose
347 global testdirs
348
Jim Ingham4f347cb2011-04-13 21:11:41 +0000349 do_help = False
350
Greg Clayton4793e942012-09-04 15:42:49 +0000351 parser = argparse.ArgumentParser(description='description', prefix_chars='+-', add_help=False)
352 group = None
Johnny Chenaf149a02010-09-16 17:11:30 +0000353
Greg Clayton4793e942012-09-04 15:42:49 +0000354 # Helper function for boolean options (group will point to the current group when executing X)
355 X = lambda optstr, helpstr, **kwargs: group.add_argument(optstr, help=helpstr, action='store_true', **kwargs)
356
357 group = parser.add_argument_group('Help')
358 group.add_argument('-h', '--help', dest='h', action='store_true', help="Print this help message and exit. Add '-v' for more detailed help.")
359
360 # C and Python toolchain options
361 group = parser.add_argument_group('Toolchain options')
362 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'''))
363 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.'''))
364 # FIXME? This won't work for different extra flags according to each arch.
365 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
366 suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
367 X('-D', 'Dump the Python sys.path variable')
368
369 # Test filtering options
370 group = parser.add_argument_group('Test filtering options')
371 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")
372 X('-a', "Don't do lldb Python API tests")
373 X('+a', "Just do lldb Python API tests. Do not specify along with '+a'", dest='plus_a')
374 X('+b', 'Just do benchmark tests', dest='plus_b')
375 group.add_argument('-b', metavar='blacklist', help='Read a blacklist file specified after this option')
Enrico Granata58b03a42012-12-14 00:07:09 +0000376 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 +0000377 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')
378 X('-l', "Don't skip long running tests")
379 group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite')
380 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 +0000381 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 +0000382
383 # Configuration options
384 group = parser.add_argument_group('Configuration options')
385 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 +0000386 group.add_argument('--framework', metavar='framework-path', help='The path to LLDB.framework')
387 group.add_argument('--executable', metavar='executable-path', help='The path to the lldb executable')
Greg Clayton4793e942012-09-04 15:42:49 +0000388 group.add_argument('-e', metavar='benchmark-exe', help='Specify the full path of an executable used for benchmark purposes (see also: -x)')
389 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")
390 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')
391 group.add_argument('-r', metavar='dir', help="Similar to '-R', except that the directory must not exist before running this test driver")
392 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')
393 group.add_argument('-x', metavar='breakpoint-spec', help='Specify the breakpoint specification for the benchmark executable')
394 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.")
395 group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times')
396
397 # Test-suite behaviour
398 group = parser.add_argument_group('Runtime behaviour options')
399 X('-d', 'Delay startup for 10 seconds (in order for the debugger to attach)')
400 X('-F', 'Fail fast. Stop the test suite on the first error/failure')
401 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")
402 X('-n', "Don't print the headers like build dir, lldb version, and svn info at all")
403 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")
404 X('-t', 'Turn on tracing of lldb command and other detailed test executions')
Greg Claytonb85785c2013-02-08 21:52:32 +0000405 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 +0000406 X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
407 X('-w', 'Insert some wait time (currently 0.5 sec) between consecutive test cases')
408
409 # Remove the reference to our helper function
410 del X
411
412 group = parser.add_argument_group('Test directories')
413 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.')
414 args = parser.parse_args()
415
416 platform_system = platform.system()
417 platform_machine = platform.machine()
Enrico Granata2d329242012-10-23 22:52:49 +0000418
Greg Claytonb85785c2013-02-08 21:52:32 +0000419 if args.unset_env_varnames:
420 for env_var in args.unset_env_varnames:
421 if env_var in os.environ:
422 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
423 # is automatically translated into a corresponding call to unsetenv().
424 del os.environ[env_var]
425 #os.unsetenv(env_var)
426
Enrico Granata2d329242012-10-23 22:52:49 +0000427 # only print the args if being verbose
428 if args.v:
429 print args
Greg Clayton4793e942012-09-04 15:42:49 +0000430
431 if args.h:
432 do_help = True
433
434 if args.archs:
435 archs = args.archs
436 else:
437 if platform_system == 'Darwin' and platform_machine == 'x86_64':
438 archs = ['x86_64', 'i386']
Johnny Chenaf149a02010-09-16 17:11:30 +0000439 else:
Greg Clayton4793e942012-09-04 15:42:49 +0000440 archs = [platform_machine]
441
Enrico Granataac3a8e22012-09-21 19:10:53 +0000442 if args.categoriesList:
443 for category in args.categoriesList:
444 if not(category in validCategories):
Enrico Granata2d329242012-10-23 22:52:49 +0000445 print "fatal error: category '" + category + "' is not a valid category"
446 print "if you have added a new category, please edit dotest.py, adding your new category to validCategories"
447 print "else, please specify one or more of the following: " + str(validCategories.keys())
Enrico Granataac3a8e22012-09-21 19:10:53 +0000448 sys.exit(1)
449 categoriesList = set(args.categoriesList)
450 useCategories = True
451 else:
452 categoriesList = []
453
Greg Clayton4793e942012-09-04 15:42:49 +0000454 if args.compilers:
455 compilers = args.compilers
456 else:
457 compilers = ['clang']
458
459 if args.D:
460 dumpSysPath = True
461
462 if args.E:
463 cflags_extras = args.E
464 os.environ['CFLAGS_EXTRAS'] = cflags_extras
465
466 # argparse makes sure we have correct options
467 if args.N == 'dwarf':
468 dont_do_dwarf_test = True
469 elif args.N == 'dsym':
470 dont_do_dsym_test = True
471
472 if args.a:
473 dont_do_python_api_test = True
474
475 if args.plus_a:
476 if dont_do_python_api_test:
477 print "Warning: -a and +a can't both be specified! Using only -a"
478 else:
479 just_do_python_api_test = True
480
481 if args.plus_b:
482 just_do_benchmarks_test = True
483
484 if args.b:
485 if args.b.startswith('-'):
486 usage(parser)
487 blacklistFile = args.b
488 if not os.path.isfile(blacklistFile):
489 print 'Blacklist file:', blacklistFile, 'does not exist!'
490 usage(parser)
491 # Now read the blacklist contents and assign it to blacklist.
492 execfile(blacklistFile, globals(), blacklistConfig)
493 blacklist = blacklistConfig.get('blacklist')
494
495 if args.c:
496 if args.c.startswith('-'):
497 usage(parser)
498 configFile = args.c
499 if not os.path.isfile(configFile):
500 print 'Config file:', configFile, 'does not exist!'
501 usage(parser)
502
503 if args.d:
504 delay = True
505
506 if args.e:
507 if args.e.startswith('-'):
508 usage(parser)
509 bmExecutable = args.e
510 if not is_exe(bmExecutable):
511 usage(parser)
512
513 if args.F:
514 failfast = True
515
516 if args.f:
Enrico Granata58b03a42012-12-14 00:07:09 +0000517 if any([x.startswith('-') for x in args.f]):
Greg Clayton4793e942012-09-04 15:42:49 +0000518 usage(parser)
Enrico Granata58b03a42012-12-14 00:07:09 +0000519 filters.extend(args.f)
Greg Clayton4793e942012-09-04 15:42:49 +0000520
521 if args.g:
522 fs4all = False
523
524 if args.i:
525 ignore = True
526
527 if args.k:
528 runHooks.extend(args.k)
529
530 if args.l:
531 skip_long_running_test = False
532
Sean Callanan0acf4c62012-10-24 22:45:39 +0000533 if args.framework:
534 lldbFrameworkPath = args.framework
535
536 if args.executable:
537 lldbExecutablePath = args.executable
538
Greg Clayton4793e942012-09-04 15:42:49 +0000539 if args.n:
540 noHeaders = True
541
542 if args.p:
543 if args.p.startswith('-'):
544 usage(parser)
545 regexp = args.p
546
547 if args.R:
548 if args.R.startswith('-'):
549 usage(parser)
550 rdir = os.path.abspath(args.R)
551 if os.path.exists(rdir):
552 import shutil
553 print 'Removing tree:', rdir
554 shutil.rmtree(rdir)
555
556 if args.r:
557 if args.r.startswith('-'):
558 usage(parser)
559 rdir = os.path.abspath(args.r)
560 if os.path.exists(rdir):
561 print 'Relocated directory:', rdir, 'must not exist!'
562 usage(parser)
563
564 if args.S:
565 skip_build_and_cleanup = True
566
567 if args.s:
568 if args.s.startswith('-'):
569 usage(parser)
570 sdir_name = args.s
571
572 if args.t:
573 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
574
Greg Clayton4793e942012-09-04 15:42:49 +0000575 if args.v:
576 verbose = 2
577
578 if args.w:
579 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
580
581 if args.X:
582 if args.X.startswith('-'):
583 usage(parser)
584 excluded.add(args.X)
585
586 if args.x:
587 if args.x.startswith('-'):
588 usage(parser)
589 bmBreakpointSpec = args.x
590
591 # argparse makes sure we have a number
592 if args.y:
593 bmIterationCount = args.y
594
595 # argparse makes sure we have a number
596 if args.sharp:
597 count = args.sharp
Johnny Chenaf149a02010-09-16 17:11:30 +0000598
Jim Ingham4f347cb2011-04-13 21:11:41 +0000599 if do_help == True:
Greg Clayton4793e942012-09-04 15:42:49 +0000600 usage(parser)
Jim Ingham4f347cb2011-04-13 21:11:41 +0000601
Johnny Chencc659ad2010-12-10 19:02:23 +0000602 # Do not specify both '-a' and '+a' at the same time.
603 if dont_do_python_api_test and just_do_python_api_test:
Greg Clayton4793e942012-09-04 15:42:49 +0000604 usage(parser)
Johnny Chencc659ad2010-12-10 19:02:23 +0000605
Johnny Chen08967192011-11-18 00:19:29 +0000606 # 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 +0000607 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 +0000608 progress_bar = True
609
Johnny Chenaf149a02010-09-16 17:11:30 +0000610 # Gather all the dirs passed on the command line.
Greg Clayton4793e942012-09-04 15:42:49 +0000611 if len(args.args) > 0:
612 testdirs = map(os.path.abspath, args.args)
Johnny Chenaf149a02010-09-16 17:11:30 +0000613
Johnny Chen548aefd2010-10-11 22:25:46 +0000614 # If '-r dir' is specified, the tests should be run under the relocated
615 # directory. Let's copy the testdirs over.
616 if rdir:
617 from shutil import copytree, ignore_patterns
618
619 tmpdirs = []
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000620 orig_testdirs = testdirs[:]
Johnny Chen548aefd2010-10-11 22:25:46 +0000621 for srcdir in testdirs:
Johnny Chen1abe4c02012-03-20 00:33:51 +0000622 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
623 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
624 # Utilize the relative path to the 'test' directory to make our destination dir path.
Greg Clayton4793e942012-09-04 15:42:49 +0000625 if ("test" + os.sep) in srcdir:
626 to_split_on = "test" + os.sep
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000627 else:
628 to_split_on = "test"
629 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
630 dstdir = dstdir.rstrip(os.sep)
Johnny Chen548aefd2010-10-11 22:25:46 +0000631 # Don't copy the *.pyc and .svn stuffs.
632 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
633 tmpdirs.append(dstdir)
634
635 # This will be our modified testdirs.
636 testdirs = tmpdirs
637
638 # With '-r dir' specified, there's no cleanup of intermediate test files.
639 os.environ["LLDB_DO_CLEANUP"] = 'NO'
640
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000641 # If the original testdirs is ['test'], the make directory has already been copied
Johnny Chen548aefd2010-10-11 22:25:46 +0000642 # recursively and is contained within the rdir/test dir. For anything
643 # else, we would need to copy over the make directory and its contents,
644 # so that, os.listdir(rdir) looks like, for example:
645 #
646 # array_types conditional_break make
647 #
648 # where the make directory contains the Makefile.rules file.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000649 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000650 scriptdir = os.path.dirname(__file__)
Johnny Chen548aefd2010-10-11 22:25:46 +0000651 # Don't copy the .svn stuffs.
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000652 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
Johnny Chen548aefd2010-10-11 22:25:46 +0000653 ignore=ignore_patterns('.svn'))
654
655 #print "testdirs:", testdirs
656
Johnny Chenb40056b2010-09-21 00:09:27 +0000657 # Source the configFile if specified.
658 # The side effect, if any, will be felt from this point on. An example
659 # config file may be these simple two lines:
660 #
661 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
662 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
663 #
664 # which will reassign the two file objects to sys.stderr and sys.stdout,
665 # respectively.
666 #
Johnny Chen8c130642012-08-22 17:53:02 +0000667 # See also lldb-trunk/examples/test/usage-config.
Johnny Chenac97a6b2012-04-16 18:55:15 +0000668 global config, pre_flight, post_flight
Johnny Chenb40056b2010-09-21 00:09:27 +0000669 if configFile:
670 # Pass config (a dictionary) as the locals namespace for side-effect.
671 execfile(configFile, globals(), config)
Johnny Chenac97a6b2012-04-16 18:55:15 +0000672 print "config:", config
673 if "pre_flight" in config:
674 pre_flight = config["pre_flight"]
675 if not callable(pre_flight):
676 print "fatal error: pre_flight is not callable, exiting."
677 sys.exit(1)
678 if "post_flight" in config:
679 post_flight = config["post_flight"]
680 if not callable(post_flight):
681 print "fatal error: post_flight is not callable, exiting."
682 sys.exit(1)
Johnny Chenb40056b2010-09-21 00:09:27 +0000683 #print "sys.stderr:", sys.stderr
684 #print "sys.stdout:", sys.stdout
685
Johnny Chenaf149a02010-09-16 17:11:30 +0000686
Johnny Chen9707bb62010-06-25 21:14:08 +0000687def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000688 """
689 Add LLDB.framework/Resources/Python to the search paths for modules.
690 As a side effect, we also discover the 'lldb' executable and export it here.
691 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000692
Johnny Chen548aefd2010-10-11 22:25:46 +0000693 global rdir
694 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000695 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000696 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000697 global svn_info
Sean Callanan0acf4c62012-10-24 22:45:39 +0000698 global lldbFrameworkPath
699 global lldbExecutablePath
Johnny Chen548aefd2010-10-11 22:25:46 +0000700
Johnny Chen9707bb62010-06-25 21:14:08 +0000701 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000702 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 +0000703 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
704 else:
705 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000706 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000707 print "This script expects to reside in lldb's test directory."
708 sys.exit(-1)
709
Johnny Chen548aefd2010-10-11 22:25:46 +0000710 if rdir:
711 # Set up the LLDB_TEST environment variable appropriately, so that the
712 # individual tests can be located relatively.
713 #
714 # See also lldbtest.TestBase.setUpClass(cls).
715 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
716 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
717 else:
718 os.environ["LLDB_TEST"] = rdir
719 else:
720 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000721
722 # Set up the LLDB_SRC environment variable, so that the tests can locate
723 # the LLDB source code.
724 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
725
Johnny Chen9de4ede2010-08-31 17:42:54 +0000726 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000727 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000728
Johnny Chen8a3c0432011-03-11 20:13:06 +0000729 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000730 sys.path.append(scriptPath)
731 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000732 sys.path.append(pexpectPath)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000733
Johnny Chen26901c82011-03-11 19:47:23 +0000734 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000735 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000736
Johnny Chen26901c82011-03-11 19:47:23 +0000737 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000738 xcode3_build_dir = ['build']
739 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
740 dbg = ['Debug']
Sean Callanand9d94632012-09-26 21:16:15 +0000741 dbc = ['DebugClang']
Johnny Chen6a564a42011-02-15 18:50:19 +0000742 rel = ['Release']
743 bai = ['BuildAndIntegration']
744 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000745
746 # Some of the tests can invoke the 'lldb' command directly.
747 # We'll try to locate the appropriate executable right here.
748
Sean Callanan0acf4c62012-10-24 22:45:39 +0000749 lldbExec = None
750 if lldbExecutablePath:
751 if is_exe(lldbExecutablePath):
752 lldbExec = lldbExecutablePath
Sean Callanan502000d2012-11-01 21:23:21 +0000753 lldbHere = lldbExec
Sean Callanan0acf4c62012-10-24 22:45:39 +0000754 else:
755 print lldbExecutablePath + " is not an executable"
756 sys.exit(-1)
Johnny Chen6033bed2011-08-26 00:00:01 +0000757 else:
Sean Callanan0acf4c62012-10-24 22:45:39 +0000758 # First, you can define an environment variable LLDB_EXEC specifying the
759 # full pathname of the lldb executable.
760 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
761 lldbExec = os.environ["LLDB_EXEC"]
762 else:
763 lldbExec = None
764
765 executable = ['lldb']
766 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
767 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
768 dbcExec = os.path.join(base, *(xcode3_build_dir + dbc + executable))
769 dbcExec2 = os.path.join(base, *(xcode4_build_dir + dbc + executable))
770 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
771 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
772 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
773 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
774
775 # The 'lldb' executable built here in the source tree.
776 lldbHere = None
777 if is_exe(dbgExec):
778 lldbHere = dbgExec
779 elif is_exe(dbgExec2):
780 lldbHere = dbgExec2
781 elif is_exe(dbcExec):
782 lldbHere = dbcExec
783 elif is_exe(dbcExec2):
784 lldbHere = dbcExec2
785 elif is_exe(relExec):
786 lldbHere = relExec
787 elif is_exe(relExec2):
788 lldbHere = relExec2
789 elif is_exe(baiExec):
790 lldbHere = baiExec
791 elif is_exe(baiExec2):
792 lldbHere = baiExec2
793 elif lldbExec:
794 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000795
Sean Callanan0acf4c62012-10-24 22:45:39 +0000796 # One last chance to locate the 'lldb' executable.
797 if not lldbExec:
798 lldbExec = which('lldb')
799 if lldbHere and not lldbExec:
800 lldbExec = lldbHere
Daniel Malea2777b012013-02-06 16:55:07 +0000801 if lldbExec and not lldbHere:
802 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000803
804 if lldbHere:
805 os.environ["LLDB_HERE"] = lldbHere
806 os.environ["LLDB_BUILD_DIR"] = os.path.split(lldbHere)[0]
807 if not noHeaders:
808 print "LLDB build dir:", os.environ["LLDB_BUILD_DIR"]
809 os.system('%s -v' % lldbHere)
Johnny Chen26901c82011-03-11 19:47:23 +0000810
811 if not lldbExec:
812 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
813 else:
814 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000815 #print "The 'lldb' from PATH env variable", lldbExec
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000816
Johnny Chenb264c9b2011-06-24 22:52:05 +0000817 if os.path.isdir(os.path.join(base, '.svn')):
818 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
819 svn_info = pipe.stdout.read()
820 elif os.path.isdir(os.path.join(base, '.git')):
821 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
822 svn_info = pipe.stdout.read()
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000823 if not noHeaders:
824 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000825
826 global ignore
827
Johnny Chen9707bb62010-06-25 21:14:08 +0000828 lldbPath = None
Sean Callanan0acf4c62012-10-24 22:45:39 +0000829 if lldbFrameworkPath:
830 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python')
831 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
832 lldbPath = candidatePath
833 if not lldbPath:
834 print 'Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath
835 sys.exit(-1)
836 else:
837 # The '-i' option is used to skip looking for lldb.py in the build tree.
838 if ignore:
839 return
Jim Inghamaa93c932012-12-21 22:22:26 +0000840
841 # If our lldb supports the -P option, use it to find the python path:
842 init_in_python_dir = 'lldb/__init__.py'
843 import pexpect
844 lldb_dash_p_result = None
845
846 if lldbHere:
847 lldb_dash_p_result = pexpect.run("%s -P"%(lldbHere))
848 elif lldbExec:
849 lldb_dash_p_result = pexpect.run("%s -P"%(lldbExec))
850
851 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")):
852 lines = lldb_dash_p_result.splitlines()
853 if len(lines) == 1 and os.path.isfile(os.path.join(lines[0], init_in_python_dir)):
854 lldbPath = lines[0]
Daniel Malea21e32a62013-01-04 23:35:13 +0000855 if "linux" in sys.platform:
856 os.environ['LLDB_BUILD_DIR'] = os.path.join(lldbPath, 'lldb')
Jim Inghamaa93c932012-12-21 22:22:26 +0000857
858 if not lldbPath:
859 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
860 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
861 dbcPath = os.path.join(base, *(xcode3_build_dir + dbc + python_resource_dir))
862 dbcPath2 = os.path.join(base, *(xcode4_build_dir + dbc + python_resource_dir))
863 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
864 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
865 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
866 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Sean Callanan0acf4c62012-10-24 22:45:39 +0000867
Jim Inghamaa93c932012-12-21 22:22:26 +0000868 if os.path.isfile(os.path.join(dbgPath, init_in_python_dir)):
869 lldbPath = dbgPath
870 elif os.path.isfile(os.path.join(dbgPath2, init_in_python_dir)):
871 lldbPath = dbgPath2
872 elif os.path.isfile(os.path.join(dbcPath, init_in_python_dir)):
873 lldbPath = dbcPath
874 elif os.path.isfile(os.path.join(dbcPath2, init_in_python_dir)):
875 lldbPath = dbcPath2
876 elif os.path.isfile(os.path.join(relPath, init_in_python_dir)):
877 lldbPath = relPath
878 elif os.path.isfile(os.path.join(relPath2, init_in_python_dir)):
879 lldbPath = relPath2
880 elif os.path.isfile(os.path.join(baiPath, init_in_python_dir)):
881 lldbPath = baiPath
882 elif os.path.isfile(os.path.join(baiPath2, init_in_python_dir)):
883 lldbPath = baiPath2
884
Sean Callanan0acf4c62012-10-24 22:45:39 +0000885 if not lldbPath:
886 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
887 print relPath + ', or ' + baiPath
888 sys.exit(-1)
Johnny Chen9707bb62010-06-25 21:14:08 +0000889
Jim Inghamaa93c932012-12-21 22:22:26 +0000890 # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
891 # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
892 (before, frameWithVersion, after) = lldbPath.rpartition("LLDB.framework/Versions/A")
893 if frameWithVersion != "" :
894 lldbPath = before + "LLDB.framework" + after
895
Enrico Granata01458ca2012-10-23 00:09:02 +0000896 # If tests need to find LLDB_FRAMEWORK, now they can do it
897 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPath))
898
Johnny Chenaf149a02010-09-16 17:11:30 +0000899 # This is to locate the lldb.py module. Insert it right after sys.path[0].
900 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000901 if dumpSysPath:
902 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000903
Johnny Chen9707bb62010-06-25 21:14:08 +0000904
Johnny Chencd0279d2010-09-20 18:07:50 +0000905def doDelay(delta):
906 """Delaying startup for delta-seconds to facilitate debugger attachment."""
907 def alarm_handler(*args):
908 raise Exception("timeout")
909
910 signal.signal(signal.SIGALRM, alarm_handler)
911 signal.alarm(delta)
912 sys.stdout.write("pid=%d\n" % os.getpid())
913 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
914 delta)
915 sys.stdout.flush()
916 try:
917 text = sys.stdin.readline()
918 except:
919 text = ""
920 signal.alarm(0)
921 sys.stdout.write("proceeding...\n")
922 pass
923
924
Johnny Chen9707bb62010-06-25 21:14:08 +0000925def visit(prefix, dir, names):
926 """Visitor function for os.path.walk(path, visit, arg)."""
927
928 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000929 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000930 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000931 global fs4all
Johnny Chene9eae812012-01-18 05:15:00 +0000932 global excluded
933
934 if set(dir.split(os.sep)).intersection(excluded):
935 #print "Detected an excluded dir component: %s" % dir
936 return
Johnny Chen9707bb62010-06-25 21:14:08 +0000937
938 for name in names:
939 if os.path.isdir(os.path.join(dir, name)):
940 continue
941
942 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000943 # Try to match the regexp pattern, if specified.
944 if regexp:
945 import re
946 if re.search(regexp, name):
947 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
948 pass
949 else:
950 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
951 continue
952
Johnny Chen953864a2010-10-12 21:35:54 +0000953 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000954
955 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000956 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000957 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000958 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000959
960 # Thoroughly check the filterspec against the base module and admit
961 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000962 filterspec = None
963 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000964 # Optimistically set the flag to True.
965 filtered = True
966 module = __import__(base)
967 parts = filterspec.split('.')
968 obj = module
969 for part in parts:
970 try:
971 parent, obj = obj, getattr(obj, part)
972 except AttributeError:
973 # The filterspec has failed.
974 filtered = False
975 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000976
Johnny Chendb4be602011-08-12 23:55:07 +0000977 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000978 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +0000979 #print "adding filter spec %s to module %s" % (filterspec, module)
980 suite.addTests(
981 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
982 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +0000983
984 # Forgo this module if the (base, filterspec) combo is invalid
985 # and no '-g' option is specified
986 if filters and fs4all and not filtered:
987 continue
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000988
Johnny Chendb4be602011-08-12 23:55:07 +0000989 # Add either the filtered test case(s) (which is done before) or the entire test class.
990 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +0000991 # A simple case of just the module name. Also the failover case
992 # from the filterspec branch when the (base, filterspec) combo
993 # doesn't make sense.
994 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000995
996
Johnny Chencd0279d2010-09-20 18:07:50 +0000997def lldbLoggings():
998 """Check and do lldb loggings if necessary."""
999
1000 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
1001 # defined. Use ${LLDB_LOG} to specify the log file.
1002 ci = lldb.DBG.GetCommandInterpreter()
1003 res = lldb.SBCommandReturnObject()
1004 if ("LLDB_LOG" in os.environ):
1005 if ("LLDB_LOG_OPTION" in os.environ):
1006 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
1007 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +00001008 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +00001009 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +00001010 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +00001011 res)
1012 if not res.Succeeded():
1013 raise Exception('log enable failed (check LLDB_LOG env variable.')
1014 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
1015 # Use ${GDB_REMOTE_LOG} to specify the log file.
1016 if ("GDB_REMOTE_LOG" in os.environ):
1017 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
1018 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
1019 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +00001020 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +00001021 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +00001022 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +00001023 + gdb_remote_log_option,
1024 res)
1025 if not res.Succeeded():
1026 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
1027
Johnny Chen067022b2011-01-19 19:31:46 +00001028def getMyCommandLine():
Johnny Chen067022b2011-01-19 19:31:46 +00001029 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
1030 lines = ps.split('\n')
1031 cmd_line = lines[1]
1032 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +00001033
Johnny Chend96b5682010-11-05 17:30:53 +00001034# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001035# #
1036# Execution of the test driver starts here #
1037# #
Johnny Chend96b5682010-11-05 17:30:53 +00001038# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001039
Johnny Chen2891bb02011-09-16 01:04:26 +00001040def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +00001041 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1042 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1043 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +00001044 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +00001045 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +00001046 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +00001047 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
1048 print "Exiting..."
1049 sys.exit(0)
1050
1051# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1052# does not exist before proceeding to running the test suite.
1053if sys.platform.startswith("darwin"):
1054 checkDsymForUUIDIsNotOn()
1055
Johnny Chen9707bb62010-06-25 21:14:08 +00001056#
Johnny Chenaf149a02010-09-16 17:11:30 +00001057# Start the actions by first parsing the options while setting up the test
1058# directories, followed by setting up the search paths for lldb utilities;
1059# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +00001060#
Johnny Chenaf149a02010-09-16 17:11:30 +00001061parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +00001062setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +00001063
1064#
1065# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
1066#
1067if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +00001068 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +00001069
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001070#
Johnny Chen41998192010-10-01 22:59:49 +00001071# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +00001072if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +00001073 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1074
1075#
Johnny Chen79723352010-10-12 15:53:22 +00001076# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001077#
Johnny Chen9707bb62010-06-25 21:14:08 +00001078for testdir in testdirs:
1079 os.path.walk(testdir, visit, 'Test')
1080
Johnny Chenb40056b2010-09-21 00:09:27 +00001081#
Johnny Chen9707bb62010-06-25 21:14:08 +00001082# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +00001083#
Johnny Chencd0279d2010-09-20 18:07:50 +00001084
Johnny Chen1bfbd412010-06-29 19:44:16 +00001085# For the time being, let's bracket the test runner within the
1086# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001087import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +00001088# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
1089# there's no need to call it a second time.
1090#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001091atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +00001092
Johnny Chen909e5a62010-07-01 22:52:57 +00001093# Create a singleton SBDebugger in the lldb namespace.
1094lldb.DBG = lldb.SBDebugger.Create()
1095
Johnny Chen4f93bf12010-12-10 00:51:23 +00001096# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +00001097lldb.blacklist = blacklist
1098
Johnny Chenac97a6b2012-04-16 18:55:15 +00001099# The pre_flight and post_flight come from reading a config file.
1100lldb.pre_flight = pre_flight
1101lldb.post_flight = post_flight
1102def getsource_if_available(obj):
1103 """
1104 Return the text of the source code for an object if available. Otherwise,
1105 a print representation is returned.
1106 """
1107 import inspect
1108 try:
1109 return inspect.getsource(obj)
1110 except:
1111 return repr(obj)
1112
1113print "lldb.pre_flight:", getsource_if_available(lldb.pre_flight)
1114print "lldb.post_flight:", getsource_if_available(lldb.post_flight)
1115
Johnny Chena3ed7d82012-04-06 00:56:05 +00001116# Put all these test decorators in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +00001117lldb.dont_do_python_api_test = dont_do_python_api_test
1118lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +00001119lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +00001120lldb.dont_do_dsym_test = dont_do_dsym_test
1121lldb.dont_do_dwarf_test = dont_do_dwarf_test
Johnny Chen4f93bf12010-12-10 00:51:23 +00001122
Johnny Chen028d8eb2011-11-17 19:57:27 +00001123# Do we need to skip build and cleanup?
1124lldb.skip_build_and_cleanup = skip_build_and_cleanup
1125
Johnny Chen5f2ed172011-10-20 18:43:28 +00001126# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +00001127lldb.bmExecutable = bmExecutable
1128lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +00001129lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +00001130
Johnny Chen38f823c2011-10-11 01:30:27 +00001131# And don't forget the runHooks!
1132lldb.runHooks = runHooks
1133
Johnny Chencd0279d2010-09-20 18:07:50 +00001134# Turn on lldb loggings if necessary.
1135lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +00001136
Johnny Chen7987ac92010-08-09 20:40:52 +00001137# Install the control-c handler.
1138unittest2.signals.installHandler()
1139
Johnny Chen125fc2b2010-10-21 16:55:35 +00001140# If sdir_name is not specified through the '-s sdir_name' option, get a
1141# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1142# be used when/if we want to dump the session info of individual test cases
1143# later on.
Johnny Chence681462010-10-19 00:25:01 +00001144#
1145# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chena73ad662012-08-16 19:15:21 +00001146import datetime
1147# The windows platforms don't like ':' in the pathname.
1148timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +00001149if not sdir_name:
Johnny Chena73ad662012-08-16 19:15:21 +00001150 sdir_name = timestamp_started
Peter Collingbourne132476f2011-06-20 23:55:53 +00001151os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +00001152
Johnny Chenfe5f1ed2011-10-21 18:33:27 +00001153if not noHeaders:
1154 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1155 " will go into directory '%s'\n" % sdir_name)
1156 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +00001157
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001158if not os.path.isdir(sdir_name):
1159 os.mkdir(sdir_name)
Johnny Chena73ad662012-08-16 19:15:21 +00001160fname = os.path.join(sdir_name, "TestStarted")
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001161with open(fname, "w") as f:
Johnny Chena73ad662012-08-16 19:15:21 +00001162 print >> f, "Test started at: %s\n" % timestamp_started
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001163 print >> f, svn_info
1164 print >> f, "Command invoked: %s\n" % getMyCommandLine()
1165
Johnny Chenb40056b2010-09-21 00:09:27 +00001166#
1167# Invoke the default TextTestRunner to run the test suite, possibly iterating
1168# over different configurations.
1169#
1170
Johnny Chenb40056b2010-09-21 00:09:27 +00001171iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +00001172iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001173
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001174if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001175 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001176
1177if isinstance(archs, list) and len(archs) >= 1:
1178 iterArchs = True
1179
1180if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001181 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001182
Johnny Chen92693b52012-03-09 02:11:37 +00001183#
1184# Add some intervention here to sanity check that the compilers requested are sane.
1185# If found not to be an executable program, the invalid one is dropped from the list.
1186for i in range(len(compilers)):
1187 c = compilers[i]
1188 if which(c):
1189 continue
1190 else:
1191 if sys.platform.startswith("darwin"):
1192 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1193 cmd_output = pipe.stdout.read()
1194 if cmd_output:
1195 if "not found" in cmd_output:
1196 print "dropping %s from the compilers used" % c
1197 compilers.remove(i)
1198 else:
1199 compilers[i] = cmd_output.split('\n')[0]
1200 print "'xcrun -find %s' returning %s" % (c, compilers[i])
1201
1202print "compilers=%s" % str(compilers)
1203
1204if not compilers or len(compilers) == 0:
1205 print "No eligible compiler found, exiting."
1206 sys.exit(1)
1207
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001208if isinstance(compilers, list) and len(compilers) >= 1:
1209 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001210
Johnny Chen953864a2010-10-12 21:35:54 +00001211# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1212# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001213if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001214 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001215# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1216if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001217 old_stderr = sys.stderr
1218 old_stdout = sys.stdout
1219 new_stderr = None
1220 new_stdout = None
1221
Johnny Chend96b5682010-11-05 17:30:53 +00001222# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001223for ia in range(len(archs) if iterArchs else 1):
1224 archConfig = ""
1225 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001226 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001227 archConfig = "arch=%s" % archs[ia]
1228 for ic in range(len(compilers) if iterCompilers else 1):
1229 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001230 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001231 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1232 else:
1233 configString = archConfig
1234
Johnny Chenb40056b2010-09-21 00:09:27 +00001235 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001236 # Translate ' ' to '-' for pathname component.
1237 from string import maketrans
1238 tbl = maketrans(' ', '-')
1239 configPostfix = configString.translate(tbl)
1240
1241 # Check whether we need to split stderr/stdout into configuration
1242 # specific files.
1243 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1244 if new_stderr:
1245 new_stderr.close()
1246 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1247 sys.stderr = new_stderr
1248 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1249 if new_stdout:
1250 new_stdout.close()
1251 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1252 sys.stdout = new_stdout
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001253
Johnny Chen953864a2010-10-12 21:35:54 +00001254 # If we specified a relocated directory to run the test suite, do
1255 # the extra housekeeping to copy the testdirs to a configStringified
1256 # directory and to update sys.path before invoking the test runner.
1257 # The purpose is to separate the configuration-specific directories
1258 # from each other.
1259 if rdir:
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001260 from shutil import copytree, rmtree, ignore_patterns
Johnny Chen953864a2010-10-12 21:35:54 +00001261
Johnny Chen953864a2010-10-12 21:35:54 +00001262 newrdir = "%s.%s" % (rdir, configPostfix)
1263
1264 # Copy the tree to a new directory with postfix name configPostfix.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001265 if os.path.exists(newrdir):
1266 rmtree(newrdir)
Johnny Chen953864a2010-10-12 21:35:54 +00001267 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1268
Filipe Cabecinhas0e1d06d2012-08-08 15:23:24 +00001269 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001270 # level test directory.
1271 #
1272 # See also lldbtest.TestBase.setUpClass(cls).
1273 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1274 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1275 else:
1276 os.environ["LLDB_TEST"] = newrdir
1277
1278 # And update the Python search paths for modules.
1279 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1280
1281 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +00001282 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001283
1284 #print "sys.stderr name is", sys.stderr.name
1285 #print "sys.stdout name is", sys.stdout.name
1286
1287 # First, write out the number of collected test cases.
Johnny Chen08967192011-11-18 00:19:29 +00001288 sys.stderr.write(separator + "\n")
1289 sys.stderr.write("Collected %d test%s\n\n"
1290 % (suite.countTestCases(),
1291 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001292
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001293 class LLDBTestResult(unittest2.TextTestResult):
1294 """
Johnny Chen26be4532010-11-09 23:56:14 +00001295 Enforce a singleton pattern to allow introspection of test progress.
1296
1297 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1298 to enable each test instance to track its failure/error status. It
1299 is used in the LLDB test framework to emit detailed trace messages
1300 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001301 """
1302 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001303 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001304
1305 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001306 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001307 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001308 super(LLDBTestResult, self).__init__(*args)
1309 LLDBTestResult.__singleton__ = self
1310 # Now put this singleton into the lldb module namespace.
1311 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001312 # Computes the format string for displaying the counter.
1313 global suite
1314 counterWidth = len(str(suite.countTestCases()))
1315 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001316 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001317 # This counts from 1 .. suite.countTestCases().
1318 self.counter = 0
1319
Johnny Chenbe452272012-04-19 21:33:55 +00001320 def _exc_info_to_string(self, err, test):
1321 """Overrides superclass TestResult's method in order to append
1322 our test config info string to the exception info string."""
1323 modified_exc_string = '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1324 test.getArchitecture(),
1325 test.getCompiler())
1326 return modified_exc_string
1327
Johnny Chenc87fd492011-01-05 22:50:11 +00001328 def getDescription(self, test):
1329 doc_first_line = test.shortDescription()
1330 if self.descriptions and doc_first_line:
1331 return '\n'.join((str(test), self.indentation + doc_first_line))
1332 else:
1333 return str(test)
1334
Enrico Granataac3a8e22012-09-21 19:10:53 +00001335 def getCategoriesForTest(self,test):
1336 if hasattr(test,"getCategories"):
1337 test_categories = test.getCategories()
1338 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1339 test_categories = test.__self__.getCategories()
1340 else:
1341 test_categories = []
1342 if test_categories == None:
1343 test_categories = []
1344 return test_categories
1345
1346 def shouldSkipBecauseOfCategories(self,test):
1347 global useCategories
1348 import inspect
1349 if useCategories:
1350 global categoriesList
1351 test_categories = self.getCategoriesForTest(test)
1352 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
1353 return True
1354 return False
1355
1356 def hardMarkAsSkipped(self,test):
1357 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1358 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1359
Johnny Chen810042e2011-01-05 20:24:11 +00001360 def startTest(self, test):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001361 if self.shouldSkipBecauseOfCategories(test):
1362 self.hardMarkAsSkipped(test)
Johnny Chen810042e2011-01-05 20:24:11 +00001363 self.counter += 1
1364 if self.showAll:
1365 self.stream.write(self.fmt % self.counter)
1366 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001367
Johnny Chence681462010-10-19 00:25:01 +00001368 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001369 global sdir_has_content
1370 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001371 super(LLDBTestResult, self).addError(test, err)
1372 method = getattr(test, "markError", None)
1373 if method:
1374 method()
1375
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001376 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001377 global sdir_has_content
Enrico Granataac3a8e22012-09-21 19:10:53 +00001378 global failuresPerCategory
Johnny Chen63c2cba2010-10-29 22:20:36 +00001379 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001380 super(LLDBTestResult, self).addFailure(test, err)
1381 method = getattr(test, "markFailure", None)
1382 if method:
1383 method()
Enrico Granataac3a8e22012-09-21 19:10:53 +00001384 if useCategories:
1385 test_categories = self.getCategoriesForTest(test)
1386 for category in test_categories:
1387 if category in failuresPerCategory:
1388 failuresPerCategory[category] = failuresPerCategory[category] + 1
1389 else:
1390 failuresPerCategory[category] = 1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001391
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001392 def addExpectedFailure(self, test, err):
1393 global sdir_has_content
1394 sdir_has_content = True
1395 super(LLDBTestResult, self).addExpectedFailure(test, err)
1396 method = getattr(test, "markExpectedFailure", None)
1397 if method:
1398 method()
1399
Johnny Chenf5b89092011-08-15 23:09:08 +00001400 def addSkip(self, test, reason):
1401 global sdir_has_content
1402 sdir_has_content = True
1403 super(LLDBTestResult, self).addSkip(test, reason)
1404 method = getattr(test, "markSkippedTest", None)
1405 if method:
1406 method()
1407
Johnny Chenab2f0662011-05-06 20:30:22 +00001408 def addUnexpectedSuccess(self, test):
1409 global sdir_has_content
1410 sdir_has_content = True
1411 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1412 method = getattr(test, "markUnexpectedSuccess", None)
1413 if method:
1414 method()
1415
Johnny Chen26be4532010-11-09 23:56:14 +00001416 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001417 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001418 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001419 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001420 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001421 resultclass=LLDBTestResult).run(suite)
1422 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001423 # We are invoking the same test suite more than once. In this case,
1424 # mark __ignore_singleton__ flag as True so the signleton pattern is
1425 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001426 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001427 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +00001428 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001429 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001430 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001431 resultclass=LLDBTestResult).run(suite)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001432
Johnny Chen1bfbd412010-06-29 19:44:16 +00001433
Johnny Chen63c2cba2010-10-29 22:20:36 +00001434if sdir_has_content:
Johnny Chenab2f0662011-05-06 20:30:22 +00001435 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1436 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001437
Enrico Granataac3a8e22012-09-21 19:10:53 +00001438if useCategories and len(failuresPerCategory) > 0:
1439 sys.stderr.write("Failures per category:\n")
1440 for category in failuresPerCategory:
1441 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
1442
Johnny Chena73ad662012-08-16 19:15:21 +00001443fname = os.path.join(sdir_name, "TestFinished")
1444with open(fname, "w") as f:
1445 print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1446
Johnny Chencd0279d2010-09-20 18:07:50 +00001447# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1448# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001449if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001450 print "Terminating Test suite..."
1451 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1452
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001453# Exiting.
Daniel Malea2777b012013-02-06 16:55:07 +00001454sys.exit(not result.wasSuccessful())