blob: 5d604f4bc878eed1d34638dc7a0228cb6f7a66b2 [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 Chen0f907b82012-01-31 00:38:03 +0000209# The environment variables to unset before running the test cases.
210unsets = []
211
Johnny Chen9707bb62010-06-25 21:14:08 +0000212# Default verbosity is 0.
213verbose = 0
214
Johnny Chen08967192011-11-18 00:19:29 +0000215# Set to True only if verbose is 0 and LLDB trace mode is off.
216progress_bar = False
217
Peter Collingbourne61aca482011-06-20 19:06:29 +0000218# By default, search from the script directory.
219testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000220
Johnny Chen877c7e42010-08-07 00:16:07 +0000221# Separator string.
222separator = '-' * 70
223
Johnny Chen9707bb62010-06-25 21:14:08 +0000224
Greg Clayton4793e942012-09-04 15:42:49 +0000225def usage(parser):
226 parser.print_help()
Jim Ingham4f347cb2011-04-13 21:11:41 +0000227 if verbose > 0:
228 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000229Examples:
230
Johnny Chena224cd12010-11-08 01:21:03 +0000231This is an example of using the -f option to pinpoint to a specfic test class
232and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000233
Johnny Chena224cd12010-11-08 01:21:03 +0000234$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000235----------------------------------------------------------------------
236Collected 1 test
237
238test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
239Test 'frame variable this' when stopped on a class constructor. ... ok
240
241----------------------------------------------------------------------
242Ran 1 test in 1.396s
243
244OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000245
246And this is an example of using the -p option to run a single file (the filename
247matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
248
249$ ./dotest.py -v -p ObjC
250----------------------------------------------------------------------
251Collected 4 tests
252
253test_break_with_dsym (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_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000256Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000257test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
258Lookup objective-c data types and evaluate expressions. ... ok
259test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
260Lookup objective-c data types and evaluate expressions. ... ok
261
262----------------------------------------------------------------------
263Ran 4 tests in 16.661s
264
265OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000266
Johnny Chen58f93922010-06-29 23:10:39 +0000267Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000268individual test cases can locate their supporting files correctly. The script
269tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000270relative to this script. See also the '-i' option in the following example.
271
272Finally, this is an example of using the lldb.py module distributed/installed by
273Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
274option to add some delay between two tests. It uses ARCH=x86_64 to specify that
275as the architecture and CC=clang to specify the compiler used for the test run:
276
277$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
278
279Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
280----------------------------------------------------------------------
281Collected 2 tests
282
283test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
284Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
285test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
286Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
287
288----------------------------------------------------------------------
289Ran 2 tests in 5.659s
290
291OK
292
293The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
294notify the directory containing the session logs for test failures or errors.
295In case there is any test failure/error, a similar message is appended at the
296end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000297
298Environment variables related to loggings:
299
300o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
301 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
302
303o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
304 'process.gdb-remote' subsystem with a default option of 'packets' if
305 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000306"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000307 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000308
309
Johnny Chenaf149a02010-09-16 17:11:30 +0000310def parseOptionsAndInitTestdirs():
311 """Initialize the list of directories containing our unittest scripts.
312
313 '-h/--help as the first option prints out usage info and exit the program.
314 """
315
Johnny Chen4f93bf12010-12-10 00:51:23 +0000316 global dont_do_python_api_test
317 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000318 global just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +0000319 global dont_do_dsym_test
320 global dont_do_dwarf_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000321 global blacklist
322 global blacklistConfig
Enrico Granataac3a8e22012-09-21 19:10:53 +0000323 global categoriesList
324 global validCategories
325 global useCategories
Sean Callanan0acf4c62012-10-24 22:45:39 +0000326 global lldbFrameworkPath
327 global lldbExecutablePath
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000328 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000329 global archs
330 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000331 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000332 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000333 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000334 global bmExecutable
335 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000336 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000337 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000338 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000339 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000340 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000341 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000342 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000343 global skip_build_and_cleanup
344 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000345 global noHeaders
Johnny Chen7c52ff12010-09-27 23:29:54 +0000346 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000347 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000348 global sdir_name
Johnny Chen0f907b82012-01-31 00:38:03 +0000349 global unsets
Johnny Chenaf149a02010-09-16 17:11:30 +0000350 global verbose
351 global testdirs
352
Jim Ingham4f347cb2011-04-13 21:11:41 +0000353 do_help = False
354
Greg Clayton4793e942012-09-04 15:42:49 +0000355 parser = argparse.ArgumentParser(description='description', prefix_chars='+-', add_help=False)
356 group = None
Johnny Chenaf149a02010-09-16 17:11:30 +0000357
Greg Clayton4793e942012-09-04 15:42:49 +0000358 # Helper function for boolean options (group will point to the current group when executing X)
359 X = lambda optstr, helpstr, **kwargs: group.add_argument(optstr, help=helpstr, action='store_true', **kwargs)
360
361 group = parser.add_argument_group('Help')
362 group.add_argument('-h', '--help', dest='h', action='store_true', help="Print this help message and exit. Add '-v' for more detailed help.")
363
364 # C and Python toolchain options
365 group = parser.add_argument_group('Toolchain options')
366 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'''))
367 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.'''))
368 # FIXME? This won't work for different extra flags according to each arch.
369 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
370 suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
371 X('-D', 'Dump the Python sys.path variable')
372
373 # Test filtering options
374 group = parser.add_argument_group('Test filtering options')
375 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")
376 X('-a', "Don't do lldb Python API tests")
377 X('+a', "Just do lldb Python API tests. Do not specify along with '+a'", dest='plus_a')
378 X('+b', 'Just do benchmark tests', dest='plus_b')
379 group.add_argument('-b', metavar='blacklist', help='Read a blacklist file specified after this option')
Enrico Granata58b03a42012-12-14 00:07:09 +0000380 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 +0000381 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')
382 X('-l', "Don't skip long running tests")
383 group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite')
384 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 +0000385 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 +0000386
387 # Configuration options
388 group = parser.add_argument_group('Configuration options')
389 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 +0000390 group.add_argument('--framework', metavar='framework-path', help='The path to LLDB.framework')
391 group.add_argument('--executable', metavar='executable-path', help='The path to the lldb executable')
Greg Clayton4793e942012-09-04 15:42:49 +0000392 group.add_argument('-e', metavar='benchmark-exe', help='Specify the full path of an executable used for benchmark purposes (see also: -x)')
393 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")
394 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')
395 group.add_argument('-r', metavar='dir', help="Similar to '-R', except that the directory must not exist before running this test driver")
396 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')
397 group.add_argument('-x', metavar='breakpoint-spec', help='Specify the breakpoint specification for the benchmark executable')
398 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.")
399 group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times')
400
401 # Test-suite behaviour
402 group = parser.add_argument_group('Runtime behaviour options')
403 X('-d', 'Delay startup for 10 seconds (in order for the debugger to attach)')
404 X('-F', 'Fail fast. Stop the test suite on the first error/failure')
405 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")
406 X('-n', "Don't print the headers like build dir, lldb version, and svn info at all")
407 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")
408 X('-t', 'Turn on tracing of lldb command and other detailed test executions')
409 group.add_argument('-u', metavar='variable', action='append', help='Specify an environment variable to unset before running the test cases. e.g., -u DYLD_INSERT_LIBRARIES -u MallocScribble')
410 X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
411 X('-w', 'Insert some wait time (currently 0.5 sec) between consecutive test cases')
412
413 # Remove the reference to our helper function
414 del X
415
416 group = parser.add_argument_group('Test directories')
417 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.')
418 args = parser.parse_args()
419
420 platform_system = platform.system()
421 platform_machine = platform.machine()
Enrico Granata2d329242012-10-23 22:52:49 +0000422
423 # only print the args if being verbose
424 if args.v:
425 print args
Greg Clayton4793e942012-09-04 15:42:49 +0000426
427 if args.h:
428 do_help = True
429
430 if args.archs:
431 archs = args.archs
432 else:
433 if platform_system == 'Darwin' and platform_machine == 'x86_64':
434 archs = ['x86_64', 'i386']
Johnny Chenaf149a02010-09-16 17:11:30 +0000435 else:
Greg Clayton4793e942012-09-04 15:42:49 +0000436 archs = [platform_machine]
437
Enrico Granataac3a8e22012-09-21 19:10:53 +0000438 if args.categoriesList:
439 for category in args.categoriesList:
440 if not(category in validCategories):
Enrico Granata2d329242012-10-23 22:52:49 +0000441 print "fatal error: category '" + category + "' is not a valid category"
442 print "if you have added a new category, please edit dotest.py, adding your new category to validCategories"
443 print "else, please specify one or more of the following: " + str(validCategories.keys())
Enrico Granataac3a8e22012-09-21 19:10:53 +0000444 sys.exit(1)
445 categoriesList = set(args.categoriesList)
446 useCategories = True
447 else:
448 categoriesList = []
449
Greg Clayton4793e942012-09-04 15:42:49 +0000450 if args.compilers:
451 compilers = args.compilers
452 else:
453 compilers = ['clang']
454
455 if args.D:
456 dumpSysPath = True
457
458 if args.E:
459 cflags_extras = args.E
460 os.environ['CFLAGS_EXTRAS'] = cflags_extras
461
462 # argparse makes sure we have correct options
463 if args.N == 'dwarf':
464 dont_do_dwarf_test = True
465 elif args.N == 'dsym':
466 dont_do_dsym_test = True
467
468 if args.a:
469 dont_do_python_api_test = True
470
471 if args.plus_a:
472 if dont_do_python_api_test:
473 print "Warning: -a and +a can't both be specified! Using only -a"
474 else:
475 just_do_python_api_test = True
476
477 if args.plus_b:
478 just_do_benchmarks_test = True
479
480 if args.b:
481 if args.b.startswith('-'):
482 usage(parser)
483 blacklistFile = args.b
484 if not os.path.isfile(blacklistFile):
485 print 'Blacklist file:', blacklistFile, 'does not exist!'
486 usage(parser)
487 # Now read the blacklist contents and assign it to blacklist.
488 execfile(blacklistFile, globals(), blacklistConfig)
489 blacklist = blacklistConfig.get('blacklist')
490
491 if args.c:
492 if args.c.startswith('-'):
493 usage(parser)
494 configFile = args.c
495 if not os.path.isfile(configFile):
496 print 'Config file:', configFile, 'does not exist!'
497 usage(parser)
498
499 if args.d:
500 delay = True
501
502 if args.e:
503 if args.e.startswith('-'):
504 usage(parser)
505 bmExecutable = args.e
506 if not is_exe(bmExecutable):
507 usage(parser)
508
509 if args.F:
510 failfast = True
511
512 if args.f:
Enrico Granata58b03a42012-12-14 00:07:09 +0000513 if any([x.startswith('-') for x in args.f]):
Greg Clayton4793e942012-09-04 15:42:49 +0000514 usage(parser)
Enrico Granata58b03a42012-12-14 00:07:09 +0000515 filters.extend(args.f)
Greg Clayton4793e942012-09-04 15:42:49 +0000516
517 if args.g:
518 fs4all = False
519
520 if args.i:
521 ignore = True
522
523 if args.k:
524 runHooks.extend(args.k)
525
526 if args.l:
527 skip_long_running_test = False
528
Sean Callanan0acf4c62012-10-24 22:45:39 +0000529 if args.framework:
530 lldbFrameworkPath = args.framework
531
532 if args.executable:
533 lldbExecutablePath = args.executable
534
Greg Clayton4793e942012-09-04 15:42:49 +0000535 if args.n:
536 noHeaders = True
537
538 if args.p:
539 if args.p.startswith('-'):
540 usage(parser)
541 regexp = args.p
542
543 if args.R:
544 if args.R.startswith('-'):
545 usage(parser)
546 rdir = os.path.abspath(args.R)
547 if os.path.exists(rdir):
548 import shutil
549 print 'Removing tree:', rdir
550 shutil.rmtree(rdir)
551
552 if args.r:
553 if args.r.startswith('-'):
554 usage(parser)
555 rdir = os.path.abspath(args.r)
556 if os.path.exists(rdir):
557 print 'Relocated directory:', rdir, 'must not exist!'
558 usage(parser)
559
560 if args.S:
561 skip_build_and_cleanup = True
562
563 if args.s:
564 if args.s.startswith('-'):
565 usage(parser)
566 sdir_name = args.s
567
568 if args.t:
569 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
570
571 if args.u:
572 unsets.extend(args.u)
573
574 if args.v:
575 verbose = 2
576
577 if args.w:
578 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
579
580 if args.X:
581 if args.X.startswith('-'):
582 usage(parser)
583 excluded.add(args.X)
584
585 if args.x:
586 if args.x.startswith('-'):
587 usage(parser)
588 bmBreakpointSpec = args.x
589
590 # argparse makes sure we have a number
591 if args.y:
592 bmIterationCount = args.y
593
594 # argparse makes sure we have a number
595 if args.sharp:
596 count = args.sharp
Johnny Chenaf149a02010-09-16 17:11:30 +0000597
Jim Ingham4f347cb2011-04-13 21:11:41 +0000598 if do_help == True:
Greg Clayton4793e942012-09-04 15:42:49 +0000599 usage(parser)
Jim Ingham4f347cb2011-04-13 21:11:41 +0000600
Johnny Chencc659ad2010-12-10 19:02:23 +0000601 # Do not specify both '-a' and '+a' at the same time.
602 if dont_do_python_api_test and just_do_python_api_test:
Greg Clayton4793e942012-09-04 15:42:49 +0000603 usage(parser)
Johnny Chencc659ad2010-12-10 19:02:23 +0000604
Johnny Chen08967192011-11-18 00:19:29 +0000605 # 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 +0000606 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 +0000607 progress_bar = True
608
Johnny Chenaf149a02010-09-16 17:11:30 +0000609 # Gather all the dirs passed on the command line.
Greg Clayton4793e942012-09-04 15:42:49 +0000610 if len(args.args) > 0:
611 testdirs = map(os.path.abspath, args.args)
Johnny Chenaf149a02010-09-16 17:11:30 +0000612
Johnny Chen548aefd2010-10-11 22:25:46 +0000613 # If '-r dir' is specified, the tests should be run under the relocated
614 # directory. Let's copy the testdirs over.
615 if rdir:
616 from shutil import copytree, ignore_patterns
617
618 tmpdirs = []
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000619 orig_testdirs = testdirs[:]
Johnny Chen548aefd2010-10-11 22:25:46 +0000620 for srcdir in testdirs:
Johnny Chen1abe4c02012-03-20 00:33:51 +0000621 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
622 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
623 # Utilize the relative path to the 'test' directory to make our destination dir path.
Greg Clayton4793e942012-09-04 15:42:49 +0000624 if ("test" + os.sep) in srcdir:
625 to_split_on = "test" + os.sep
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000626 else:
627 to_split_on = "test"
628 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
629 dstdir = dstdir.rstrip(os.sep)
Johnny Chen548aefd2010-10-11 22:25:46 +0000630 # Don't copy the *.pyc and .svn stuffs.
631 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
632 tmpdirs.append(dstdir)
633
634 # This will be our modified testdirs.
635 testdirs = tmpdirs
636
637 # With '-r dir' specified, there's no cleanup of intermediate test files.
638 os.environ["LLDB_DO_CLEANUP"] = 'NO'
639
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000640 # If the original testdirs is ['test'], the make directory has already been copied
Johnny Chen548aefd2010-10-11 22:25:46 +0000641 # recursively and is contained within the rdir/test dir. For anything
642 # else, we would need to copy over the make directory and its contents,
643 # so that, os.listdir(rdir) looks like, for example:
644 #
645 # array_types conditional_break make
646 #
647 # where the make directory contains the Makefile.rules file.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000648 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000649 scriptdir = os.path.dirname(__file__)
Johnny Chen548aefd2010-10-11 22:25:46 +0000650 # Don't copy the .svn stuffs.
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000651 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
Johnny Chen548aefd2010-10-11 22:25:46 +0000652 ignore=ignore_patterns('.svn'))
653
654 #print "testdirs:", testdirs
655
Johnny Chenb40056b2010-09-21 00:09:27 +0000656 # Source the configFile if specified.
657 # The side effect, if any, will be felt from this point on. An example
658 # config file may be these simple two lines:
659 #
660 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
661 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
662 #
663 # which will reassign the two file objects to sys.stderr and sys.stdout,
664 # respectively.
665 #
Johnny Chen8c130642012-08-22 17:53:02 +0000666 # See also lldb-trunk/examples/test/usage-config.
Johnny Chenac97a6b2012-04-16 18:55:15 +0000667 global config, pre_flight, post_flight
Johnny Chenb40056b2010-09-21 00:09:27 +0000668 if configFile:
669 # Pass config (a dictionary) as the locals namespace for side-effect.
670 execfile(configFile, globals(), config)
Johnny Chenac97a6b2012-04-16 18:55:15 +0000671 print "config:", config
672 if "pre_flight" in config:
673 pre_flight = config["pre_flight"]
674 if not callable(pre_flight):
675 print "fatal error: pre_flight is not callable, exiting."
676 sys.exit(1)
677 if "post_flight" in config:
678 post_flight = config["post_flight"]
679 if not callable(post_flight):
680 print "fatal error: post_flight is not callable, exiting."
681 sys.exit(1)
Johnny Chenb40056b2010-09-21 00:09:27 +0000682 #print "sys.stderr:", sys.stderr
683 #print "sys.stdout:", sys.stdout
684
Johnny Chenaf149a02010-09-16 17:11:30 +0000685
Johnny Chen9707bb62010-06-25 21:14:08 +0000686def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000687 """
688 Add LLDB.framework/Resources/Python to the search paths for modules.
689 As a side effect, we also discover the 'lldb' executable and export it here.
690 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000691
Johnny Chen548aefd2010-10-11 22:25:46 +0000692 global rdir
693 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000694 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000695 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000696 global svn_info
Sean Callanan0acf4c62012-10-24 22:45:39 +0000697 global lldbFrameworkPath
698 global lldbExecutablePath
Johnny Chen548aefd2010-10-11 22:25:46 +0000699
Johnny Chen9707bb62010-06-25 21:14:08 +0000700 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000701 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 +0000702 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
703 else:
704 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000705 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000706 print "This script expects to reside in lldb's test directory."
707 sys.exit(-1)
708
Johnny Chen548aefd2010-10-11 22:25:46 +0000709 if rdir:
710 # Set up the LLDB_TEST environment variable appropriately, so that the
711 # individual tests can be located relatively.
712 #
713 # See also lldbtest.TestBase.setUpClass(cls).
714 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
715 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
716 else:
717 os.environ["LLDB_TEST"] = rdir
718 else:
719 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000720
721 # Set up the LLDB_SRC environment variable, so that the tests can locate
722 # the LLDB source code.
723 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
724
Johnny Chen9de4ede2010-08-31 17:42:54 +0000725 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000726 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000727
Johnny Chen8a3c0432011-03-11 20:13:06 +0000728 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000729 sys.path.append(scriptPath)
730 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000731 sys.path.append(pexpectPath)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000732
Johnny Chen26901c82011-03-11 19:47:23 +0000733 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000734 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000735
Johnny Chen26901c82011-03-11 19:47:23 +0000736 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000737 xcode3_build_dir = ['build']
738 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
739 dbg = ['Debug']
Sean Callanand9d94632012-09-26 21:16:15 +0000740 dbc = ['DebugClang']
Johnny Chen6a564a42011-02-15 18:50:19 +0000741 rel = ['Release']
742 bai = ['BuildAndIntegration']
743 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000744
745 # Some of the tests can invoke the 'lldb' command directly.
746 # We'll try to locate the appropriate executable right here.
747
Sean Callanan0acf4c62012-10-24 22:45:39 +0000748 lldbExec = None
749 if lldbExecutablePath:
750 if is_exe(lldbExecutablePath):
751 lldbExec = lldbExecutablePath
Sean Callanan502000d2012-11-01 21:23:21 +0000752 lldbHere = lldbExec
Sean Callanan0acf4c62012-10-24 22:45:39 +0000753 else:
754 print lldbExecutablePath + " is not an executable"
755 sys.exit(-1)
Johnny Chen6033bed2011-08-26 00:00:01 +0000756 else:
Sean Callanan0acf4c62012-10-24 22:45:39 +0000757 # First, you can define an environment variable LLDB_EXEC specifying the
758 # full pathname of the lldb executable.
759 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
760 lldbExec = os.environ["LLDB_EXEC"]
761 else:
762 lldbExec = None
763
764 executable = ['lldb']
765 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
766 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
767 dbcExec = os.path.join(base, *(xcode3_build_dir + dbc + executable))
768 dbcExec2 = os.path.join(base, *(xcode4_build_dir + dbc + executable))
769 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
770 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
771 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
772 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
773
774 # The 'lldb' executable built here in the source tree.
775 lldbHere = None
776 if is_exe(dbgExec):
777 lldbHere = dbgExec
778 elif is_exe(dbgExec2):
779 lldbHere = dbgExec2
780 elif is_exe(dbcExec):
781 lldbHere = dbcExec
782 elif is_exe(dbcExec2):
783 lldbHere = dbcExec2
784 elif is_exe(relExec):
785 lldbHere = relExec
786 elif is_exe(relExec2):
787 lldbHere = relExec2
788 elif is_exe(baiExec):
789 lldbHere = baiExec
790 elif is_exe(baiExec2):
791 lldbHere = baiExec2
792 elif lldbExec:
793 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000794
Sean Callanan0acf4c62012-10-24 22:45:39 +0000795 # One last chance to locate the 'lldb' executable.
796 if not lldbExec:
797 lldbExec = which('lldb')
798 if lldbHere and not lldbExec:
799 lldbExec = lldbHere
Sean Callanan502000d2012-11-01 21:23:21 +0000800
801 if lldbHere:
802 os.environ["LLDB_HERE"] = lldbHere
803 os.environ["LLDB_BUILD_DIR"] = os.path.split(lldbHere)[0]
804 if not noHeaders:
805 print "LLDB build dir:", os.environ["LLDB_BUILD_DIR"]
806 os.system('%s -v' % lldbHere)
Johnny Chen26901c82011-03-11 19:47:23 +0000807
808 if not lldbExec:
809 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
810 else:
811 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000812 #print "The 'lldb' from PATH env variable", lldbExec
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000813
Johnny Chenb264c9b2011-06-24 22:52:05 +0000814 if os.path.isdir(os.path.join(base, '.svn')):
815 pipe = subprocess.Popen(["svn", "info", base], stdout = subprocess.PIPE)
816 svn_info = pipe.stdout.read()
817 elif os.path.isdir(os.path.join(base, '.git')):
818 pipe = subprocess.Popen(["git", "svn", "info", base], stdout = subprocess.PIPE)
819 svn_info = pipe.stdout.read()
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000820 if not noHeaders:
821 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000822
823 global ignore
824
Johnny Chen9707bb62010-06-25 21:14:08 +0000825 lldbPath = None
Sean Callanan0acf4c62012-10-24 22:45:39 +0000826 if lldbFrameworkPath:
827 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python')
828 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
829 lldbPath = candidatePath
830 if not lldbPath:
831 print 'Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath
832 sys.exit(-1)
833 else:
834 # The '-i' option is used to skip looking for lldb.py in the build tree.
835 if ignore:
836 return
837
838 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
839 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
840 dbcPath = os.path.join(base, *(xcode3_build_dir + dbc + python_resource_dir))
841 dbcPath2 = os.path.join(base, *(xcode4_build_dir + dbc + python_resource_dir))
842 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
843 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
844 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
845 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
846
847 if os.path.isfile(os.path.join(dbgPath, 'lldb/__init__.py')):
848 lldbPath = dbgPath
849 elif os.path.isfile(os.path.join(dbgPath2, 'lldb/__init__.py')):
850 lldbPath = dbgPath2
851 elif os.path.isfile(os.path.join(dbcPath, 'lldb/__init__.py')):
852 lldbPath = dbcPath
853 elif os.path.isfile(os.path.join(dbcPath2, 'lldb/__init__.py')):
854 lldbPath = dbcPath2
855 elif os.path.isfile(os.path.join(relPath, 'lldb/__init__.py')):
856 lldbPath = relPath
857 elif os.path.isfile(os.path.join(relPath2, 'lldb/__init__.py')):
858 lldbPath = relPath2
859 elif os.path.isfile(os.path.join(baiPath, 'lldb/__init__.py')):
860 lldbPath = baiPath
861 elif os.path.isfile(os.path.join(baiPath2, 'lldb/__init__.py')):
862 lldbPath = baiPath2
863
864 if not lldbPath:
865 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
866 print relPath + ', or ' + baiPath
867 sys.exit(-1)
Johnny Chen9707bb62010-06-25 21:14:08 +0000868
Enrico Granata01458ca2012-10-23 00:09:02 +0000869 # If tests need to find LLDB_FRAMEWORK, now they can do it
870 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPath))
871
Johnny Chenaf149a02010-09-16 17:11:30 +0000872 # This is to locate the lldb.py module. Insert it right after sys.path[0].
873 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000874 if dumpSysPath:
875 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000876
Johnny Chen9707bb62010-06-25 21:14:08 +0000877
Johnny Chencd0279d2010-09-20 18:07:50 +0000878def doDelay(delta):
879 """Delaying startup for delta-seconds to facilitate debugger attachment."""
880 def alarm_handler(*args):
881 raise Exception("timeout")
882
883 signal.signal(signal.SIGALRM, alarm_handler)
884 signal.alarm(delta)
885 sys.stdout.write("pid=%d\n" % os.getpid())
886 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
887 delta)
888 sys.stdout.flush()
889 try:
890 text = sys.stdin.readline()
891 except:
892 text = ""
893 signal.alarm(0)
894 sys.stdout.write("proceeding...\n")
895 pass
896
897
Johnny Chen9707bb62010-06-25 21:14:08 +0000898def visit(prefix, dir, names):
899 """Visitor function for os.path.walk(path, visit, arg)."""
900
901 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +0000902 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +0000903 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000904 global fs4all
Johnny Chene9eae812012-01-18 05:15:00 +0000905 global excluded
906
907 if set(dir.split(os.sep)).intersection(excluded):
908 #print "Detected an excluded dir component: %s" % dir
909 return
Johnny Chen9707bb62010-06-25 21:14:08 +0000910
911 for name in names:
912 if os.path.isdir(os.path.join(dir, name)):
913 continue
914
915 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +0000916 # Try to match the regexp pattern, if specified.
917 if regexp:
918 import re
919 if re.search(regexp, name):
920 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
921 pass
922 else:
923 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
924 continue
925
Johnny Chen953864a2010-10-12 21:35:54 +0000926 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +0000927
928 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +0000929 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +0000930 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +0000931 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +0000932
933 # Thoroughly check the filterspec against the base module and admit
934 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000935 filterspec = None
936 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +0000937 # Optimistically set the flag to True.
938 filtered = True
939 module = __import__(base)
940 parts = filterspec.split('.')
941 obj = module
942 for part in parts:
943 try:
944 parent, obj = obj, getattr(obj, part)
945 except AttributeError:
946 # The filterspec has failed.
947 filtered = False
948 break
Johnny Chenc5fa0052011-07-29 22:54:56 +0000949
Johnny Chendb4be602011-08-12 23:55:07 +0000950 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +0000951 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +0000952 #print "adding filter spec %s to module %s" % (filterspec, module)
953 suite.addTests(
954 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
955 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +0000956
957 # Forgo this module if the (base, filterspec) combo is invalid
958 # and no '-g' option is specified
959 if filters and fs4all and not filtered:
960 continue
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000961
Johnny Chendb4be602011-08-12 23:55:07 +0000962 # Add either the filtered test case(s) (which is done before) or the entire test class.
963 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +0000964 # A simple case of just the module name. Also the failover case
965 # from the filterspec branch when the (base, filterspec) combo
966 # doesn't make sense.
967 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +0000968
969
Johnny Chencd0279d2010-09-20 18:07:50 +0000970def lldbLoggings():
971 """Check and do lldb loggings if necessary."""
972
973 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
974 # defined. Use ${LLDB_LOG} to specify the log file.
975 ci = lldb.DBG.GetCommandInterpreter()
976 res = lldb.SBCommandReturnObject()
977 if ("LLDB_LOG" in os.environ):
978 if ("LLDB_LOG_OPTION" in os.environ):
979 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
980 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +0000981 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +0000982 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +0000983 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +0000984 res)
985 if not res.Succeeded():
986 raise Exception('log enable failed (check LLDB_LOG env variable.')
987 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
988 # Use ${GDB_REMOTE_LOG} to specify the log file.
989 if ("GDB_REMOTE_LOG" in os.environ):
990 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
991 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
992 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +0000993 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +0000994 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +0000995 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +0000996 + gdb_remote_log_option,
997 res)
998 if not res.Succeeded():
999 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
1000
Johnny Chen067022b2011-01-19 19:31:46 +00001001def getMyCommandLine():
Johnny Chen067022b2011-01-19 19:31:46 +00001002 ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
1003 lines = ps.split('\n')
1004 cmd_line = lines[1]
1005 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +00001006
Johnny Chend96b5682010-11-05 17:30:53 +00001007# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001008# #
1009# Execution of the test driver starts here #
1010# #
Johnny Chend96b5682010-11-05 17:30:53 +00001011# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001012
Johnny Chen2891bb02011-09-16 01:04:26 +00001013def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +00001014 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1015 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1016 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +00001017 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +00001018 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +00001019 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +00001020 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
1021 print "Exiting..."
1022 sys.exit(0)
1023
1024# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1025# does not exist before proceeding to running the test suite.
1026if sys.platform.startswith("darwin"):
1027 checkDsymForUUIDIsNotOn()
1028
Johnny Chen9707bb62010-06-25 21:14:08 +00001029#
Johnny Chenaf149a02010-09-16 17:11:30 +00001030# Start the actions by first parsing the options while setting up the test
1031# directories, followed by setting up the search paths for lldb utilities;
1032# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +00001033#
Johnny Chenaf149a02010-09-16 17:11:30 +00001034parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +00001035setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +00001036
1037#
1038# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
1039#
1040if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +00001041 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +00001042
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001043#
Johnny Chen41998192010-10-01 22:59:49 +00001044# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +00001045if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +00001046 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1047
1048#
Johnny Chen79723352010-10-12 15:53:22 +00001049# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001050#
Johnny Chen9707bb62010-06-25 21:14:08 +00001051for testdir in testdirs:
1052 os.path.walk(testdir, visit, 'Test')
1053
Johnny Chenb40056b2010-09-21 00:09:27 +00001054#
Johnny Chen9707bb62010-06-25 21:14:08 +00001055# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +00001056#
Johnny Chencd0279d2010-09-20 18:07:50 +00001057
Johnny Chen1bfbd412010-06-29 19:44:16 +00001058# For the time being, let's bracket the test runner within the
1059# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001060import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +00001061# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
1062# there's no need to call it a second time.
1063#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001064atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +00001065
Johnny Chen909e5a62010-07-01 22:52:57 +00001066# Create a singleton SBDebugger in the lldb namespace.
1067lldb.DBG = lldb.SBDebugger.Create()
1068
Johnny Chen4f93bf12010-12-10 00:51:23 +00001069# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +00001070lldb.blacklist = blacklist
1071
Johnny Chenac97a6b2012-04-16 18:55:15 +00001072# The pre_flight and post_flight come from reading a config file.
1073lldb.pre_flight = pre_flight
1074lldb.post_flight = post_flight
1075def getsource_if_available(obj):
1076 """
1077 Return the text of the source code for an object if available. Otherwise,
1078 a print representation is returned.
1079 """
1080 import inspect
1081 try:
1082 return inspect.getsource(obj)
1083 except:
1084 return repr(obj)
1085
1086print "lldb.pre_flight:", getsource_if_available(lldb.pre_flight)
1087print "lldb.post_flight:", getsource_if_available(lldb.post_flight)
1088
Johnny Chena3ed7d82012-04-06 00:56:05 +00001089# Put all these test decorators in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +00001090lldb.dont_do_python_api_test = dont_do_python_api_test
1091lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +00001092lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +00001093lldb.dont_do_dsym_test = dont_do_dsym_test
1094lldb.dont_do_dwarf_test = dont_do_dwarf_test
Johnny Chen4f93bf12010-12-10 00:51:23 +00001095
Johnny Chen028d8eb2011-11-17 19:57:27 +00001096# Do we need to skip build and cleanup?
1097lldb.skip_build_and_cleanup = skip_build_and_cleanup
1098
Johnny Chen5f2ed172011-10-20 18:43:28 +00001099# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +00001100lldb.bmExecutable = bmExecutable
1101lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +00001102lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +00001103
Johnny Chen38f823c2011-10-11 01:30:27 +00001104# And don't forget the runHooks!
1105lldb.runHooks = runHooks
1106
Johnny Chencd0279d2010-09-20 18:07:50 +00001107# Turn on lldb loggings if necessary.
1108lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +00001109
Johnny Chen7987ac92010-08-09 20:40:52 +00001110# Install the control-c handler.
1111unittest2.signals.installHandler()
1112
Johnny Chen125fc2b2010-10-21 16:55:35 +00001113# If sdir_name is not specified through the '-s sdir_name' option, get a
1114# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1115# be used when/if we want to dump the session info of individual test cases
1116# later on.
Johnny Chence681462010-10-19 00:25:01 +00001117#
1118# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chena73ad662012-08-16 19:15:21 +00001119import datetime
1120# The windows platforms don't like ':' in the pathname.
1121timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +00001122if not sdir_name:
Johnny Chena73ad662012-08-16 19:15:21 +00001123 sdir_name = timestamp_started
Peter Collingbourne132476f2011-06-20 23:55:53 +00001124os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +00001125
Johnny Chenfe5f1ed2011-10-21 18:33:27 +00001126if not noHeaders:
1127 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1128 " will go into directory '%s'\n" % sdir_name)
1129 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +00001130
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001131if not os.path.isdir(sdir_name):
1132 os.mkdir(sdir_name)
Johnny Chena73ad662012-08-16 19:15:21 +00001133fname = os.path.join(sdir_name, "TestStarted")
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001134with open(fname, "w") as f:
Johnny Chena73ad662012-08-16 19:15:21 +00001135 print >> f, "Test started at: %s\n" % timestamp_started
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001136 print >> f, svn_info
1137 print >> f, "Command invoked: %s\n" % getMyCommandLine()
1138
Johnny Chenb40056b2010-09-21 00:09:27 +00001139#
Johnny Chen0f907b82012-01-31 00:38:03 +00001140# If we have environment variables to unset, do it here before we invoke the test runner.
1141#
1142for env_var in unsets :
1143 if env_var in os.environ:
1144 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
Johnny Chen6346a292012-01-31 00:48:02 +00001145 # is automatically translated into a corresponding call to unsetenv().
Johnny Chen0f907b82012-01-31 00:38:03 +00001146 del os.environ[env_var]
1147 #os.unsetenv(env_var)
1148
1149#
Johnny Chenb40056b2010-09-21 00:09:27 +00001150# Invoke the default TextTestRunner to run the test suite, possibly iterating
1151# over different configurations.
1152#
1153
Johnny Chenb40056b2010-09-21 00:09:27 +00001154iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +00001155iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001156
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001157if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001158 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001159
1160if isinstance(archs, list) and len(archs) >= 1:
1161 iterArchs = True
1162
1163if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001164 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001165
Johnny Chen92693b52012-03-09 02:11:37 +00001166#
1167# Add some intervention here to sanity check that the compilers requested are sane.
1168# If found not to be an executable program, the invalid one is dropped from the list.
1169for i in range(len(compilers)):
1170 c = compilers[i]
1171 if which(c):
1172 continue
1173 else:
1174 if sys.platform.startswith("darwin"):
1175 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1176 cmd_output = pipe.stdout.read()
1177 if cmd_output:
1178 if "not found" in cmd_output:
1179 print "dropping %s from the compilers used" % c
1180 compilers.remove(i)
1181 else:
1182 compilers[i] = cmd_output.split('\n')[0]
1183 print "'xcrun -find %s' returning %s" % (c, compilers[i])
1184
1185print "compilers=%s" % str(compilers)
1186
1187if not compilers or len(compilers) == 0:
1188 print "No eligible compiler found, exiting."
1189 sys.exit(1)
1190
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001191if isinstance(compilers, list) and len(compilers) >= 1:
1192 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001193
Johnny Chen953864a2010-10-12 21:35:54 +00001194# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1195# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001196if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001197 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001198# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1199if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001200 old_stderr = sys.stderr
1201 old_stdout = sys.stdout
1202 new_stderr = None
1203 new_stdout = None
1204
Johnny Chend96b5682010-11-05 17:30:53 +00001205# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001206for ia in range(len(archs) if iterArchs else 1):
1207 archConfig = ""
1208 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001209 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001210 archConfig = "arch=%s" % archs[ia]
1211 for ic in range(len(compilers) if iterCompilers else 1):
1212 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001213 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001214 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1215 else:
1216 configString = archConfig
1217
Johnny Chenb40056b2010-09-21 00:09:27 +00001218 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001219 # Translate ' ' to '-' for pathname component.
1220 from string import maketrans
1221 tbl = maketrans(' ', '-')
1222 configPostfix = configString.translate(tbl)
1223
1224 # Check whether we need to split stderr/stdout into configuration
1225 # specific files.
1226 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1227 if new_stderr:
1228 new_stderr.close()
1229 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1230 sys.stderr = new_stderr
1231 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1232 if new_stdout:
1233 new_stdout.close()
1234 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1235 sys.stdout = new_stdout
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001236
Johnny Chen953864a2010-10-12 21:35:54 +00001237 # If we specified a relocated directory to run the test suite, do
1238 # the extra housekeeping to copy the testdirs to a configStringified
1239 # directory and to update sys.path before invoking the test runner.
1240 # The purpose is to separate the configuration-specific directories
1241 # from each other.
1242 if rdir:
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001243 from shutil import copytree, rmtree, ignore_patterns
Johnny Chen953864a2010-10-12 21:35:54 +00001244
Johnny Chen953864a2010-10-12 21:35:54 +00001245 newrdir = "%s.%s" % (rdir, configPostfix)
1246
1247 # Copy the tree to a new directory with postfix name configPostfix.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001248 if os.path.exists(newrdir):
1249 rmtree(newrdir)
Johnny Chen953864a2010-10-12 21:35:54 +00001250 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1251
Filipe Cabecinhas0e1d06d2012-08-08 15:23:24 +00001252 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001253 # level test directory.
1254 #
1255 # See also lldbtest.TestBase.setUpClass(cls).
1256 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1257 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1258 else:
1259 os.environ["LLDB_TEST"] = newrdir
1260
1261 # And update the Python search paths for modules.
1262 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1263
1264 # Output the configuration.
Johnny Chenb40056b2010-09-21 00:09:27 +00001265 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001266
1267 #print "sys.stderr name is", sys.stderr.name
1268 #print "sys.stdout name is", sys.stdout.name
1269
1270 # First, write out the number of collected test cases.
Johnny Chen08967192011-11-18 00:19:29 +00001271 sys.stderr.write(separator + "\n")
1272 sys.stderr.write("Collected %d test%s\n\n"
1273 % (suite.countTestCases(),
1274 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001275
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001276 class LLDBTestResult(unittest2.TextTestResult):
1277 """
Johnny Chen26be4532010-11-09 23:56:14 +00001278 Enforce a singleton pattern to allow introspection of test progress.
1279
1280 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1281 to enable each test instance to track its failure/error status. It
1282 is used in the LLDB test framework to emit detailed trace messages
1283 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001284 """
1285 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001286 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001287
1288 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001289 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001290 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001291 super(LLDBTestResult, self).__init__(*args)
1292 LLDBTestResult.__singleton__ = self
1293 # Now put this singleton into the lldb module namespace.
1294 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001295 # Computes the format string for displaying the counter.
1296 global suite
1297 counterWidth = len(str(suite.countTestCases()))
1298 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001299 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001300 # This counts from 1 .. suite.countTestCases().
1301 self.counter = 0
1302
Johnny Chenbe452272012-04-19 21:33:55 +00001303 def _exc_info_to_string(self, err, test):
1304 """Overrides superclass TestResult's method in order to append
1305 our test config info string to the exception info string."""
1306 modified_exc_string = '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1307 test.getArchitecture(),
1308 test.getCompiler())
1309 return modified_exc_string
1310
Johnny Chenc87fd492011-01-05 22:50:11 +00001311 def getDescription(self, test):
1312 doc_first_line = test.shortDescription()
1313 if self.descriptions and doc_first_line:
1314 return '\n'.join((str(test), self.indentation + doc_first_line))
1315 else:
1316 return str(test)
1317
Enrico Granataac3a8e22012-09-21 19:10:53 +00001318 def getCategoriesForTest(self,test):
1319 if hasattr(test,"getCategories"):
1320 test_categories = test.getCategories()
1321 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1322 test_categories = test.__self__.getCategories()
1323 else:
1324 test_categories = []
1325 if test_categories == None:
1326 test_categories = []
1327 return test_categories
1328
1329 def shouldSkipBecauseOfCategories(self,test):
1330 global useCategories
1331 import inspect
1332 if useCategories:
1333 global categoriesList
1334 test_categories = self.getCategoriesForTest(test)
1335 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
1336 return True
1337 return False
1338
1339 def hardMarkAsSkipped(self,test):
1340 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1341 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
1342
Johnny Chen810042e2011-01-05 20:24:11 +00001343 def startTest(self, test):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001344 if self.shouldSkipBecauseOfCategories(test):
1345 self.hardMarkAsSkipped(test)
Johnny Chen810042e2011-01-05 20:24:11 +00001346 self.counter += 1
1347 if self.showAll:
1348 self.stream.write(self.fmt % self.counter)
1349 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001350
Johnny Chence681462010-10-19 00:25:01 +00001351 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001352 global sdir_has_content
1353 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001354 super(LLDBTestResult, self).addError(test, err)
1355 method = getattr(test, "markError", None)
1356 if method:
1357 method()
1358
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001359 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001360 global sdir_has_content
Enrico Granataac3a8e22012-09-21 19:10:53 +00001361 global failuresPerCategory
Johnny Chen63c2cba2010-10-29 22:20:36 +00001362 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001363 super(LLDBTestResult, self).addFailure(test, err)
1364 method = getattr(test, "markFailure", None)
1365 if method:
1366 method()
Enrico Granataac3a8e22012-09-21 19:10:53 +00001367 if useCategories:
1368 test_categories = self.getCategoriesForTest(test)
1369 for category in test_categories:
1370 if category in failuresPerCategory:
1371 failuresPerCategory[category] = failuresPerCategory[category] + 1
1372 else:
1373 failuresPerCategory[category] = 1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001374
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001375 def addExpectedFailure(self, test, err):
1376 global sdir_has_content
1377 sdir_has_content = True
1378 super(LLDBTestResult, self).addExpectedFailure(test, err)
1379 method = getattr(test, "markExpectedFailure", None)
1380 if method:
1381 method()
1382
Johnny Chenf5b89092011-08-15 23:09:08 +00001383 def addSkip(self, test, reason):
1384 global sdir_has_content
1385 sdir_has_content = True
1386 super(LLDBTestResult, self).addSkip(test, reason)
1387 method = getattr(test, "markSkippedTest", None)
1388 if method:
1389 method()
1390
Johnny Chenab2f0662011-05-06 20:30:22 +00001391 def addUnexpectedSuccess(self, test):
1392 global sdir_has_content
1393 sdir_has_content = True
1394 super(LLDBTestResult, self).addUnexpectedSuccess(test)
1395 method = getattr(test, "markUnexpectedSuccess", None)
1396 if method:
1397 method()
1398
Johnny Chen26be4532010-11-09 23:56:14 +00001399 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001400 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001401 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001402 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001403 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001404 resultclass=LLDBTestResult).run(suite)
1405 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001406 # We are invoking the same test suite more than once. In this case,
1407 # mark __ignore_singleton__ flag as True so the signleton pattern is
1408 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001409 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001410 for i in range(count):
Johnny Chen7d6d8442010-12-03 19:59:35 +00001411 result = unittest2.TextTestRunner(stream=sys.stderr,
Johnny Chene6d88a82012-04-19 20:09:44 +00001412 verbosity=(1 if progress_bar else verbose),
Johnny Chen7d6d8442010-12-03 19:59:35 +00001413 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001414 resultclass=LLDBTestResult).run(suite)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001415
Johnny Chen1bfbd412010-06-29 19:44:16 +00001416
Johnny Chen63c2cba2010-10-29 22:20:36 +00001417if sdir_has_content:
Johnny Chenab2f0662011-05-06 20:30:22 +00001418 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1419 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001420
Enrico Granataac3a8e22012-09-21 19:10:53 +00001421if useCategories and len(failuresPerCategory) > 0:
1422 sys.stderr.write("Failures per category:\n")
1423 for category in failuresPerCategory:
1424 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
1425
Johnny Chena73ad662012-08-16 19:15:21 +00001426fname = os.path.join(sdir_name, "TestFinished")
1427with open(fname, "w") as f:
1428 print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1429
Johnny Chencd0279d2010-09-20 18:07:50 +00001430# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1431# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001432if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001433 print "Terminating Test suite..."
1434 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1435
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001436# Exiting.
1437sys.exit(not result.wasSuccessful)