blob: d4bb9d913e4f4224792f71c1d1c3453709f3bf66 [file] [log] [blame]
Johnny Chen9707bb62010-06-25 21:14:08 +00001#!/usr/bin/env python
2
3"""
4A simple testing framework for lldb using python's unit testing framework.
5
6Tests for lldb are written as python scripts which take advantage of the script
7bridging provided by LLDB.framework to interact with lldb core.
8
9A specific naming pattern is followed by the .py script to be recognized as
10a module which implements a test scenario, namely, Test*.py.
11
12To specify the directories where "Test*.py" python test scripts are located,
13you need to pass in a list of directory names. By default, the current
14working directory is searched if nothing is specified on the command line.
Johnny Chen872aee12010-09-16 15:44:23 +000015
16Type:
17
18./dotest.py -h
19
20for available options.
Johnny Chen9707bb62010-06-25 21:14:08 +000021"""
22
Greg Clayton4793e942012-09-04 15:42:49 +000023import os
24import platform
25import signal
Johnny Chen2891bb02011-09-16 01:04:26 +000026import subprocess
Greg Clayton4793e942012-09-04 15:42:49 +000027import sys
28import textwrap
29import time
Johnny Chen75e28f92010-08-05 23:42:46 +000030import unittest2
Enrico Granatabc0c5a62013-02-08 23:39:18 +000031import progress
Johnny Chen9707bb62010-06-25 21:14:08 +000032
Filipe Cabecinhasd3eb8372013-02-16 09:05:23 +000033if sys.version_info >= (2, 7):
34 argparse = __import__('argparse')
35else:
36 argparse = __import__('argparse_compat')
37
Daniel Maleaf3b68be2013-07-03 18:50:03 +000038def parse_args(parser):
39 """ Returns an argument object. LLDB_TEST_ARGUMENTS environment variable can
40 be used to pass additional arguments if a compatible (>=2.7) argparse
41 library is available.
42 """
43 if sys.version_info >= (2, 7):
44 args = ArgParseNamespace()
45
46 if ('LLDB_TEST_ARGUMENTS' in os.environ):
47 print "Arguments passed through environment: '%s'" % os.environ['LLDB_TEST_ARGUMENTS']
48 args = parser.parse_args([sys.argv[0]].__add__(os.environ['LLDB_TEST_ARGUMENTS'].split()),namespace=args)
49
50 return parser.parse_args(namespace=args)
51 else:
52 return parser.parse_args()
53
Johnny Chen26901c82011-03-11 19:47:23 +000054def is_exe(fpath):
Johnny Chenf2c7b282011-04-26 23:10:51 +000055 """Returns true if fpath is an executable."""
Johnny Chen26901c82011-03-11 19:47:23 +000056 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
57
Johnny Chen26901c82011-03-11 19:47:23 +000058def which(program):
Johnny Chenf2c7b282011-04-26 23:10:51 +000059 """Returns the full path to a program; None otherwise."""
Johnny Chen26901c82011-03-11 19:47:23 +000060 fpath, fname = os.path.split(program)
61 if fpath:
62 if is_exe(program):
63 return program
64 else:
65 for path in os.environ["PATH"].split(os.pathsep):
66 exe_file = os.path.join(path, program)
67 if is_exe(exe_file):
68 return exe_file
69 return None
70
Johnny Chen877c7e42010-08-07 00:16:07 +000071class _WritelnDecorator(object):
72 """Used to decorate file-like objects with a handy 'writeln' method"""
73 def __init__(self,stream):
74 self.stream = stream
75
76 def __getattr__(self, attr):
77 if attr in ('stream', '__getstate__'):
78 raise AttributeError(attr)
79 return getattr(self.stream,attr)
80
81 def writeln(self, arg=None):
82 if arg:
83 self.write(arg)
84 self.write('\n') # text-mode streams translate to \r\n if needed
85
Johnny Chen9707bb62010-06-25 21:14:08 +000086#
87# Global variables:
88#
89
Enrico Granataac3a8e22012-09-21 19:10:53 +000090# Dictionary of categories
91# When you define a new category for your testcases, be sure to add it here, or the test suite
92# will gladly complain as soon as you try to use it. This allows us to centralize which categories
93# exist, and to provide a description for each one
94validCategories = {
95'dataformatters':'Tests related to the type command and the data formatters subsystem',
96'expression':'Tests related to the expression parser',
97'objc':'Tests related to the Objective-C programming language support',
Jim Ingham60139f32013-02-25 23:51:06 +000098'pyapi':'Tests related to the Python API',
Enrico Granata3cb3fe32013-06-18 00:22:27 +000099'basic_process': 'Basic process execution sniff tests.',
100'cmdline' : 'Tests related to the LLDB command-line interface'
Enrico Granataac3a8e22012-09-21 19:10:53 +0000101}
102
Johnny Chen9707bb62010-06-25 21:14:08 +0000103# The test suite.
Johnny Chen75e28f92010-08-05 23:42:46 +0000104suite = unittest2.TestSuite()
Johnny Chen9707bb62010-06-25 21:14:08 +0000105
Johnny Chen4f93bf12010-12-10 00:51:23 +0000106# By default, both command line and Python API tests are performed.
Johnny Chen3ebdacc2010-12-10 18:52:10 +0000107# Use @python_api_test decorator, defined in lldbtest.py, to mark a test as
108# a Python API test.
Johnny Chen4f93bf12010-12-10 00:51:23 +0000109dont_do_python_api_test = False
110
111# By default, both command line and Python API tests are performed.
Johnny Chen4f93bf12010-12-10 00:51:23 +0000112just_do_python_api_test = False
113
Johnny Chen82ccf402011-07-30 01:39:58 +0000114# By default, benchmarks tests are not run.
115just_do_benchmarks_test = False
116
Johnny Chena3ed7d82012-04-06 00:56:05 +0000117# By default, both dsym and dwarf tests are performed.
118# Use @dsym_test or @dwarf_test decorators, defined in lldbtest.py, to mark a test
119# as a dsym or dwarf test. Use '-N dsym' or '-N dwarf' to exclude dsym or dwarf
120# tests from running.
Ed Mastebd5505c2013-06-25 19:59:56 +0000121dont_do_dsym_test = "linux" in sys.platform or "freebsd" in sys.platform
Johnny Chena3ed7d82012-04-06 00:56:05 +0000122dont_do_dwarf_test = False
123
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000124# The blacklist is optional (-b blacklistFile) and allows a central place to skip
125# testclass's and/or testclass.testmethod's.
126blacklist = None
127
128# The dictionary as a result of sourcing blacklistFile.
129blacklistConfig = {}
130
Enrico Granataac3a8e22012-09-21 19:10:53 +0000131# The list of categories we said we care about
132categoriesList = None
133# set to true if we are going to use categories for cherry-picking test cases
134useCategories = False
Stefanus Du Toit2bf96332013-08-01 17:59:20 +0000135# Categories we want to skip
136skipCategories = []
Enrico Granataac3a8e22012-09-21 19:10:53 +0000137# use this to track per-category failures
138failuresPerCategory = {}
139
Sean Callanan0acf4c62012-10-24 22:45:39 +0000140# The path to LLDB.framework is optional.
141lldbFrameworkPath = None
142
143# The path to lldb is optional
144lldbExecutablePath = None
145
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000146# The config file is optional.
147configFile = None
148
Johnny Chend2acdb32010-11-16 22:42:58 +0000149# Test suite repeat count. Can be overwritten with '-# count'.
150count = 1
151
Johnny Chenb40056b2010-09-21 00:09:27 +0000152# The dictionary as a result of sourcing configFile.
153config = {}
Johnny Chenac97a6b2012-04-16 18:55:15 +0000154# The pre_flight and post_flight functions come from reading a config file.
155pre_flight = None
156post_flight = None
Johnny Chenb40056b2010-09-21 00:09:27 +0000157
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000158# The 'archs' and 'compilers' can be specified via either command line or configFile,
Greg Clayton4793e942012-09-04 15:42:49 +0000159# with the command line overriding the configFile. The corresponding options can be
Filipe Cabecinhasd3eb8372013-02-16 09:05:23 +0000160# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386']
Greg Clayton4793e942012-09-04 15:42:49 +0000161# and "-C gcc -C clang" => compilers=['gcc', 'clang'].
162archs = None # Must be initialized after option parsing
163compilers = None # Must be initialized after option parsing
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000164
Johnny Chen1abe4c02012-03-20 00:33:51 +0000165# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
166# the inferior programs. The global variable cflags_extras provides a hook to do
167# just that.
168cflags_extras = ''
169
Johnny Chen91960d32010-09-08 20:56:16 +0000170# Delay startup in order for the debugger to attach.
171delay = False
172
Johnny Chend5362332011-01-29 01:21:04 +0000173# Dump the Python sys.path variable. Use '-D' to dump sys.path.
Johnny Chen50bc6382011-01-29 01:16:52 +0000174dumpSysPath = False
175
Johnny Chene00c9302011-10-10 22:03:44 +0000176# Full path of the benchmark executable, as specified by the '-e' option.
177bmExecutable = None
178# The breakpoint specification of bmExecutable, as specified by the '-x' option.
179bmBreakpointSpec = None
Johnny Chen5f2ed172011-10-20 18:43:28 +0000180# The benchamrk iteration count, as specified by the '-y' option.
181bmIterationCount = -1
Johnny Chene00c9302011-10-10 22:03:44 +0000182
Johnny Chene9eae812012-01-18 05:15:00 +0000183# By default, don't exclude any directories. Use '-X' to add one excluded directory.
184excluded = set(['.svn', '.git'])
185
Johnny Chen7d6d8442010-12-03 19:59:35 +0000186# By default, failfast is False. Use '-F' to overwrite it.
187failfast = False
188
Johnny Chenc5fa0052011-07-29 22:54:56 +0000189# The filters (testclass.testmethod) used to admit tests into our test suite.
190filters = []
Johnny Chenb62436b2010-10-06 20:40:56 +0000191
Johnny Chen38f823c2011-10-11 01:30:27 +0000192# The runhooks is a list of lldb commands specifically for the debugger.
193# Use '-k' to specify a runhook.
194runHooks = []
195
Johnny Chena224cd12010-11-08 01:21:03 +0000196# If '-g' is specified, the filterspec is not exclusive. If a test module does
197# not contain testclass.testmethod which matches the filterspec, the whole test
198# module is still admitted into our test suite. fs4all flag defaults to True.
199fs4all = True
Johnny Chenb62436b2010-10-06 20:40:56 +0000200
Johnny Chenaf149a02010-09-16 17:11:30 +0000201# Ignore the build search path relative to this script to locate the lldb.py module.
202ignore = False
203
Johnny Chen028d8eb2011-11-17 19:57:27 +0000204# By default, we do not skip build and cleanup. Use '-S' option to override.
205skip_build_and_cleanup = False
206
Johnny Chen548aefd2010-10-11 22:25:46 +0000207# By default, we skip long running test case. Use '-l' option to override.
Johnny Chen028d8eb2011-11-17 19:57:27 +0000208skip_long_running_test = True
Johnny Chen41998192010-10-01 22:59:49 +0000209
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000210# By default, we print the build dir, lldb version, and svn info. Use '-n' option to
211# turn it off.
212noHeaders = False
213
Daniel Malea361eb432013-02-15 21:31:37 +0000214# Parsable mode silences headers, and any other output this script might generate, and instead
215# prints machine-readable output similar to what clang tests produce.
216parsable = False
217
Johnny Chen7c52ff12010-09-27 23:29:54 +0000218# The regular expression pattern to match against eligible filenames as our test cases.
219regexp = None
220
Johnny Chen548aefd2010-10-11 22:25:46 +0000221# By default, tests are executed in place and cleanups are performed afterwards.
222# Use '-r dir' option to relocate the tests and their intermediate files to a
223# different directory and to forgo any cleanups. The directory specified must
224# not exist yet.
225rdir = None
226
Johnny Chen125fc2b2010-10-21 16:55:35 +0000227# By default, recorded session info for errored/failed test are dumped into its
228# own file under a session directory named after the timestamp of the test suite
229# run. Use '-s session-dir-name' to specify a specific dir name.
230sdir_name = None
231
Johnny Chen63c2cba2010-10-29 22:20:36 +0000232# Set this flag if there is any session info dumped during the test run.
233sdir_has_content = False
234
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000235# svn_info stores the output from 'svn info lldb.base.dir'.
236svn_info = ''
237
Enrico Granata814c8132013-04-11 23:48:00 +0000238# svn_silent means do not try to obtain svn status
239svn_silent = True
240
Johnny Chen9707bb62010-06-25 21:14:08 +0000241# Default verbosity is 0.
Jim Ingham75f260a2013-02-19 20:39:27 +0000242verbose = 1
Johnny Chen9707bb62010-06-25 21:14:08 +0000243
Johnny Chen08967192011-11-18 00:19:29 +0000244# Set to True only if verbose is 0 and LLDB trace mode is off.
245progress_bar = False
246
Peter Collingbourne61aca482011-06-20 19:06:29 +0000247# By default, search from the script directory.
248testdirs = [ sys.path[0] ]
Johnny Chen9707bb62010-06-25 21:14:08 +0000249
Johnny Chen877c7e42010-08-07 00:16:07 +0000250# Separator string.
251separator = '-' * 70
252
Daniel Malea24765572013-02-20 20:12:11 +0000253failed = False
Johnny Chen9707bb62010-06-25 21:14:08 +0000254
Greg Clayton4793e942012-09-04 15:42:49 +0000255def usage(parser):
256 parser.print_help()
Jim Ingham4f347cb2011-04-13 21:11:41 +0000257 if verbose > 0:
258 print """
Johnny Chen9656ab22010-10-22 19:00:18 +0000259Examples:
260
Johnny Chena224cd12010-11-08 01:21:03 +0000261This is an example of using the -f option to pinpoint to a specfic test class
262and test method to be run:
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000263
Johnny Chena224cd12010-11-08 01:21:03 +0000264$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000265----------------------------------------------------------------------
266Collected 1 test
267
268test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
269Test 'frame variable this' when stopped on a class constructor. ... ok
270
271----------------------------------------------------------------------
272Ran 1 test in 1.396s
273
274OK
Johnny Chen9656ab22010-10-22 19:00:18 +0000275
276And this is an example of using the -p option to run a single file (the filename
277matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
278
279$ ./dotest.py -v -p ObjC
280----------------------------------------------------------------------
281Collected 4 tests
282
283test_break_with_dsym (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000284Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000285test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000286Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
Johnny Chen9656ab22010-10-22 19:00:18 +0000287test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
288Lookup objective-c data types and evaluate expressions. ... ok
289test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
290Lookup objective-c data types and evaluate expressions. ... ok
291
292----------------------------------------------------------------------
293Ran 4 tests in 16.661s
294
295OK
Johnny Chen6ad7e5e2010-10-21 00:47:52 +0000296
Johnny Chen58f93922010-06-29 23:10:39 +0000297Running of this script also sets up the LLDB_TEST environment variable so that
Johnny Chenaf149a02010-09-16 17:11:30 +0000298individual test cases can locate their supporting files correctly. The script
299tries to set up Python's search paths for modules by looking at the build tree
Johnny Chena85859f2010-11-11 22:14:56 +0000300relative to this script. See also the '-i' option in the following example.
301
302Finally, this is an example of using the lldb.py module distributed/installed by
303Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
304option to add some delay between two tests. It uses ARCH=x86_64 to specify that
305as the architecture and CC=clang to specify the compiler used for the test run:
306
307$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
308
309Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
310----------------------------------------------------------------------
311Collected 2 tests
312
313test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
314Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
315test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
316Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
317
318----------------------------------------------------------------------
319Ran 2 tests in 5.659s
320
321OK
322
323The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
324notify the directory containing the session logs for test failures or errors.
325In case there is any test failure/error, a similar message is appended at the
326end of the stderr output for your convenience.
Johnny Chenfde69bc2010-09-14 22:01:40 +0000327
328Environment variables related to loggings:
329
330o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
331 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
332
333o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
334 'process.gdb-remote' subsystem with a default option of 'packets' if
335 GDB_REMOTE_LOG_OPTION is not defined.
Johnny Chen9707bb62010-06-25 21:14:08 +0000336"""
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000337 sys.exit(0)
Johnny Chen9707bb62010-06-25 21:14:08 +0000338
339
Enrico Granata69d7c102013-05-07 00:36:28 +0000340def unique_string_match(yourentry,list):
341 candidate = None
342 for item in list:
343 if item.startswith(yourentry):
344 if candidate:
345 return None
346 candidate = item
347 return candidate
348
Enrico Granata6fa3c502013-06-22 00:15:25 +0000349class ArgParseNamespace(object):
350 pass
351
Stefanus Du Toit2bf96332013-08-01 17:59:20 +0000352def validate_categories(categories):
353 """For each category in categories, ensure that it's a valid category (or a prefix thereof).
354 If a category is invalid, print a message and quit.
355 If all categories are valid, return the list of categories. Prefixes are expanded in the
356 returned list.
357 """
358 global validCategories
359 result = []
360 for category in categories:
361 origCategory = category
362 if category not in validCategories:
363 category = unique_string_match(category, validCategories)
364 if (category not in validCategories) or category == None:
365 print "fatal error: category '" + origCategory + "' is not a valid category"
366 print "if you have added a new category, please edit dotest.py, adding your new category to validCategories"
367 print "else, please specify one or more of the following: " + str(validCategories.keys())
368 sys.exit(1)
369 result.append(category)
370 return result
371
Johnny Chenaf149a02010-09-16 17:11:30 +0000372def parseOptionsAndInitTestdirs():
373 """Initialize the list of directories containing our unittest scripts.
374
375 '-h/--help as the first option prints out usage info and exit the program.
376 """
377
Johnny Chen4f93bf12010-12-10 00:51:23 +0000378 global dont_do_python_api_test
379 global just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +0000380 global just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +0000381 global dont_do_dsym_test
382 global dont_do_dwarf_test
Johnny Chen82e6b1e2010-12-01 22:47:54 +0000383 global blacklist
384 global blacklistConfig
Enrico Granataac3a8e22012-09-21 19:10:53 +0000385 global categoriesList
386 global validCategories
387 global useCategories
Stefanus Du Toit2bf96332013-08-01 17:59:20 +0000388 global skipCategories
Sean Callanan0acf4c62012-10-24 22:45:39 +0000389 global lldbFrameworkPath
390 global lldbExecutablePath
Johnny Chen9fdb0a92010-09-18 00:16:47 +0000391 global configFile
Johnny Chen1a4d5e72011-03-04 01:35:22 +0000392 global archs
393 global compilers
Johnny Chend2acdb32010-11-16 22:42:58 +0000394 global count
Johnny Chenaf149a02010-09-16 17:11:30 +0000395 global delay
Johnny Chen50bc6382011-01-29 01:16:52 +0000396 global dumpSysPath
Johnny Chene00c9302011-10-10 22:03:44 +0000397 global bmExecutable
398 global bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +0000399 global bmIterationCount
Johnny Chen7d6d8442010-12-03 19:59:35 +0000400 global failfast
Johnny Chenc5fa0052011-07-29 22:54:56 +0000401 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +0000402 global fs4all
Johnny Chen7c52ff12010-09-27 23:29:54 +0000403 global ignore
Johnny Chen08967192011-11-18 00:19:29 +0000404 global progress_bar
Johnny Chen38f823c2011-10-11 01:30:27 +0000405 global runHooks
Johnny Chen028d8eb2011-11-17 19:57:27 +0000406 global skip_build_and_cleanup
407 global skip_long_running_test
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000408 global noHeaders
Daniel Malea361eb432013-02-15 21:31:37 +0000409 global parsable
Johnny Chen7c52ff12010-09-27 23:29:54 +0000410 global regexp
Johnny Chen548aefd2010-10-11 22:25:46 +0000411 global rdir
Johnny Chen125fc2b2010-10-21 16:55:35 +0000412 global sdir_name
Enrico Granata814c8132013-04-11 23:48:00 +0000413 global svn_silent
Johnny Chenaf149a02010-09-16 17:11:30 +0000414 global verbose
415 global testdirs
416
Jim Ingham4f347cb2011-04-13 21:11:41 +0000417 do_help = False
418
Greg Clayton4793e942012-09-04 15:42:49 +0000419 parser = argparse.ArgumentParser(description='description', prefix_chars='+-', add_help=False)
420 group = None
Johnny Chenaf149a02010-09-16 17:11:30 +0000421
Greg Clayton4793e942012-09-04 15:42:49 +0000422 # Helper function for boolean options (group will point to the current group when executing X)
423 X = lambda optstr, helpstr, **kwargs: group.add_argument(optstr, help=helpstr, action='store_true', **kwargs)
424
425 group = parser.add_argument_group('Help')
426 group.add_argument('-h', '--help', dest='h', action='store_true', help="Print this help message and exit. Add '-v' for more detailed help.")
427
428 # C and Python toolchain options
429 group = parser.add_argument_group('Toolchain options')
430 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'''))
431 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.'''))
432 # FIXME? This won't work for different extra flags according to each arch.
433 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
434 suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures'''))
435 X('-D', 'Dump the Python sys.path variable')
436
437 # Test filtering options
438 group = parser.add_argument_group('Test filtering options')
439 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")
440 X('-a', "Don't do lldb Python API tests")
441 X('+a', "Just do lldb Python API tests. Do not specify along with '+a'", dest='plus_a')
442 X('+b', 'Just do benchmark tests', dest='plus_b')
443 group.add_argument('-b', metavar='blacklist', help='Read a blacklist file specified after this option')
Enrico Granata58b03a42012-12-14 00:07:09 +0000444 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 +0000445 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')
446 X('-l', "Don't skip long running tests")
447 group.add_argument('-p', metavar='pattern', help='Specify a regexp filename pattern for inclusion in the test suite')
448 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 +0000449 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.'''))
Stefanus Du Toit2bf96332013-08-01 17:59:20 +0000450 group.add_argument('--skip-category', metavar='category', action='append', dest='skipCategories', help=textwrap.dedent('''Specify categories of test cases to skip. Takes precedence over -G. Can be specified more than once.'''))
Greg Clayton4793e942012-09-04 15:42:49 +0000451
452 # Configuration options
453 group = parser.add_argument_group('Configuration options')
454 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 +0000455 group.add_argument('--framework', metavar='framework-path', help='The path to LLDB.framework')
456 group.add_argument('--executable', metavar='executable-path', help='The path to the lldb executable')
Greg Clayton4793e942012-09-04 15:42:49 +0000457 group.add_argument('-e', metavar='benchmark-exe', help='Specify the full path of an executable used for benchmark purposes (see also: -x)')
458 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")
459 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')
460 group.add_argument('-r', metavar='dir', help="Similar to '-R', except that the directory must not exist before running this test driver")
461 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')
462 group.add_argument('-x', metavar='breakpoint-spec', help='Specify the breakpoint specification for the benchmark executable')
463 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.")
464 group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times')
465
466 # Test-suite behaviour
467 group = parser.add_argument_group('Runtime behaviour options')
468 X('-d', 'Delay startup for 10 seconds (in order for the debugger to attach)')
469 X('-F', 'Fail fast. Stop the test suite on the first error/failure')
470 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")
471 X('-n', "Don't print the headers like build dir, lldb version, and svn info at all")
Jim Ingham75f260a2013-02-19 20:39:27 +0000472 X('-P', "Use the graphic progress bar.")
Daniel Malea361eb432013-02-15 21:31:37 +0000473 X('-q', "Don't print extra output from this script.")
Greg Clayton4793e942012-09-04 15:42:49 +0000474 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")
475 X('-t', 'Turn on tracing of lldb command and other detailed test executions')
Greg Claytonb85785c2013-02-08 21:52:32 +0000476 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 +0000477 X('-v', 'Do verbose mode of unittest framework (print out each test case invocation)')
478 X('-w', 'Insert some wait time (currently 0.5 sec) between consecutive test cases')
Enrico Granata814c8132013-04-11 23:48:00 +0000479 X('-T', 'Obtain and dump svn information for this checkout of LLDB (off by default)')
Greg Clayton4793e942012-09-04 15:42:49 +0000480
481 # Remove the reference to our helper function
482 del X
483
484 group = parser.add_argument_group('Test directories')
485 group.add_argument('args', metavar='test-dir', nargs='*', help='Specify a list of directory names to search for test modules named after Test*.py (test discovery). If empty, search from the current working directory instead.')
Enrico Granata6fa3c502013-06-22 00:15:25 +0000486
Daniel Maleaf3b68be2013-07-03 18:50:03 +0000487 args = parse_args(parser)
Greg Clayton4793e942012-09-04 15:42:49 +0000488 platform_system = platform.system()
489 platform_machine = platform.machine()
Enrico Granata2d329242012-10-23 22:52:49 +0000490
Greg Claytonb85785c2013-02-08 21:52:32 +0000491 if args.unset_env_varnames:
492 for env_var in args.unset_env_varnames:
493 if env_var in os.environ:
494 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
495 # is automatically translated into a corresponding call to unsetenv().
496 del os.environ[env_var]
497 #os.unsetenv(env_var)
498
Daniel Malea361eb432013-02-15 21:31:37 +0000499 # only print the args if being verbose (and parsable is off)
500 if args.v and not args.q:
Enrico Granatab0cb21e2013-06-29 01:53:55 +0000501 print sys.argv
Greg Clayton4793e942012-09-04 15:42:49 +0000502
503 if args.h:
504 do_help = True
505
506 if args.archs:
507 archs = args.archs
508 else:
509 if platform_system == 'Darwin' and platform_machine == 'x86_64':
510 archs = ['x86_64', 'i386']
Johnny Chenaf149a02010-09-16 17:11:30 +0000511 else:
Greg Clayton4793e942012-09-04 15:42:49 +0000512 archs = [platform_machine]
513
Enrico Granataac3a8e22012-09-21 19:10:53 +0000514 if args.categoriesList:
Stefanus Du Toit2bf96332013-08-01 17:59:20 +0000515 categoriesList = set(validate_categories(args.categoriesList))
Enrico Granataac3a8e22012-09-21 19:10:53 +0000516 useCategories = True
517 else:
518 categoriesList = []
519
Stefanus Du Toit2bf96332013-08-01 17:59:20 +0000520 if args.skipCategories:
521 skipCategories = validate_categories(args.skipCategories)
522
Greg Clayton4793e942012-09-04 15:42:49 +0000523 if args.compilers:
524 compilers = args.compilers
525 else:
526 compilers = ['clang']
527
528 if args.D:
529 dumpSysPath = True
530
531 if args.E:
532 cflags_extras = args.E
533 os.environ['CFLAGS_EXTRAS'] = cflags_extras
534
535 # argparse makes sure we have correct options
536 if args.N == 'dwarf':
537 dont_do_dwarf_test = True
538 elif args.N == 'dsym':
539 dont_do_dsym_test = True
540
541 if args.a:
542 dont_do_python_api_test = True
543
544 if args.plus_a:
545 if dont_do_python_api_test:
546 print "Warning: -a and +a can't both be specified! Using only -a"
547 else:
548 just_do_python_api_test = True
549
550 if args.plus_b:
551 just_do_benchmarks_test = True
552
553 if args.b:
554 if args.b.startswith('-'):
555 usage(parser)
556 blacklistFile = args.b
557 if not os.path.isfile(blacklistFile):
558 print 'Blacklist file:', blacklistFile, 'does not exist!'
559 usage(parser)
560 # Now read the blacklist contents and assign it to blacklist.
561 execfile(blacklistFile, globals(), blacklistConfig)
562 blacklist = blacklistConfig.get('blacklist')
563
564 if args.c:
565 if args.c.startswith('-'):
566 usage(parser)
567 configFile = args.c
568 if not os.path.isfile(configFile):
569 print 'Config file:', configFile, 'does not exist!'
570 usage(parser)
571
572 if args.d:
573 delay = True
574
575 if args.e:
576 if args.e.startswith('-'):
577 usage(parser)
578 bmExecutable = args.e
579 if not is_exe(bmExecutable):
580 usage(parser)
581
582 if args.F:
583 failfast = True
584
585 if args.f:
Enrico Granata58b03a42012-12-14 00:07:09 +0000586 if any([x.startswith('-') for x in args.f]):
Greg Clayton4793e942012-09-04 15:42:49 +0000587 usage(parser)
Enrico Granata58b03a42012-12-14 00:07:09 +0000588 filters.extend(args.f)
Greg Clayton4793e942012-09-04 15:42:49 +0000589
590 if args.g:
591 fs4all = False
592
593 if args.i:
594 ignore = True
595
596 if args.k:
597 runHooks.extend(args.k)
598
599 if args.l:
600 skip_long_running_test = False
601
Sean Callanan0acf4c62012-10-24 22:45:39 +0000602 if args.framework:
603 lldbFrameworkPath = args.framework
604
605 if args.executable:
606 lldbExecutablePath = args.executable
607
Greg Clayton4793e942012-09-04 15:42:49 +0000608 if args.n:
609 noHeaders = True
610
611 if args.p:
612 if args.p.startswith('-'):
613 usage(parser)
614 regexp = args.p
615
Daniel Malea361eb432013-02-15 21:31:37 +0000616 if args.q:
617 noHeaders = True
618 parsable = True
619
Jim Ingham75f260a2013-02-19 20:39:27 +0000620 if args.P:
621 progress_bar = True
622 verbose = 0
623
Greg Clayton4793e942012-09-04 15:42:49 +0000624 if args.R:
625 if args.R.startswith('-'):
626 usage(parser)
627 rdir = os.path.abspath(args.R)
628 if os.path.exists(rdir):
629 import shutil
630 print 'Removing tree:', rdir
631 shutil.rmtree(rdir)
632
633 if args.r:
634 if args.r.startswith('-'):
635 usage(parser)
636 rdir = os.path.abspath(args.r)
637 if os.path.exists(rdir):
638 print 'Relocated directory:', rdir, 'must not exist!'
639 usage(parser)
640
641 if args.S:
642 skip_build_and_cleanup = True
643
644 if args.s:
645 if args.s.startswith('-'):
646 usage(parser)
647 sdir_name = args.s
648
649 if args.t:
650 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
651
Enrico Granata814c8132013-04-11 23:48:00 +0000652 if args.T:
653 svn_silent = False
654
Greg Clayton4793e942012-09-04 15:42:49 +0000655 if args.v:
656 verbose = 2
657
658 if args.w:
659 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES'
660
661 if args.X:
662 if args.X.startswith('-'):
663 usage(parser)
664 excluded.add(args.X)
665
666 if args.x:
667 if args.x.startswith('-'):
668 usage(parser)
669 bmBreakpointSpec = args.x
670
671 # argparse makes sure we have a number
672 if args.y:
673 bmIterationCount = args.y
674
675 # argparse makes sure we have a number
676 if args.sharp:
677 count = args.sharp
Johnny Chenaf149a02010-09-16 17:11:30 +0000678
Jim Ingham4f347cb2011-04-13 21:11:41 +0000679 if do_help == True:
Greg Clayton4793e942012-09-04 15:42:49 +0000680 usage(parser)
Jim Ingham4f347cb2011-04-13 21:11:41 +0000681
Johnny Chencc659ad2010-12-10 19:02:23 +0000682 # Do not specify both '-a' and '+a' at the same time.
683 if dont_do_python_api_test and just_do_python_api_test:
Greg Clayton4793e942012-09-04 15:42:49 +0000684 usage(parser)
Johnny Chencc659ad2010-12-10 19:02:23 +0000685
Johnny Chenaf149a02010-09-16 17:11:30 +0000686 # Gather all the dirs passed on the command line.
Greg Clayton4793e942012-09-04 15:42:49 +0000687 if len(args.args) > 0:
688 testdirs = map(os.path.abspath, args.args)
Johnny Chenaf149a02010-09-16 17:11:30 +0000689
Johnny Chen548aefd2010-10-11 22:25:46 +0000690 # If '-r dir' is specified, the tests should be run under the relocated
691 # directory. Let's copy the testdirs over.
692 if rdir:
693 from shutil import copytree, ignore_patterns
694
695 tmpdirs = []
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000696 orig_testdirs = testdirs[:]
Johnny Chen548aefd2010-10-11 22:25:46 +0000697 for srcdir in testdirs:
Johnny Chen1abe4c02012-03-20 00:33:51 +0000698 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
699 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
700 # Utilize the relative path to the 'test' directory to make our destination dir path.
Greg Clayton4793e942012-09-04 15:42:49 +0000701 if ("test" + os.sep) in srcdir:
702 to_split_on = "test" + os.sep
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000703 else:
704 to_split_on = "test"
705 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1])
706 dstdir = dstdir.rstrip(os.sep)
Johnny Chen548aefd2010-10-11 22:25:46 +0000707 # Don't copy the *.pyc and .svn stuffs.
708 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
709 tmpdirs.append(dstdir)
710
711 # This will be our modified testdirs.
712 testdirs = tmpdirs
713
714 # With '-r dir' specified, there's no cleanup of intermediate test files.
715 os.environ["LLDB_DO_CLEANUP"] = 'NO'
716
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000717 # If the original testdirs is ['test'], the make directory has already been copied
Johnny Chen548aefd2010-10-11 22:25:46 +0000718 # recursively and is contained within the rdir/test dir. For anything
719 # else, we would need to copy over the make directory and its contents,
720 # so that, os.listdir(rdir) looks like, for example:
721 #
722 # array_types conditional_break make
723 #
724 # where the make directory contains the Makefile.rules file.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +0000725 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000726 scriptdir = os.path.dirname(__file__)
Johnny Chen548aefd2010-10-11 22:25:46 +0000727 # Don't copy the .svn stuffs.
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000728 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
Johnny Chen548aefd2010-10-11 22:25:46 +0000729 ignore=ignore_patterns('.svn'))
730
731 #print "testdirs:", testdirs
732
Johnny Chenb40056b2010-09-21 00:09:27 +0000733 # Source the configFile if specified.
734 # The side effect, if any, will be felt from this point on. An example
735 # config file may be these simple two lines:
736 #
737 # sys.stderr = open("/tmp/lldbtest-stderr", "w")
738 # sys.stdout = open("/tmp/lldbtest-stdout", "w")
739 #
740 # which will reassign the two file objects to sys.stderr and sys.stdout,
741 # respectively.
742 #
Johnny Chen8c130642012-08-22 17:53:02 +0000743 # See also lldb-trunk/examples/test/usage-config.
Johnny Chenac97a6b2012-04-16 18:55:15 +0000744 global config, pre_flight, post_flight
Johnny Chenb40056b2010-09-21 00:09:27 +0000745 if configFile:
746 # Pass config (a dictionary) as the locals namespace for side-effect.
747 execfile(configFile, globals(), config)
Johnny Chenac97a6b2012-04-16 18:55:15 +0000748 print "config:", config
749 if "pre_flight" in config:
750 pre_flight = config["pre_flight"]
751 if not callable(pre_flight):
752 print "fatal error: pre_flight is not callable, exiting."
753 sys.exit(1)
754 if "post_flight" in config:
755 post_flight = config["post_flight"]
756 if not callable(post_flight):
757 print "fatal error: post_flight is not callable, exiting."
758 sys.exit(1)
Johnny Chenb40056b2010-09-21 00:09:27 +0000759 #print "sys.stderr:", sys.stderr
760 #print "sys.stdout:", sys.stdout
761
Johnny Chenaf149a02010-09-16 17:11:30 +0000762
Johnny Chen9707bb62010-06-25 21:14:08 +0000763def setupSysPath():
Johnny Chen8a3c0432011-03-11 20:13:06 +0000764 """
765 Add LLDB.framework/Resources/Python to the search paths for modules.
766 As a side effect, we also discover the 'lldb' executable and export it here.
767 """
Johnny Chen9707bb62010-06-25 21:14:08 +0000768
Johnny Chen548aefd2010-10-11 22:25:46 +0000769 global rdir
770 global testdirs
Johnny Chen50bc6382011-01-29 01:16:52 +0000771 global dumpSysPath
Johnny Chenfe5f1ed2011-10-21 18:33:27 +0000772 global noHeaders
Johnny Chenb5fe80c2011-05-17 22:58:50 +0000773 global svn_info
Enrico Granata814c8132013-04-11 23:48:00 +0000774 global svn_silent
Sean Callanan0acf4c62012-10-24 22:45:39 +0000775 global lldbFrameworkPath
776 global lldbExecutablePath
Johnny Chen548aefd2010-10-11 22:25:46 +0000777
Johnny Chen9707bb62010-06-25 21:14:08 +0000778 # Get the directory containing the current script.
Johnny Chen4d162e52011-08-12 18:54:11 +0000779 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 +0000780 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
781 else:
782 scriptPath = sys.path[0]
Johnny Chena1affab2010-07-03 03:41:59 +0000783 if not scriptPath.endswith('test'):
Johnny Chen9707bb62010-06-25 21:14:08 +0000784 print "This script expects to reside in lldb's test directory."
785 sys.exit(-1)
786
Johnny Chen548aefd2010-10-11 22:25:46 +0000787 if rdir:
788 # Set up the LLDB_TEST environment variable appropriately, so that the
789 # individual tests can be located relatively.
790 #
791 # See also lldbtest.TestBase.setUpClass(cls).
792 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
793 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test')
794 else:
795 os.environ["LLDB_TEST"] = rdir
796 else:
797 os.environ["LLDB_TEST"] = scriptPath
Peter Collingbournef6c3de82011-06-20 19:06:45 +0000798
799 # Set up the LLDB_SRC environment variable, so that the tests can locate
800 # the LLDB source code.
801 os.environ["LLDB_SRC"] = os.path.join(sys.path[0], os.pardir)
802
Johnny Chen9de4ede2010-08-31 17:42:54 +0000803 pluginPath = os.path.join(scriptPath, 'plugins')
Johnny Chen8a3c0432011-03-11 20:13:06 +0000804 pexpectPath = os.path.join(scriptPath, 'pexpect-2.4')
Johnny Chen58f93922010-06-29 23:10:39 +0000805
Johnny Chen8a3c0432011-03-11 20:13:06 +0000806 # Append script dir, plugin dir, and pexpect dir to the sys.path.
Johnny Chenaf149a02010-09-16 17:11:30 +0000807 sys.path.append(scriptPath)
808 sys.path.append(pluginPath)
Johnny Chen8a3c0432011-03-11 20:13:06 +0000809 sys.path.append(pexpectPath)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000810
Johnny Chen26901c82011-03-11 19:47:23 +0000811 # This is our base name component.
Johnny Chena1affab2010-07-03 03:41:59 +0000812 base = os.path.abspath(os.path.join(scriptPath, os.pardir))
Johnny Chen6a564a42011-02-15 18:50:19 +0000813
Johnny Chen26901c82011-03-11 19:47:23 +0000814 # These are for xcode build directories.
Johnny Chen6a564a42011-02-15 18:50:19 +0000815 xcode3_build_dir = ['build']
816 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
817 dbg = ['Debug']
Sean Callanand9d94632012-09-26 21:16:15 +0000818 dbc = ['DebugClang']
Johnny Chen6a564a42011-02-15 18:50:19 +0000819 rel = ['Release']
820 bai = ['BuildAndIntegration']
821 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
Johnny Chen26901c82011-03-11 19:47:23 +0000822
823 # Some of the tests can invoke the 'lldb' command directly.
824 # We'll try to locate the appropriate executable right here.
825
Sean Callanan0acf4c62012-10-24 22:45:39 +0000826 lldbExec = None
827 if lldbExecutablePath:
828 if is_exe(lldbExecutablePath):
829 lldbExec = lldbExecutablePath
Sean Callanan502000d2012-11-01 21:23:21 +0000830 lldbHere = lldbExec
Sean Callanan0acf4c62012-10-24 22:45:39 +0000831 else:
832 print lldbExecutablePath + " is not an executable"
833 sys.exit(-1)
Johnny Chen6033bed2011-08-26 00:00:01 +0000834 else:
Sean Callanan0acf4c62012-10-24 22:45:39 +0000835 # First, you can define an environment variable LLDB_EXEC specifying the
836 # full pathname of the lldb executable.
837 if "LLDB_EXEC" in os.environ and is_exe(os.environ["LLDB_EXEC"]):
838 lldbExec = os.environ["LLDB_EXEC"]
839 else:
840 lldbExec = None
841
842 executable = ['lldb']
843 dbgExec = os.path.join(base, *(xcode3_build_dir + dbg + executable))
844 dbgExec2 = os.path.join(base, *(xcode4_build_dir + dbg + executable))
845 dbcExec = os.path.join(base, *(xcode3_build_dir + dbc + executable))
846 dbcExec2 = os.path.join(base, *(xcode4_build_dir + dbc + executable))
847 relExec = os.path.join(base, *(xcode3_build_dir + rel + executable))
848 relExec2 = os.path.join(base, *(xcode4_build_dir + rel + executable))
849 baiExec = os.path.join(base, *(xcode3_build_dir + bai + executable))
850 baiExec2 = os.path.join(base, *(xcode4_build_dir + bai + executable))
851
852 # The 'lldb' executable built here in the source tree.
853 lldbHere = None
854 if is_exe(dbgExec):
855 lldbHere = dbgExec
856 elif is_exe(dbgExec2):
857 lldbHere = dbgExec2
858 elif is_exe(dbcExec):
859 lldbHere = dbcExec
860 elif is_exe(dbcExec2):
861 lldbHere = dbcExec2
862 elif is_exe(relExec):
863 lldbHere = relExec
864 elif is_exe(relExec2):
865 lldbHere = relExec2
866 elif is_exe(baiExec):
867 lldbHere = baiExec
868 elif is_exe(baiExec2):
869 lldbHere = baiExec2
870 elif lldbExec:
871 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000872
Sean Callanan0acf4c62012-10-24 22:45:39 +0000873 # One last chance to locate the 'lldb' executable.
874 if not lldbExec:
875 lldbExec = which('lldb')
876 if lldbHere and not lldbExec:
877 lldbExec = lldbHere
Daniel Malea2777b012013-02-06 16:55:07 +0000878 if lldbExec and not lldbHere:
879 lldbHere = lldbExec
Sean Callanan502000d2012-11-01 21:23:21 +0000880
881 if lldbHere:
882 os.environ["LLDB_HERE"] = lldbHere
Matt Kopeca964b092013-02-20 20:54:10 +0000883 os.environ["LLDB_LIB_DIR"] = os.path.split(lldbHere)[0]
Sean Callanan502000d2012-11-01 21:23:21 +0000884 if not noHeaders:
Matt Kopeca964b092013-02-20 20:54:10 +0000885 print "LLDB library dir:", os.environ["LLDB_LIB_DIR"]
Sean Callanan502000d2012-11-01 21:23:21 +0000886 os.system('%s -v' % lldbHere)
Johnny Chen26901c82011-03-11 19:47:23 +0000887
888 if not lldbExec:
889 print "The 'lldb' executable cannot be located. Some of the tests may not be run as a result."
890 else:
891 os.environ["LLDB_EXEC"] = lldbExec
Johnny Chen8904eb02011-10-28 00:59:00 +0000892 #print "The 'lldb' from PATH env variable", lldbExec
Filipe Cabecinhasc0566642012-08-08 15:05:04 +0000893
Daniel Malea2b606ab2013-03-13 20:50:05 +0000894 # Skip printing svn/git information when running in parsable (lit-test compatibility) mode
Enrico Granata814c8132013-04-11 23:48:00 +0000895 if not svn_silent and not parsable:
Daniel Malea2b606ab2013-03-13 20:50:05 +0000896 if os.path.isdir(os.path.join(base, '.svn')) and which("svn") is not None:
897 pipe = subprocess.Popen([which("svn"), "info", base], stdout = subprocess.PIPE)
898 svn_info = pipe.stdout.read()
899 elif os.path.isdir(os.path.join(base, '.git')) and which("git") is not None:
900 pipe = subprocess.Popen([which("git"), "svn", "info", base], stdout = subprocess.PIPE)
901 svn_info = pipe.stdout.read()
902 if not noHeaders:
903 print svn_info
Johnny Chen26901c82011-03-11 19:47:23 +0000904
905 global ignore
906
Johnny Chen9707bb62010-06-25 21:14:08 +0000907 lldbPath = None
Sean Callanan0acf4c62012-10-24 22:45:39 +0000908 if lldbFrameworkPath:
909 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python')
910 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
911 lldbPath = candidatePath
912 if not lldbPath:
913 print 'Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath
914 sys.exit(-1)
915 else:
916 # The '-i' option is used to skip looking for lldb.py in the build tree.
917 if ignore:
918 return
Jim Inghamaa93c932012-12-21 22:22:26 +0000919
920 # If our lldb supports the -P option, use it to find the python path:
921 init_in_python_dir = 'lldb/__init__.py'
922 import pexpect
923 lldb_dash_p_result = None
924
925 if lldbHere:
926 lldb_dash_p_result = pexpect.run("%s -P"%(lldbHere))
927 elif lldbExec:
928 lldb_dash_p_result = pexpect.run("%s -P"%(lldbExec))
929
930 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")):
931 lines = lldb_dash_p_result.splitlines()
932 if len(lines) == 1 and os.path.isfile(os.path.join(lines[0], init_in_python_dir)):
933 lldbPath = lines[0]
Daniel Malea21e32a62013-01-04 23:35:13 +0000934 if "linux" in sys.platform:
Matt Kopeca964b092013-02-20 20:54:10 +0000935 os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPath, '..', '..')
Jim Inghamaa93c932012-12-21 22:22:26 +0000936
937 if not lldbPath:
938 dbgPath = os.path.join(base, *(xcode3_build_dir + dbg + python_resource_dir))
939 dbgPath2 = os.path.join(base, *(xcode4_build_dir + dbg + python_resource_dir))
940 dbcPath = os.path.join(base, *(xcode3_build_dir + dbc + python_resource_dir))
941 dbcPath2 = os.path.join(base, *(xcode4_build_dir + dbc + python_resource_dir))
942 relPath = os.path.join(base, *(xcode3_build_dir + rel + python_resource_dir))
943 relPath2 = os.path.join(base, *(xcode4_build_dir + rel + python_resource_dir))
944 baiPath = os.path.join(base, *(xcode3_build_dir + bai + python_resource_dir))
945 baiPath2 = os.path.join(base, *(xcode4_build_dir + bai + python_resource_dir))
Sean Callanan0acf4c62012-10-24 22:45:39 +0000946
Jim Inghamaa93c932012-12-21 22:22:26 +0000947 if os.path.isfile(os.path.join(dbgPath, init_in_python_dir)):
948 lldbPath = dbgPath
949 elif os.path.isfile(os.path.join(dbgPath2, init_in_python_dir)):
950 lldbPath = dbgPath2
951 elif os.path.isfile(os.path.join(dbcPath, init_in_python_dir)):
952 lldbPath = dbcPath
953 elif os.path.isfile(os.path.join(dbcPath2, init_in_python_dir)):
954 lldbPath = dbcPath2
955 elif os.path.isfile(os.path.join(relPath, init_in_python_dir)):
956 lldbPath = relPath
957 elif os.path.isfile(os.path.join(relPath2, init_in_python_dir)):
958 lldbPath = relPath2
959 elif os.path.isfile(os.path.join(baiPath, init_in_python_dir)):
960 lldbPath = baiPath
961 elif os.path.isfile(os.path.join(baiPath2, init_in_python_dir)):
962 lldbPath = baiPath2
963
Sean Callanan0acf4c62012-10-24 22:45:39 +0000964 if not lldbPath:
965 print 'This script requires lldb.py to be in either ' + dbgPath + ',',
966 print relPath + ', or ' + baiPath
967 sys.exit(-1)
Johnny Chen9707bb62010-06-25 21:14:08 +0000968
Jim Inghamaa93c932012-12-21 22:22:26 +0000969 # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
970 # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
971 (before, frameWithVersion, after) = lldbPath.rpartition("LLDB.framework/Versions/A")
972 if frameWithVersion != "" :
973 lldbPath = before + "LLDB.framework" + after
974
Enrico Granata0ad92972013-04-11 23:40:59 +0000975 lldbPath = os.path.abspath(lldbPath)
976
Enrico Granata01458ca2012-10-23 00:09:02 +0000977 # If tests need to find LLDB_FRAMEWORK, now they can do it
978 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPath))
979
Johnny Chenaf149a02010-09-16 17:11:30 +0000980 # This is to locate the lldb.py module. Insert it right after sys.path[0].
981 sys.path[1:1] = [lldbPath]
Johnny Chen50bc6382011-01-29 01:16:52 +0000982 if dumpSysPath:
983 print "sys.path:", sys.path
Johnny Chen9707bb62010-06-25 21:14:08 +0000984
Johnny Chen9707bb62010-06-25 21:14:08 +0000985
Johnny Chencd0279d2010-09-20 18:07:50 +0000986def doDelay(delta):
987 """Delaying startup for delta-seconds to facilitate debugger attachment."""
988 def alarm_handler(*args):
989 raise Exception("timeout")
990
991 signal.signal(signal.SIGALRM, alarm_handler)
992 signal.alarm(delta)
993 sys.stdout.write("pid=%d\n" % os.getpid())
994 sys.stdout.write("Enter RET to proceed (or timeout after %d seconds):" %
995 delta)
996 sys.stdout.flush()
997 try:
998 text = sys.stdin.readline()
999 except:
1000 text = ""
1001 signal.alarm(0)
1002 sys.stdout.write("proceeding...\n")
1003 pass
1004
1005
Johnny Chen9707bb62010-06-25 21:14:08 +00001006def visit(prefix, dir, names):
1007 """Visitor function for os.path.walk(path, visit, arg)."""
1008
1009 global suite
Johnny Chen7c52ff12010-09-27 23:29:54 +00001010 global regexp
Johnny Chenc5fa0052011-07-29 22:54:56 +00001011 global filters
Johnny Chenb62436b2010-10-06 20:40:56 +00001012 global fs4all
Johnny Chene9eae812012-01-18 05:15:00 +00001013 global excluded
1014
1015 if set(dir.split(os.sep)).intersection(excluded):
1016 #print "Detected an excluded dir component: %s" % dir
1017 return
Johnny Chen9707bb62010-06-25 21:14:08 +00001018
1019 for name in names:
1020 if os.path.isdir(os.path.join(dir, name)):
1021 continue
1022
1023 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
Johnny Chen7c52ff12010-09-27 23:29:54 +00001024 # Try to match the regexp pattern, if specified.
1025 if regexp:
1026 import re
1027 if re.search(regexp, name):
1028 #print "Filename: '%s' matches pattern: '%s'" % (name, regexp)
1029 pass
1030 else:
1031 #print "Filename: '%s' does not match pattern: '%s'" % (name, regexp)
1032 continue
1033
Johnny Chen953864a2010-10-12 21:35:54 +00001034 # We found a match for our test. Add it to the suite.
Johnny Chen79723352010-10-12 15:53:22 +00001035
1036 # Update the sys.path first.
Johnny Chena85d7ee2010-06-26 00:19:32 +00001037 if not sys.path.count(dir):
Johnny Chen548aefd2010-10-11 22:25:46 +00001038 sys.path.insert(0, dir)
Johnny Chen9707bb62010-06-25 21:14:08 +00001039 base = os.path.splitext(name)[0]
Johnny Chenb62436b2010-10-06 20:40:56 +00001040
1041 # Thoroughly check the filterspec against the base module and admit
1042 # the (base, filterspec) combination only when it makes sense.
Johnny Chenc5fa0052011-07-29 22:54:56 +00001043 filterspec = None
1044 for filterspec in filters:
Johnny Chenb62436b2010-10-06 20:40:56 +00001045 # Optimistically set the flag to True.
1046 filtered = True
1047 module = __import__(base)
1048 parts = filterspec.split('.')
1049 obj = module
1050 for part in parts:
1051 try:
1052 parent, obj = obj, getattr(obj, part)
1053 except AttributeError:
1054 # The filterspec has failed.
1055 filtered = False
1056 break
Johnny Chenc5fa0052011-07-29 22:54:56 +00001057
Johnny Chendb4be602011-08-12 23:55:07 +00001058 # If filtered, we have a good filterspec. Add it.
Johnny Chenc5fa0052011-07-29 22:54:56 +00001059 if filtered:
Johnny Chendb4be602011-08-12 23:55:07 +00001060 #print "adding filter spec %s to module %s" % (filterspec, module)
1061 suite.addTests(
1062 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
1063 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +00001064
1065 # Forgo this module if the (base, filterspec) combo is invalid
1066 # and no '-g' option is specified
1067 if filters and fs4all and not filtered:
1068 continue
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001069
Johnny Chendb4be602011-08-12 23:55:07 +00001070 # Add either the filtered test case(s) (which is done before) or the entire test class.
1071 if not filterspec or not filtered:
Johnny Chenb62436b2010-10-06 20:40:56 +00001072 # A simple case of just the module name. Also the failover case
1073 # from the filterspec branch when the (base, filterspec) combo
1074 # doesn't make sense.
1075 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Johnny Chen9707bb62010-06-25 21:14:08 +00001076
1077
Johnny Chencd0279d2010-09-20 18:07:50 +00001078def lldbLoggings():
1079 """Check and do lldb loggings if necessary."""
1080
1081 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
1082 # defined. Use ${LLDB_LOG} to specify the log file.
1083 ci = lldb.DBG.GetCommandInterpreter()
1084 res = lldb.SBCommandReturnObject()
1085 if ("LLDB_LOG" in os.environ):
1086 if ("LLDB_LOG_OPTION" in os.environ):
1087 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
1088 else:
Johnny Chen8fd886c2010-12-08 01:25:21 +00001089 lldb_log_option = "event process expr state api"
Johnny Chencd0279d2010-09-20 18:07:50 +00001090 ci.HandleCommand(
Greg Clayton940b1032011-02-23 00:35:02 +00001091 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
Johnny Chencd0279d2010-09-20 18:07:50 +00001092 res)
1093 if not res.Succeeded():
1094 raise Exception('log enable failed (check LLDB_LOG env variable.')
1095 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
1096 # Use ${GDB_REMOTE_LOG} to specify the log file.
1097 if ("GDB_REMOTE_LOG" in os.environ):
1098 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
1099 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
1100 else:
Johnny Chen7ab8c852010-12-02 18:35:13 +00001101 gdb_remote_log_option = "packets process"
Johnny Chencd0279d2010-09-20 18:07:50 +00001102 ci.HandleCommand(
Johnny Chenc935a892011-06-21 19:25:45 +00001103 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
Johnny Chencd0279d2010-09-20 18:07:50 +00001104 + gdb_remote_log_option,
1105 res)
1106 if not res.Succeeded():
1107 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
1108
Johnny Chen067022b2011-01-19 19:31:46 +00001109def getMyCommandLine():
Daniel Malea782e4742013-05-30 21:48:58 +00001110 ps = subprocess.Popen([which('ps'), '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
Johnny Chen067022b2011-01-19 19:31:46 +00001111 lines = ps.split('\n')
1112 cmd_line = lines[1]
1113 return cmd_line
Johnny Chencd0279d2010-09-20 18:07:50 +00001114
Johnny Chend96b5682010-11-05 17:30:53 +00001115# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001116# #
1117# Execution of the test driver starts here #
1118# #
Johnny Chend96b5682010-11-05 17:30:53 +00001119# ======================================== #
Johnny Chencd0279d2010-09-20 18:07:50 +00001120
Johnny Chen2891bb02011-09-16 01:04:26 +00001121def checkDsymForUUIDIsNotOn():
Johnny Chen6a4e0872011-09-16 17:50:44 +00001122 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
1123 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1124 cmd_output = pipe.stdout.read()
Johnny Chen178c8d92011-09-16 18:03:19 +00001125 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
Johnny Chen6a451482011-09-16 18:09:45 +00001126 print "%s =>" % ' '.join(cmd)
Johnny Chen6a4e0872011-09-16 17:50:44 +00001127 print cmd_output
Johnny Chen2891bb02011-09-16 01:04:26 +00001128 print "Disable automatic lookup and caching of dSYMs before running the test suite!"
1129 print "Exiting..."
1130 sys.exit(0)
1131
1132# On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
1133# does not exist before proceeding to running the test suite.
1134if sys.platform.startswith("darwin"):
1135 checkDsymForUUIDIsNotOn()
1136
Johnny Chen9707bb62010-06-25 21:14:08 +00001137#
Johnny Chenaf149a02010-09-16 17:11:30 +00001138# Start the actions by first parsing the options while setting up the test
1139# directories, followed by setting up the search paths for lldb utilities;
1140# then, we walk the directory trees and collect the tests into our test suite.
Johnny Chen9707bb62010-06-25 21:14:08 +00001141#
Johnny Chenaf149a02010-09-16 17:11:30 +00001142parseOptionsAndInitTestdirs()
Johnny Chen9707bb62010-06-25 21:14:08 +00001143setupSysPath()
Johnny Chen91960d32010-09-08 20:56:16 +00001144
1145#
1146# If '-d' is specified, do a delay of 10 seconds for the debugger to attach.
1147#
1148if delay:
Johnny Chencd0279d2010-09-20 18:07:50 +00001149 doDelay(10)
Johnny Chen91960d32010-09-08 20:56:16 +00001150
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001151#
Johnny Chen41998192010-10-01 22:59:49 +00001152# If '-l' is specified, do not skip the long running tests.
Johnny Chen028d8eb2011-11-17 19:57:27 +00001153if not skip_long_running_test:
Johnny Chen41998192010-10-01 22:59:49 +00001154 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
1155
1156#
Johnny Chen79723352010-10-12 15:53:22 +00001157# Walk through the testdirs while collecting tests.
Johnny Chen49f2f7a2010-09-20 17:25:45 +00001158#
Johnny Chen9707bb62010-06-25 21:14:08 +00001159for testdir in testdirs:
1160 os.path.walk(testdir, visit, 'Test')
1161
Johnny Chenb40056b2010-09-21 00:09:27 +00001162#
Johnny Chen9707bb62010-06-25 21:14:08 +00001163# Now that we have loaded all the test cases, run the whole test suite.
Johnny Chenb40056b2010-09-21 00:09:27 +00001164#
Johnny Chencd0279d2010-09-20 18:07:50 +00001165
Johnny Chen1bfbd412010-06-29 19:44:16 +00001166# For the time being, let's bracket the test runner within the
1167# lldb.SBDebugger.Initialize()/Terminate() pair.
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001168import lldb, atexit
Johnny Chen6b6f5ba2010-10-14 16:36:49 +00001169# Update: the act of importing lldb now executes lldb.SBDebugger.Initialize(),
1170# there's no need to call it a second time.
1171#lldb.SBDebugger.Initialize()
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001172atexit.register(lambda: lldb.SBDebugger.Terminate())
Johnny Chen1bfbd412010-06-29 19:44:16 +00001173
Johnny Chen909e5a62010-07-01 22:52:57 +00001174# Create a singleton SBDebugger in the lldb namespace.
1175lldb.DBG = lldb.SBDebugger.Create()
1176
Johnny Chen4f93bf12010-12-10 00:51:23 +00001177# Put the blacklist in the lldb namespace, to be used by lldb.TestBase.
Johnny Chen82e6b1e2010-12-01 22:47:54 +00001178lldb.blacklist = blacklist
1179
Johnny Chenac97a6b2012-04-16 18:55:15 +00001180# The pre_flight and post_flight come from reading a config file.
1181lldb.pre_flight = pre_flight
1182lldb.post_flight = post_flight
1183def getsource_if_available(obj):
1184 """
1185 Return the text of the source code for an object if available. Otherwise,
1186 a print representation is returned.
1187 """
1188 import inspect
1189 try:
1190 return inspect.getsource(obj)
1191 except:
1192 return repr(obj)
1193
Daniel Malea361eb432013-02-15 21:31:37 +00001194if not noHeaders:
1195 print "lldb.pre_flight:", getsource_if_available(lldb.pre_flight)
1196 print "lldb.post_flight:", getsource_if_available(lldb.post_flight)
Johnny Chenac97a6b2012-04-16 18:55:15 +00001197
Johnny Chena3ed7d82012-04-06 00:56:05 +00001198# Put all these test decorators in the lldb namespace.
Johnny Chen4f93bf12010-12-10 00:51:23 +00001199lldb.dont_do_python_api_test = dont_do_python_api_test
1200lldb.just_do_python_api_test = just_do_python_api_test
Johnny Chen82ccf402011-07-30 01:39:58 +00001201lldb.just_do_benchmarks_test = just_do_benchmarks_test
Johnny Chena3ed7d82012-04-06 00:56:05 +00001202lldb.dont_do_dsym_test = dont_do_dsym_test
1203lldb.dont_do_dwarf_test = dont_do_dwarf_test
Johnny Chen4f93bf12010-12-10 00:51:23 +00001204
Johnny Chen028d8eb2011-11-17 19:57:27 +00001205# Do we need to skip build and cleanup?
1206lldb.skip_build_and_cleanup = skip_build_and_cleanup
1207
Johnny Chen5f2ed172011-10-20 18:43:28 +00001208# Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too.
Johnny Chene00c9302011-10-10 22:03:44 +00001209lldb.bmExecutable = bmExecutable
1210lldb.bmBreakpointSpec = bmBreakpointSpec
Johnny Chen5f2ed172011-10-20 18:43:28 +00001211lldb.bmIterationCount = bmIterationCount
Johnny Chene00c9302011-10-10 22:03:44 +00001212
Johnny Chen38f823c2011-10-11 01:30:27 +00001213# And don't forget the runHooks!
1214lldb.runHooks = runHooks
1215
Johnny Chencd0279d2010-09-20 18:07:50 +00001216# Turn on lldb loggings if necessary.
1217lldbLoggings()
Johnny Chen909e5a62010-07-01 22:52:57 +00001218
Johnny Chen7987ac92010-08-09 20:40:52 +00001219# Install the control-c handler.
1220unittest2.signals.installHandler()
1221
Johnny Chen125fc2b2010-10-21 16:55:35 +00001222# If sdir_name is not specified through the '-s sdir_name' option, get a
1223# timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1224# be used when/if we want to dump the session info of individual test cases
1225# later on.
Johnny Chence681462010-10-19 00:25:01 +00001226#
1227# See also TestBase.dumpSessionInfo() in lldbtest.py.
Johnny Chena73ad662012-08-16 19:15:21 +00001228import datetime
1229# The windows platforms don't like ':' in the pathname.
1230timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Johnny Chen125fc2b2010-10-21 16:55:35 +00001231if not sdir_name:
Johnny Chena73ad662012-08-16 19:15:21 +00001232 sdir_name = timestamp_started
Peter Collingbourne132476f2011-06-20 23:55:53 +00001233os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name)
Johnny Chen067022b2011-01-19 19:31:46 +00001234
Johnny Chenfe5f1ed2011-10-21 18:33:27 +00001235if not noHeaders:
1236 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1237 " will go into directory '%s'\n" % sdir_name)
1238 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Johnny Chence681462010-10-19 00:25:01 +00001239
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001240if not os.path.isdir(sdir_name):
1241 os.mkdir(sdir_name)
Enrico Granata571358f2013-06-19 21:48:09 +00001242where_to_save_session = os.getcwd()
Johnny Chena73ad662012-08-16 19:15:21 +00001243fname = os.path.join(sdir_name, "TestStarted")
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001244with open(fname, "w") as f:
Johnny Chena73ad662012-08-16 19:15:21 +00001245 print >> f, "Test started at: %s\n" % timestamp_started
Johnny Chenb5fe80c2011-05-17 22:58:50 +00001246 print >> f, svn_info
1247 print >> f, "Command invoked: %s\n" % getMyCommandLine()
1248
Johnny Chenb40056b2010-09-21 00:09:27 +00001249#
1250# Invoke the default TextTestRunner to run the test suite, possibly iterating
1251# over different configurations.
1252#
1253
Johnny Chenb40056b2010-09-21 00:09:27 +00001254iterArchs = False
Johnny Chenf032d902010-09-21 00:16:09 +00001255iterCompilers = False
Johnny Chenb40056b2010-09-21 00:09:27 +00001256
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001257if not archs and "archs" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001258 archs = config["archs"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001259
1260if isinstance(archs, list) and len(archs) >= 1:
1261 iterArchs = True
1262
1263if not compilers and "compilers" in config:
Johnny Chenb40056b2010-09-21 00:09:27 +00001264 compilers = config["compilers"]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001265
Johnny Chen92693b52012-03-09 02:11:37 +00001266#
1267# Add some intervention here to sanity check that the compilers requested are sane.
1268# If found not to be an executable program, the invalid one is dropped from the list.
1269for i in range(len(compilers)):
1270 c = compilers[i]
1271 if which(c):
1272 continue
1273 else:
1274 if sys.platform.startswith("darwin"):
1275 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1276 cmd_output = pipe.stdout.read()
1277 if cmd_output:
1278 if "not found" in cmd_output:
1279 print "dropping %s from the compilers used" % c
1280 compilers.remove(i)
1281 else:
1282 compilers[i] = cmd_output.split('\n')[0]
1283 print "'xcrun -find %s' returning %s" % (c, compilers[i])
1284
Daniel Malea361eb432013-02-15 21:31:37 +00001285if not parsable:
1286 print "compilers=%s" % str(compilers)
Johnny Chen92693b52012-03-09 02:11:37 +00001287
1288if not compilers or len(compilers) == 0:
1289 print "No eligible compiler found, exiting."
1290 sys.exit(1)
1291
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001292if isinstance(compilers, list) and len(compilers) >= 1:
1293 iterCompilers = True
Johnny Chenb40056b2010-09-21 00:09:27 +00001294
Johnny Chen953864a2010-10-12 21:35:54 +00001295# Make a shallow copy of sys.path, we need to manipulate the search paths later.
1296# This is only necessary if we are relocated and with different configurations.
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001297if rdir:
Johnny Chen953864a2010-10-12 21:35:54 +00001298 old_sys_path = sys.path[:]
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001299# If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1300if iterArchs or iterCompilers:
Johnny Chen953864a2010-10-12 21:35:54 +00001301 old_stderr = sys.stderr
1302 old_stdout = sys.stdout
1303 new_stderr = None
1304 new_stdout = None
1305
Johnny Chend96b5682010-11-05 17:30:53 +00001306# Iterating over all possible architecture and compiler combinations.
Johnny Chenb40056b2010-09-21 00:09:27 +00001307for ia in range(len(archs) if iterArchs else 1):
1308 archConfig = ""
1309 if iterArchs:
Johnny Chen18a921f2010-09-30 17:11:58 +00001310 os.environ["ARCH"] = archs[ia]
Johnny Chenb40056b2010-09-21 00:09:27 +00001311 archConfig = "arch=%s" % archs[ia]
1312 for ic in range(len(compilers) if iterCompilers else 1):
1313 if iterCompilers:
Johnny Chen18a921f2010-09-30 17:11:58 +00001314 os.environ["CC"] = compilers[ic]
Johnny Chenb40056b2010-09-21 00:09:27 +00001315 configString = "%s compiler=%s" % (archConfig, compilers[ic])
1316 else:
1317 configString = archConfig
1318
Johnny Chenb40056b2010-09-21 00:09:27 +00001319 if iterArchs or iterCompilers:
Johnny Chen1a4d5e72011-03-04 01:35:22 +00001320 # Translate ' ' to '-' for pathname component.
1321 from string import maketrans
1322 tbl = maketrans(' ', '-')
1323 configPostfix = configString.translate(tbl)
1324
1325 # Check whether we need to split stderr/stdout into configuration
1326 # specific files.
1327 if old_stderr.name != '<stderr>' and config.get('split_stderr'):
1328 if new_stderr:
1329 new_stderr.close()
1330 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w")
1331 sys.stderr = new_stderr
1332 if old_stdout.name != '<stdout>' and config.get('split_stdout'):
1333 if new_stdout:
1334 new_stdout.close()
1335 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w")
1336 sys.stdout = new_stdout
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001337
Johnny Chen953864a2010-10-12 21:35:54 +00001338 # If we specified a relocated directory to run the test suite, do
1339 # the extra housekeeping to copy the testdirs to a configStringified
1340 # directory and to update sys.path before invoking the test runner.
1341 # The purpose is to separate the configuration-specific directories
1342 # from each other.
1343 if rdir:
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001344 from shutil import copytree, rmtree, ignore_patterns
Johnny Chen953864a2010-10-12 21:35:54 +00001345
Johnny Chen953864a2010-10-12 21:35:54 +00001346 newrdir = "%s.%s" % (rdir, configPostfix)
1347
1348 # Copy the tree to a new directory with postfix name configPostfix.
Johnny Chen3bc7e5e2012-04-24 21:44:10 +00001349 if os.path.exists(newrdir):
1350 rmtree(newrdir)
Johnny Chen953864a2010-10-12 21:35:54 +00001351 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1352
Filipe Cabecinhas0e1d06d2012-08-08 15:23:24 +00001353 # Update the LLDB_TEST environment variable to reflect new top
Johnny Chen953864a2010-10-12 21:35:54 +00001354 # level test directory.
1355 #
1356 # See also lldbtest.TestBase.setUpClass(cls).
1357 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test':
1358 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1359 else:
1360 os.environ["LLDB_TEST"] = newrdir
1361
1362 # And update the Python search paths for modules.
1363 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1364
1365 # Output the configuration.
Daniel Malea361eb432013-02-15 21:31:37 +00001366 if not parsable:
1367 sys.stderr.write("\nConfiguration: " + configString + "\n")
Johnny Chen953864a2010-10-12 21:35:54 +00001368
1369 #print "sys.stderr name is", sys.stderr.name
1370 #print "sys.stdout name is", sys.stdout.name
1371
1372 # First, write out the number of collected test cases.
Daniel Malea361eb432013-02-15 21:31:37 +00001373 if not parsable:
1374 sys.stderr.write(separator + "\n")
1375 sys.stderr.write("Collected %d test%s\n\n"
1376 % (suite.countTestCases(),
1377 suite.countTestCases() != 1 and "s" or ""))
Johnny Chen953864a2010-10-12 21:35:54 +00001378
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001379 class LLDBTestResult(unittest2.TextTestResult):
1380 """
Johnny Chen26be4532010-11-09 23:56:14 +00001381 Enforce a singleton pattern to allow introspection of test progress.
1382
1383 Overwrite addError(), addFailure(), and addExpectedFailure() methods
1384 to enable each test instance to track its failure/error status. It
1385 is used in the LLDB test framework to emit detailed trace messages
1386 to a log file for easier human inspection of test failres/errors.
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001387 """
1388 __singleton__ = None
Johnny Chen360dd372010-11-29 17:50:10 +00001389 __ignore_singleton__ = False
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001390
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001391 @staticmethod
1392 def getTerminalSize():
1393 import os
1394 env = os.environ
1395 def ioctl_GWINSZ(fd):
1396 try:
1397 import fcntl, termios, struct, os
1398 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
1399 '1234'))
1400 except:
1401 return
1402 return cr
1403 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
1404 if not cr:
1405 try:
1406 fd = os.open(os.ctermid(), os.O_RDONLY)
1407 cr = ioctl_GWINSZ(fd)
1408 os.close(fd)
1409 except:
1410 pass
1411 if not cr:
1412 cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
1413 return int(cr[1]), int(cr[0])
1414
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001415 def __init__(self, *args):
Johnny Chen360dd372010-11-29 17:50:10 +00001416 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
Johnny Chend2acdb32010-11-16 22:42:58 +00001417 raise Exception("LLDBTestResult instantiated more than once")
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001418 super(LLDBTestResult, self).__init__(*args)
1419 LLDBTestResult.__singleton__ = self
1420 # Now put this singleton into the lldb module namespace.
1421 lldb.test_result = self
Johnny Chen810042e2011-01-05 20:24:11 +00001422 # Computes the format string for displaying the counter.
1423 global suite
1424 counterWidth = len(str(suite.countTestCases()))
1425 self.fmt = "%" + str(counterWidth) + "d: "
Johnny Chenc87fd492011-01-05 22:50:11 +00001426 self.indentation = ' ' * (counterWidth + 2)
Johnny Chen810042e2011-01-05 20:24:11 +00001427 # This counts from 1 .. suite.countTestCases().
1428 self.counter = 0
Enrico Granatabc0c5a62013-02-08 23:39:18 +00001429 (width, height) = LLDBTestResult.getTerminalSize()
Enrico Granata77215892013-02-15 00:32:05 +00001430 self.progressbar = None
Jim Ingham75f260a2013-02-19 20:39:27 +00001431 global progress_bar
Daniel Malea361eb432013-02-15 21:31:37 +00001432 if width > 10 and not parsable and progress_bar:
Enrico Granata77215892013-02-15 00:32:05 +00001433 try:
1434 self.progressbar = progress.ProgressWithEvents(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10)
1435 except:
1436 self.progressbar = None
Johnny Chen810042e2011-01-05 20:24:11 +00001437
Daniel Malea361eb432013-02-15 21:31:37 +00001438 def _config_string(self, test):
1439 compiler = getattr(test, "getCompiler", None)
1440 arch = getattr(test, "getArchitecture", None)
1441 return "%s-%s" % (compiler() if compiler else "", arch() if arch else "")
1442
Johnny Chenbe452272012-04-19 21:33:55 +00001443 def _exc_info_to_string(self, err, test):
1444 """Overrides superclass TestResult's method in order to append
1445 our test config info string to the exception info string."""
Daniel Malea1d6437d2013-07-30 21:28:32 +00001446 if hasattr(test, "getArchitecture") and hasattr(test, "getCompiler"):
1447 return '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
1448 test.getArchitecture(),
1449 test.getCompiler())
1450 else:
1451 return super(LLDBTestResult, self)._exc_info_to_string(err, test)
Johnny Chenbe452272012-04-19 21:33:55 +00001452
Johnny Chenc87fd492011-01-05 22:50:11 +00001453 def getDescription(self, test):
1454 doc_first_line = test.shortDescription()
1455 if self.descriptions and doc_first_line:
1456 return '\n'.join((str(test), self.indentation + doc_first_line))
1457 else:
1458 return str(test)
1459
Enrico Granataac3a8e22012-09-21 19:10:53 +00001460 def getCategoriesForTest(self,test):
Enrico Granata56e2c562013-02-27 02:37:12 +00001461 if hasattr(test,"_testMethodName"):
1462 test_method = getattr(test,"_testMethodName")
1463 test_method = getattr(test,test_method)
1464 else:
1465 test_method = None
1466 if test_method != None and hasattr(test_method,"getCategories"):
1467 test_categories = test_method.getCategories(test)
1468 elif hasattr(test,"getCategories"):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001469 test_categories = test.getCategories()
1470 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
1471 test_categories = test.__self__.getCategories()
1472 else:
1473 test_categories = []
1474 if test_categories == None:
1475 test_categories = []
1476 return test_categories
1477
1478 def shouldSkipBecauseOfCategories(self,test):
1479 global useCategories
1480 import inspect
1481 if useCategories:
1482 global categoriesList
1483 test_categories = self.getCategoriesForTest(test)
1484 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0:
1485 return True
Stefanus Du Toit2bf96332013-08-01 17:59:20 +00001486
1487 global skipCategories
1488 for category in skipCategories:
1489 if category in self.getCategoriesForTest(test):
1490 return True
1491
Enrico Granataac3a8e22012-09-21 19:10:53 +00001492 return False
1493
1494 def hardMarkAsSkipped(self,test):
1495 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
1496 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
Enrico Granata571358f2013-06-19 21:48:09 +00001497 test.__class__.__unittest_skip__ = True
1498 test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
Enrico Granataac3a8e22012-09-21 19:10:53 +00001499
Johnny Chen810042e2011-01-05 20:24:11 +00001500 def startTest(self, test):
Enrico Granataac3a8e22012-09-21 19:10:53 +00001501 if self.shouldSkipBecauseOfCategories(test):
1502 self.hardMarkAsSkipped(test)
Johnny Chen810042e2011-01-05 20:24:11 +00001503 self.counter += 1
1504 if self.showAll:
1505 self.stream.write(self.fmt % self.counter)
1506 super(LLDBTestResult, self).startTest(test)
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001507
Daniel Malea361eb432013-02-15 21:31:37 +00001508 def addSuccess(self, test):
1509 global parsable
1510 super(LLDBTestResult, self).addSuccess(test)
1511 if parsable:
1512 self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1513
Johnny Chence681462010-10-19 00:25:01 +00001514 def addError(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001515 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001516 global parsable
Johnny Chen63c2cba2010-10-29 22:20:36 +00001517 sdir_has_content = True
Johnny Chence681462010-10-19 00:25:01 +00001518 super(LLDBTestResult, self).addError(test, err)
1519 method = getattr(test, "markError", None)
1520 if method:
1521 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001522 if parsable:
Daniel Maleae1dd3e52013-03-07 18:39:26 +00001523 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Johnny Chence681462010-10-19 00:25:01 +00001524
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001525 def addFailure(self, test, err):
Johnny Chen63c2cba2010-10-29 22:20:36 +00001526 global sdir_has_content
Enrico Granataac3a8e22012-09-21 19:10:53 +00001527 global failuresPerCategory
Daniel Malea361eb432013-02-15 21:31:37 +00001528 global parsable
Johnny Chen63c2cba2010-10-29 22:20:36 +00001529 sdir_has_content = True
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001530 super(LLDBTestResult, self).addFailure(test, err)
1531 method = getattr(test, "markFailure", None)
1532 if method:
1533 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001534 if parsable:
1535 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Enrico Granataac3a8e22012-09-21 19:10:53 +00001536 if useCategories:
1537 test_categories = self.getCategoriesForTest(test)
1538 for category in test_categories:
1539 if category in failuresPerCategory:
1540 failuresPerCategory[category] = failuresPerCategory[category] + 1
1541 else:
1542 failuresPerCategory[category] = 1
Johnny Chen84a6d6f2010-10-15 01:18:29 +00001543
Enrico Granata21416a12013-02-23 01:05:23 +00001544 def addExpectedFailure(self, test, err, bugnumber):
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001545 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001546 global parsable
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001547 sdir_has_content = True
Enrico Granata21416a12013-02-23 01:05:23 +00001548 super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber)
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001549 method = getattr(test, "markExpectedFailure", None)
1550 if method:
Enrico Granata21416a12013-02-23 01:05:23 +00001551 method(err, bugnumber)
Daniel Malea361eb432013-02-15 21:31:37 +00001552 if parsable:
1553 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
Johnny Chendd2bb2c2010-11-03 18:17:03 +00001554
Johnny Chenf5b89092011-08-15 23:09:08 +00001555 def addSkip(self, test, reason):
1556 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001557 global parsable
Johnny Chenf5b89092011-08-15 23:09:08 +00001558 sdir_has_content = True
1559 super(LLDBTestResult, self).addSkip(test, reason)
1560 method = getattr(test, "markSkippedTest", None)
1561 if method:
1562 method()
Daniel Malea361eb432013-02-15 21:31:37 +00001563 if parsable:
1564 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason))
Johnny Chenf5b89092011-08-15 23:09:08 +00001565
Enrico Granata21416a12013-02-23 01:05:23 +00001566 def addUnexpectedSuccess(self, test, bugnumber):
Johnny Chenab2f0662011-05-06 20:30:22 +00001567 global sdir_has_content
Daniel Malea361eb432013-02-15 21:31:37 +00001568 global parsable
Johnny Chenab2f0662011-05-06 20:30:22 +00001569 sdir_has_content = True
Enrico Granata21416a12013-02-23 01:05:23 +00001570 super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber)
Johnny Chenab2f0662011-05-06 20:30:22 +00001571 method = getattr(test, "markUnexpectedSuccess", None)
1572 if method:
Enrico Granata21416a12013-02-23 01:05:23 +00001573 method(bugnumber)
Daniel Malea361eb432013-02-15 21:31:37 +00001574 if parsable:
1575 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
1576
1577 if parsable:
1578 v = 0
1579 elif progress_bar:
1580 v = 1
1581 else:
1582 v = verbose
Johnny Chenab2f0662011-05-06 20:30:22 +00001583
Johnny Chen26be4532010-11-09 23:56:14 +00001584 # Invoke the test runner.
Johnny Chend2acdb32010-11-16 22:42:58 +00001585 if count == 1:
Johnny Chen7d6d8442010-12-03 19:59:35 +00001586 result = unittest2.TextTestRunner(stream=sys.stderr,
Daniel Malea361eb432013-02-15 21:31:37 +00001587 verbosity=v,
Johnny Chen7d6d8442010-12-03 19:59:35 +00001588 failfast=failfast,
Johnny Chend2acdb32010-11-16 22:42:58 +00001589 resultclass=LLDBTestResult).run(suite)
1590 else:
Johnny Chend6e7ca22010-11-29 17:52:43 +00001591 # We are invoking the same test suite more than once. In this case,
1592 # mark __ignore_singleton__ flag as True so the signleton pattern is
1593 # not enforced.
Johnny Chen360dd372010-11-29 17:50:10 +00001594 LLDBTestResult.__ignore_singleton__ = True
Johnny Chend2acdb32010-11-16 22:42:58 +00001595 for i in range(count):
Daniel Malea361eb432013-02-15 21:31:37 +00001596
Johnny Chen7d6d8442010-12-03 19:59:35 +00001597 result = unittest2.TextTestRunner(stream=sys.stderr,
Daniel Malea361eb432013-02-15 21:31:37 +00001598 verbosity=v,
Johnny Chen7d6d8442010-12-03 19:59:35 +00001599 failfast=failfast,
Johnny Chen360dd372010-11-29 17:50:10 +00001600 resultclass=LLDBTestResult).run(suite)
Filipe Cabecinhasc0566642012-08-08 15:05:04 +00001601
Daniel Malea24765572013-02-20 20:12:11 +00001602 failed = failed or not result.wasSuccessful()
Johnny Chen1bfbd412010-06-29 19:44:16 +00001603
Daniel Malea361eb432013-02-15 21:31:37 +00001604if sdir_has_content and not parsable:
Johnny Chenab2f0662011-05-06 20:30:22 +00001605 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
1606 " can be found in directory '%s'\n" % sdir_name)
Johnny Chen63c2cba2010-10-29 22:20:36 +00001607
Enrico Granataac3a8e22012-09-21 19:10:53 +00001608if useCategories and len(failuresPerCategory) > 0:
1609 sys.stderr.write("Failures per category:\n")
1610 for category in failuresPerCategory:
1611 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category]))
1612
Enrico Granata571358f2013-06-19 21:48:09 +00001613os.chdir(where_to_save_session)
Johnny Chena73ad662012-08-16 19:15:21 +00001614fname = os.path.join(sdir_name, "TestFinished")
1615with open(fname, "w") as f:
1616 print >> f, "Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
1617
Johnny Chencd0279d2010-09-20 18:07:50 +00001618# Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1619# This should not be necessary now.
Johnny Chen83f6e512010-08-13 22:58:44 +00001620if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
Johnny Chen83f6e512010-08-13 22:58:44 +00001621 print "Terminating Test suite..."
1622 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1623
Johnny Chen01f2a6a2010-08-10 20:23:55 +00001624# Exiting.
Daniel Malea24765572013-02-20 20:12:11 +00001625sys.exit(failed)