blob: cf01cc4b6e9be0cc7242d94ec0979402dd741dac [file] [log] [blame]
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001"""
2A simple testing framework for lldb using python's unit testing framework.
3
4Tests for lldb are written as python scripts which take advantage of the script
5bridging provided by LLDB.framework to interact with lldb core.
6
7A specific naming pattern is followed by the .py script to be recognized as
8a module which implements a test scenario, namely, Test*.py.
9
10To specify the directories where "Test*.py" python test scripts are located,
11you need to pass in a list of directory names. By default, the current
12working directory is searched if nothing is specified on the command line.
13
14Type:
15
16./dotest.py -h
17
18for available options.
19"""
20
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000021from __future__ import absolute_import
Zachary Turnerc432c8f2015-10-28 17:43:26 +000022from __future__ import print_function
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000023
24# System modules
Zachary Turnerc432c8f2015-10-28 17:43:26 +000025import atexit
Zachary Turnerc432c8f2015-10-28 17:43:26 +000026import importlib
27import os
Zachary Turnerc432c8f2015-10-28 17:43:26 +000028import errno
29import platform
Zachary Turnerc432c8f2015-10-28 17:43:26 +000030import signal
31import socket
32import subprocess
33import sys
Zachary Turnerc432c8f2015-10-28 17:43:26 +000034import inspect
Zachary Turnerc432c8f2015-10-28 17:43:26 +000035
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000036# Third-party modules
Zachary Turnerc432c8f2015-10-28 17:43:26 +000037import six
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000038import unittest2
39
40# LLDB Modules
41import lldbsuite
Zachary Turner606e3a52015-12-08 01:15:30 +000042from . import configuration
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000043from . import dotest_args
44from . import lldbtest_config
45from . import test_categories
Zachary Turner905a9882015-12-07 21:23:41 +000046from . import result_formatter
Zachary Turnerb4733e62015-12-08 01:15:44 +000047from . import test_result
Zachary Turner905a9882015-12-07 21:23:41 +000048from .result_formatter import EventBuilder
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000049from ..support import seven
Zachary Turnerc432c8f2015-10-28 17:43:26 +000050
51def is_exe(fpath):
52 """Returns true if fpath is an executable."""
53 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
54
55def which(program):
56 """Returns the full path to a program; None otherwise."""
57 fpath, fname = os.path.split(program)
58 if fpath:
59 if is_exe(program):
60 return program
61 else:
62 for path in os.environ["PATH"].split(os.pathsep):
63 exe_file = os.path.join(path, program)
64 if is_exe(exe_file):
65 return exe_file
66 return None
67
68class _WritelnDecorator(object):
69 """Used to decorate file-like objects with a handy 'writeln' method"""
70 def __init__(self,stream):
71 self.stream = stream
72
73 def __getattr__(self, attr):
74 if attr in ('stream', '__getstate__'):
75 raise AttributeError(attr)
76 return getattr(self.stream,attr)
77
78 def writeln(self, arg=None):
79 if arg:
80 self.write(arg)
81 self.write('\n') # text-mode streams translate to \r\n if needed
82
83#
84# Global variables:
85#
Zachary Turnerc432c8f2015-10-28 17:43:26 +000086def usage(parser):
87 parser.print_help()
Zachary Turner606e3a52015-12-08 01:15:30 +000088 if configuration.verbose > 0:
Zachary Turnerc432c8f2015-10-28 17:43:26 +000089 print("""
90Examples:
91
92This is an example of using the -f option to pinpoint to a specific test class
93and test method to be run:
94
95$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command
96----------------------------------------------------------------------
97Collected 1 test
98
99test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase)
100Test 'frame variable this' when stopped on a class constructor. ... ok
101
102----------------------------------------------------------------------
103Ran 1 test in 1.396s
104
105OK
106
107And this is an example of using the -p option to run a single file (the filename
108matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'):
109
110$ ./dotest.py -v -p ObjC
111----------------------------------------------------------------------
112Collected 4 tests
113
114test_break_with_dsym (TestObjCMethods.FoundationTestCase)
115Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
116test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
117Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
118test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
119Lookup objective-c data types and evaluate expressions. ... ok
120test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
121Lookup objective-c data types and evaluate expressions. ... ok
122
123----------------------------------------------------------------------
124Ran 4 tests in 16.661s
125
126OK
127
128Running of this script also sets up the LLDB_TEST environment variable so that
129individual test cases can locate their supporting files correctly. The script
130tries to set up Python's search paths for modules by looking at the build tree
131relative to this script. See also the '-i' option in the following example.
132
133Finally, this is an example of using the lldb.py module distributed/installed by
134Xcode4 to run against the tests under the 'forward' directory, and with the '-w'
135option to add some delay between two tests. It uses ARCH=x86_64 to specify that
136as the architecture and CC=clang to specify the compiler used for the test run:
137
138$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward
139
140Session logs for test failures/errors will go into directory '2010-11-11-13_56_16'
141----------------------------------------------------------------------
142Collected 2 tests
143
144test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
145Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
146test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase)
147Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok
148
149----------------------------------------------------------------------
150Ran 2 tests in 5.659s
151
152OK
153
154The 'Session ...' verbiage is recently introduced (see also the '-s' option) to
155notify the directory containing the session logs for test failures or errors.
156In case there is any test failure/error, a similar message is appended at the
157end of the stderr output for your convenience.
158
159ENABLING LOGS FROM TESTS
160
161Option 1:
162
163Writing logs into different files per test case::
164
165This option is particularly useful when multiple dotest instances are created
166by dosep.py
167
168$ ./dotest.py --channel "lldb all"
169
170$ ./dotest.py --channel "lldb all" --channel "gdb-remote packets"
171
172These log files are written to:
173
174<session-dir>/<test-id>-host.log (logs from lldb host process)
175<session-dir>/<test-id>-server.log (logs from debugserver/lldb-server)
176<session-dir>/<test-id>-<test-result>.log (console logs)
177
178By default, logs from successful runs are deleted. Use the --log-success flag
179to create reference logs for debugging.
180
181$ ./dotest.py --log-success
182
183Option 2: (DEPRECATED)
184
185The following options can only enable logs from the host lldb process.
186Only categories from the "lldb" or "gdb-remote" channels can be enabled
187They also do not automatically enable logs in locally running debug servers.
188Also, logs from all test case are written into each log file
189
190o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem
191 with a default option of 'event process' if LLDB_LOG_OPTION is not defined.
192
193o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the
194 'process.gdb-remote' subsystem with a default option of 'packets' if
195 GDB_REMOTE_LOG_OPTION is not defined.
196
197""")
198 sys.exit(0)
199
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000200def parseOptionsAndInitTestdirs():
201 """Initialize the list of directories containing our unittest scripts.
202
203 '-h/--help as the first option prints out usage info and exit the program.
204 """
205
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000206 do_help = False
207
208 platform_system = platform.system()
209 platform_machine = platform.machine()
210
211 parser = dotest_args.create_parser()
212 args = dotest_args.parse_args(parser, sys.argv[1:])
213
214 if args.unset_env_varnames:
215 for env_var in args.unset_env_varnames:
216 if env_var in os.environ:
217 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ
218 # is automatically translated into a corresponding call to unsetenv().
219 del os.environ[env_var]
220 #os.unsetenv(env_var)
221
222 if args.set_env_vars:
223 for env_var in args.set_env_vars:
224 parts = env_var.split('=', 1)
225 if len(parts) == 1:
226 os.environ[parts[0]] = ""
227 else:
228 os.environ[parts[0]] = parts[1]
229
230 # only print the args if being verbose (and parsable is off)
231 if args.v and not args.q:
232 print(sys.argv)
233
234 if args.h:
235 do_help = True
236
237 if args.compilers:
Zachary Turner606e3a52015-12-08 01:15:30 +0000238 configuration.compilers = args.compilers
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000239 else:
240 # Use a compiler appropriate appropriate for the Apple SDK if one was specified
241 if platform_system == 'Darwin' and args.apple_sdk:
Zachary Turner606e3a52015-12-08 01:15:30 +0000242 configuration.compilers = [seven.get_command_output('xcrun -sdk "%s" -find clang 2> /dev/null' % (args.apple_sdk))]
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000243 else:
244 # 'clang' on ubuntu 14.04 is 3.4 so we try clang-3.5 first
245 candidateCompilers = ['clang-3.5', 'clang', 'gcc']
246 for candidate in candidateCompilers:
247 if which(candidate):
Zachary Turner606e3a52015-12-08 01:15:30 +0000248 configuration.compilers = [candidate]
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000249 break
250
251 if args.channels:
252 lldbtest_config.channels = args.channels
253
254 if args.log_success:
255 lldbtest_config.log_success = args.log_success
256
257 # Set SDKROOT if we are using an Apple SDK
258 if platform_system == 'Darwin' and args.apple_sdk:
Zachary Turnerbb03a462015-11-03 18:55:22 +0000259 os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk "%s" --show-sdk-path 2> /dev/null' % (args.apple_sdk))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000260
261 if args.archs:
Zachary Turner606e3a52015-12-08 01:15:30 +0000262 configuration.archs = args.archs
263 for arch in configuration.archs:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000264 if arch.startswith('arm') and platform_system == 'Darwin' and not args.apple_sdk:
Zachary Turnerbb03a462015-11-03 18:55:22 +0000265 os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk iphoneos.internal --show-sdk-path 2> /dev/null')
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000266 if not os.path.exists(os.environ['SDKROOT']):
Zachary Turnerbb03a462015-11-03 18:55:22 +0000267 os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk iphoneos --show-sdk-path 2> /dev/null')
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000268 else:
Zachary Turner606e3a52015-12-08 01:15:30 +0000269 configuration.archs = [platform_machine]
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000270
271 if args.categoriesList:
Zachary Turner606e3a52015-12-08 01:15:30 +0000272 configuration.categoriesList = set(test_categories.validate(args.categoriesList, False))
273 configuration.useCategories = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000274 else:
Zachary Turner606e3a52015-12-08 01:15:30 +0000275 configuration.categoriesList = []
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000276
277 if args.skipCategories:
Zachary Turner606e3a52015-12-08 01:15:30 +0000278 configuration.skipCategories = test_categories.validate(args.skipCategories, False)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000279
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000280 if args.E:
281 cflags_extras = args.E
282 os.environ['CFLAGS_EXTRAS'] = cflags_extras
283
284 # argparse makes sure we have correct options
285 if args.N == 'dwarf':
Zachary Turner606e3a52015-12-08 01:15:30 +0000286 configuration.dont_do_dwarf_test = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000287 elif args.N == 'dwo':
Zachary Turner606e3a52015-12-08 01:15:30 +0000288 configuration.dont_do_dwo_test = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000289 elif args.N == 'dsym':
Zachary Turner606e3a52015-12-08 01:15:30 +0000290 configuration.dont_do_dsym_test = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000291
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000292 if args.d:
293 sys.stdout.write("Suspending the process %d to wait for debugger to attach...\n" % os.getpid())
294 sys.stdout.flush()
295 os.kill(os.getpid(), signal.SIGSTOP)
296
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000297 if args.f:
298 if any([x.startswith('-') for x in args.f]):
299 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000300 configuration.filters.extend(args.f)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000301 # Shut off multiprocessing mode when additional filters are specified.
302 # The rational is that the user is probably going after a very specific
303 # test and doesn't need a bunch of parallel test runners all looking for
304 # it in a frenzy. Also, '-v' now spits out all test run output even
305 # on success, so the standard recipe for redoing a failing test (with -v
306 # and a -f to filter to the specific test) now causes all test scanning
307 # (in parallel) to print results for do-nothing runs in a very distracting
308 # manner. If we really need filtered parallel runs in the future, consider
309 # adding a --no-output-on-success that prevents -v from setting
310 # output-on-success.
Zachary Turner606e3a52015-12-08 01:15:30 +0000311 configuration.no_multiprocess_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000312
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000313 if args.l:
Zachary Turner606e3a52015-12-08 01:15:30 +0000314 configuration.skip_long_running_test = False
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000315
316 if args.framework:
Zachary Turner606e3a52015-12-08 01:15:30 +0000317 configuration.lldbFrameworkPath = args.framework
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000318
319 if args.executable:
320 lldbtest_config.lldbExec = args.executable
321
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000322 if args.p:
323 if args.p.startswith('-'):
324 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000325 configuration.regexp = args.p
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000326
327 if args.q:
Zachary Turner606e3a52015-12-08 01:15:30 +0000328 configuration.parsable = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000329
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000330 if args.R:
331 if args.R.startswith('-'):
332 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000333 configuration.rdir = os.path.abspath(args.R)
334 if os.path.exists(configuration.rdir):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000335 import shutil
Zachary Turner606e3a52015-12-08 01:15:30 +0000336 print('Removing tree:', configuration.rdir)
337 shutil.rmtree(configuration.rdir)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000338
339 if args.r:
340 if args.r.startswith('-'):
341 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000342 configuration.rdir = os.path.abspath(args.r)
343 if os.path.exists(configuration.rdir):
344 print('Relocated directory:', configuration.rdir, 'must not exist!')
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000345 usage(parser)
346
347 if args.S:
Zachary Turner606e3a52015-12-08 01:15:30 +0000348 configuration.skip_build_and_cleanup = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000349
350 if args.s:
351 if args.s.startswith('-'):
352 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000353 configuration.sdir_name = args.s
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000354
355 if args.t:
356 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
357
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000358 if args.v:
Zachary Turner606e3a52015-12-08 01:15:30 +0000359 configuration.verbose = 2
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000360
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000361 # argparse makes sure we have a number
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000362 if args.sharp:
Zachary Turner606e3a52015-12-08 01:15:30 +0000363 configuration.count = args.sharp
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000364
365 if sys.platform.startswith('win32'):
366 os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str(args.disable_crash_dialog)
Zachary Turner80310c22015-12-10 18:51:02 +0000367 os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(True)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000368
369 if do_help == True:
370 usage(parser)
371
372 if args.no_multiprocess:
Zachary Turner606e3a52015-12-08 01:15:30 +0000373 configuration.no_multiprocess_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000374
375 if args.inferior:
Zachary Turner606e3a52015-12-08 01:15:30 +0000376 configuration.is_inferior_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000377
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000378 if args.num_threads:
Zachary Turner606e3a52015-12-08 01:15:30 +0000379 configuration.num_threads = args.num_threads
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000380
381 if args.test_subdir:
Zachary Turner606e3a52015-12-08 01:15:30 +0000382 configuration.multiprocess_test_subdir = args.test_subdir
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000383
384 if args.test_runner_name:
Zachary Turner606e3a52015-12-08 01:15:30 +0000385 configuration.test_runner_name = args.test_runner_name
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000386
387 # Capture test results-related args.
Todd Fialacee6a6a2015-11-09 18:51:04 +0000388 if args.curses and not args.inferior:
389 # Act as if the following args were set.
390 args.results_formatter = "lldbsuite.test.curses_results.Curses"
391 args.results_file = "stdout"
392
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000393 if args.results_file:
Zachary Turner606e3a52015-12-08 01:15:30 +0000394 configuration.results_filename = args.results_file
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000395
396 if args.results_port:
Zachary Turner606e3a52015-12-08 01:15:30 +0000397 configuration.results_port = args.results_port
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000398
399 if args.results_file and args.results_port:
400 sys.stderr.write(
401 "only one of --results-file and --results-port should "
402 "be specified\n")
403 usage(args)
404
405 if args.results_formatter:
Zachary Turner606e3a52015-12-08 01:15:30 +0000406 configuration.results_formatter_name = args.results_formatter
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000407 if args.results_formatter_options:
Zachary Turner606e3a52015-12-08 01:15:30 +0000408 configuration.results_formatter_options = args.results_formatter_options
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000409
410 if args.lldb_platform_name:
Zachary Turner606e3a52015-12-08 01:15:30 +0000411 configuration.lldb_platform_name = args.lldb_platform_name
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000412 if args.lldb_platform_url:
Zachary Turner606e3a52015-12-08 01:15:30 +0000413 configuration.lldb_platform_url = args.lldb_platform_url
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000414 if args.lldb_platform_working_dir:
Zachary Turner606e3a52015-12-08 01:15:30 +0000415 configuration.lldb_platform_working_dir = args.lldb_platform_working_dir
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000416
417 if args.event_add_entries and len(args.event_add_entries) > 0:
418 entries = {}
419 # Parse out key=val pairs, separated by comma
420 for keyval in args.event_add_entries.split(","):
421 key_val_entry = keyval.split("=")
422 if len(key_val_entry) == 2:
423 (key, val) = key_val_entry
424 val_parts = val.split(':')
425 if len(val_parts) > 1:
426 (val, val_type) = val_parts
427 if val_type == 'int':
428 val = int(val)
429 entries[key] = val
430 # Tell the event builder to create all events with these
431 # key/val pairs in them.
432 if len(entries) > 0:
Zachary Turner905a9882015-12-07 21:23:41 +0000433 result_formatter.EventBuilder.add_entries_to_all_events(entries)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000434
435 # Gather all the dirs passed on the command line.
436 if len(args.args) > 0:
Zachary Turner606e3a52015-12-08 01:15:30 +0000437 configuration.testdirs = list(map(os.path.abspath, args.args))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000438 # Shut off multiprocessing mode when test directories are specified.
Zachary Turner606e3a52015-12-08 01:15:30 +0000439 configuration.no_multiprocess_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000440
441 # If '-r dir' is specified, the tests should be run under the relocated
442 # directory. Let's copy the testdirs over.
Zachary Turner606e3a52015-12-08 01:15:30 +0000443 if configuration.rdir:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000444 from shutil import copytree, ignore_patterns
445
446 tmpdirs = []
Zachary Turner606e3a52015-12-08 01:15:30 +0000447 orig_testdirs = configuration.testdirs[:]
448 for srcdir in configuration.testdirs:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000449 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint
450 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint'].
451 # Utilize the relative path to the 'test' directory to make our destination dir path.
452 if ("test" + os.sep) in srcdir:
453 to_split_on = "test" + os.sep
454 else:
455 to_split_on = "test"
Zachary Turner606e3a52015-12-08 01:15:30 +0000456 dstdir = os.path.join(configuration.rdir, srcdir.split(to_split_on)[1])
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000457 dstdir = dstdir.rstrip(os.sep)
458 # Don't copy the *.pyc and .svn stuffs.
459 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn'))
460 tmpdirs.append(dstdir)
461
462 # This will be our modified testdirs.
Zachary Turner606e3a52015-12-08 01:15:30 +0000463 configuration.testdirs = tmpdirs
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000464
465 # With '-r dir' specified, there's no cleanup of intermediate test files.
466 os.environ["LLDB_DO_CLEANUP"] = 'NO'
467
468 # If the original testdirs is ['test'], the make directory has already been copied
469 # recursively and is contained within the rdir/test dir. For anything
470 # else, we would need to copy over the make directory and its contents,
471 # so that, os.listdir(rdir) looks like, for example:
472 #
473 # array_types conditional_break make
474 #
475 # where the make directory contains the Makefile.rules file.
Zachary Turner606e3a52015-12-08 01:15:30 +0000476 if len(configuration.testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test':
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000477 scriptdir = os.path.dirname(__file__)
478 # Don't copy the .svn stuffs.
479 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'),
480 ignore=ignore_patterns('.svn'))
481
482 #print("testdirs:", testdirs)
483
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000484def getXcodeOutputPaths(lldbRootDirectory):
485 result = []
486
487 # These are for xcode build directories.
488 xcode3_build_dir = ['build']
489 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
490
491 configurations = [['Debug'], ['DebugClang'], ['Release'], ['BuildAndIntegration']]
492 xcode_build_dirs = [xcode3_build_dir, xcode4_build_dir]
493 for configuration in configurations:
494 for xcode_build_dir in xcode_build_dirs:
495 outputPath = os.path.join(lldbRootDirectory, *(xcode_build_dir+configuration) )
496 result.append(outputPath)
497
498 return result
499
500
501def createSocketToLocalPort(port):
502 def socket_closer(s):
503 """Close down an opened socket properly."""
504 s.shutdown(socket.SHUT_RDWR)
505 s.close()
506
507 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
508 sock.connect(("localhost", port))
509 return (sock, lambda: socket_closer(sock))
510
511
512def setupTestResults():
513 """Sets up test results-related objects based on arg settings."""
Todd Fiala51831472015-12-09 06:45:43 +0000514 # Setup the results formatter configuration.
515 formatter_config = result_formatter.FormatterConfig()
516 formatter_config.filename = configuration.results_filename
517 formatter_config.formatter_name = configuration.results_formatter_name
518 formatter_config.formatter_options = (
519 configuration.results_formatter_options)
520 formatter_config.port = configuration.results_port
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000521
Todd Fialade029392015-12-08 00:53:56 +0000522 # Create the results formatter.
Todd Fiala51831472015-12-09 06:45:43 +0000523 formatter_spec = result_formatter.create_results_formatter(
524 formatter_config)
Todd Fialade029392015-12-08 00:53:56 +0000525 if formatter_spec is not None and formatter_spec.formatter is not None:
Zachary Turner606e3a52015-12-08 01:15:30 +0000526 configuration.results_formatter_object = formatter_spec.formatter
Todd Fiala194913f2015-12-02 21:12:17 +0000527
Todd Fialade029392015-12-08 00:53:56 +0000528 # Send an intialize message to the formatter.
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000529 initialize_event = EventBuilder.bare_event("initialize")
530 if isMultiprocessTestRunner():
Todd Fiala51831472015-12-09 06:45:43 +0000531 if (configuration.test_runner_name is not None and
532 configuration.test_runner_name == "serial"):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000533 # Only one worker queue here.
534 worker_count = 1
535 else:
536 # Workers will be the number of threads specified.
Zachary Turner606e3a52015-12-08 01:15:30 +0000537 worker_count = configuration.num_threads
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000538 else:
539 worker_count = 1
540 initialize_event["worker_count"] = worker_count
541
Todd Fialade029392015-12-08 00:53:56 +0000542 formatter_spec.formatter.handle_event(initialize_event)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000543
Todd Fialade029392015-12-08 00:53:56 +0000544 # Make sure we clean up the formatter on shutdown.
545 if formatter_spec.cleanup_func is not None:
546 atexit.register(formatter_spec.cleanup_func)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000547
548
549def getOutputPaths(lldbRootDirectory):
550 """
551 Returns typical build output paths for the lldb executable
552
553 lldbDirectory - path to the root of the lldb svn/git repo
554 """
555 result = []
556
557 if sys.platform == 'darwin':
558 result.extend(getXcodeOutputPaths(lldbRootDirectory))
559
560 # cmake builds? look for build or build/host folder next to llvm directory
561 # lldb is located in llvm/tools/lldb so we need to go up three levels
562 llvmParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir, os.pardir, os.pardir))
563 result.append(os.path.join(llvmParentDir, 'build', 'bin'))
564 result.append(os.path.join(llvmParentDir, 'build', 'host', 'bin'))
565
566 # some cmake developers keep their build directory beside their lldb directory
567 lldbParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir))
568 result.append(os.path.join(lldbParentDir, 'build', 'bin'))
569 result.append(os.path.join(lldbParentDir, 'build', 'host', 'bin'))
570
571 return result
572
573def setupSysPath():
574 """
575 Add LLDB.framework/Resources/Python to the search paths for modules.
576 As a side effect, we also discover the 'lldb' executable and export it here.
577 """
578
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000579 # Get the directory containing the current script.
580 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
581 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
582 else:
583 scriptPath = os.path.dirname(os.path.realpath(__file__))
584 if not scriptPath.endswith('test'):
585 print("This script expects to reside in lldb's test directory.")
586 sys.exit(-1)
587
Zachary Turner606e3a52015-12-08 01:15:30 +0000588 if configuration.rdir:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000589 # Set up the LLDB_TEST environment variable appropriately, so that the
590 # individual tests can be located relatively.
591 #
592 # See also lldbtest.TestBase.setUpClass(cls).
Zachary Turner606e3a52015-12-08 01:15:30 +0000593 if len(configuration.testdirs) == 1 and os.path.basename(configuration.testdirs[0]) == 'test':
594 os.environ["LLDB_TEST"] = os.path.join(configuration.rdir, 'test')
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000595 else:
Zachary Turner606e3a52015-12-08 01:15:30 +0000596 os.environ["LLDB_TEST"] = configuration.rdir
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000597 else:
598 os.environ["LLDB_TEST"] = scriptPath
599
600 # Set up the LLDB_SRC environment variable, so that the tests can locate
601 # the LLDB source code.
602 os.environ["LLDB_SRC"] = lldbsuite.lldb_root
603
604 pluginPath = os.path.join(scriptPath, 'plugins')
605 toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi')
606 toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')
607
608 # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the sys.path.
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000609 sys.path.insert(0, pluginPath)
610 sys.path.insert(0, toolsLLDBMIPath) # Adding test/tools/lldb-mi to the path makes it easy
611 # to "import lldbmi_testcase" from the MI tests
612 sys.path.insert(0, toolsLLDBServerPath) # Adding test/tools/lldb-server to the path makes it easy
613 # to "import lldbgdbserverutils" from the lldb-server tests
614
615 # This is the root of the lldb git/svn checkout
616 # When this changes over to a package instead of a standalone script, this
617 # will be `lldbsuite.lldb_root`
618 lldbRootDirectory = lldbsuite.lldb_root
619
620 # Some of the tests can invoke the 'lldb' command directly.
621 # We'll try to locate the appropriate executable right here.
622
623 # The lldb executable can be set from the command line
624 # if it's not set, we try to find it now
625 # first, we try the environment
626 if not lldbtest_config.lldbExec:
627 # First, you can define an environment variable LLDB_EXEC specifying the
628 # full pathname of the lldb executable.
629 if "LLDB_EXEC" in os.environ:
630 lldbtest_config.lldbExec = os.environ["LLDB_EXEC"]
631
632 if not lldbtest_config.lldbExec:
633 outputPaths = getOutputPaths(lldbRootDirectory)
634 for outputPath in outputPaths:
635 candidatePath = os.path.join(outputPath, 'lldb')
636 if is_exe(candidatePath):
637 lldbtest_config.lldbExec = candidatePath
638 break
639
640 if not lldbtest_config.lldbExec:
641 # Last, check the path
642 lldbtest_config.lldbExec = which('lldb')
643
644 if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec):
645 print("'{}' is not a path to a valid executable".format(lldbtest_config.lldbExec))
646 lldbtest_config.lldbExec = None
647
648 if not lldbtest_config.lldbExec:
649 print("The 'lldb' executable cannot be located. Some of the tests may not be run as a result.")
650 sys.exit(-1)
651
652 lldbLibDir = os.path.dirname(lldbtest_config.lldbExec) # confusingly, this is the "bin" directory
653 os.environ["LLDB_LIB_DIR"] = lldbLibDir
654 lldbImpLibDir = os.path.join(lldbLibDir, '..', 'lib') if sys.platform.startswith('win32') else lldbLibDir
655 os.environ["LLDB_IMPLIB_DIR"] = lldbImpLibDir
Zachary Turner35a76102015-12-09 20:48:42 +0000656 print("LLDB library dir:", os.environ["LLDB_LIB_DIR"])
657 print("LLDB import library dir:", os.environ["LLDB_IMPLIB_DIR"])
658 os.system('%s -v' % lldbtest_config.lldbExec)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000659
660 # Assume lldb-mi is in same place as lldb
661 # If not found, disable the lldb-mi tests
662 lldbMiExec = None
663 if lldbtest_config.lldbExec and is_exe(lldbtest_config.lldbExec + "-mi"):
664 lldbMiExec = lldbtest_config.lldbExec + "-mi"
665 if not lldbMiExec:
Zachary Turnerb4733e62015-12-08 01:15:44 +0000666 if not configuration.shouldSkipBecauseOfCategories(["lldb-mi"]):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000667 print("The 'lldb-mi' executable cannot be located. The lldb-mi tests can not be run as a result.")
Zachary Turner606e3a52015-12-08 01:15:30 +0000668 configuration.skipCategories.append("lldb-mi")
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000669 else:
670 os.environ["LLDBMI_EXEC"] = lldbMiExec
671
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000672 lldbPythonDir = None # The directory that contains 'lldb/__init__.py'
Zachary Turner606e3a52015-12-08 01:15:30 +0000673 if configuration.lldbFrameworkPath:
674 candidatePath = os.path.join(configuration.lldbFrameworkPath, 'Resources', 'Python')
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000675 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
676 lldbPythonDir = candidatePath
677 if not lldbPythonDir:
Zachary Turner606e3a52015-12-08 01:15:30 +0000678 print('Resources/Python/lldb/__init__.py was not found in ' + configuration.lldbFrameworkPath)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000679 sys.exit(-1)
680 else:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000681 # If our lldb supports the -P option, use it to find the python path:
682 init_in_python_dir = os.path.join('lldb', '__init__.py')
683
Zachary Turnerbbc5b462015-11-04 01:03:47 +0000684 lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000685
686 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")) \
687 and not lldb_dash_p_result.startswith("Traceback"):
688 lines = lldb_dash_p_result.splitlines()
689
690 # Workaround for readline vs libedit issue on FreeBSD. If stdout
691 # is not a terminal Python executes
692 # rl_variable_bind ("enable-meta-key", "off");
693 # This produces a warning with FreeBSD's libedit because the
694 # enable-meta-key variable is unknown. Not an issue on Apple
695 # because cpython commit f0ab6f9f0603 added a #ifndef __APPLE__
696 # around the call. See http://bugs.python.org/issue19884 for more
697 # information. For now we just discard the warning output.
698 if len(lines) >= 1 and lines[0].startswith("bind: Invalid command"):
699 lines.pop(0)
700
701 # Taking the last line because lldb outputs
702 # 'Cannot read termcap database;\nusing dumb terminal settings.\n'
703 # before the path
704 if len(lines) >= 1 and os.path.isfile(os.path.join(lines[-1], init_in_python_dir)):
705 lldbPythonDir = lines[-1]
706 if "freebsd" in sys.platform or "linux" in sys.platform:
707 os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPythonDir, '..', '..')
708
709 if not lldbPythonDir:
710 if platform.system() == "Darwin":
711 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
712 outputPaths = getXcodeOutputPaths()
713 for outputPath in outputPaths:
714 candidatePath = os.path.join(outputPath, python_resource_dir)
715 if os.path.isfile(os.path.join(candidatePath, init_in_python_dir)):
716 lldbPythonDir = candidatePath
717 break
718
719 if not lldbPythonDir:
720 print('This script requires lldb.py to be in either ' + dbgPath + ',', end=' ')
721 print(relPath + ', or ' + baiPath + '. Some tests might fail.')
722 else:
723 print("Unable to load lldb extension module. Possible reasons for this include:")
724 print(" 1) LLDB was built with LLDB_DISABLE_PYTHON=1")
725 print(" 2) PYTHONPATH and PYTHONHOME are not set correctly. PYTHONHOME should refer to")
726 print(" the version of Python that LLDB built and linked against, and PYTHONPATH")
727 print(" should contain the Lib directory for the same python distro, as well as the")
728 print(" location of LLDB\'s site-packages folder.")
729 print(" 3) A different version of Python than that which was built against is exported in")
730 print(" the system\'s PATH environment variable, causing conflicts.")
731 print(" 4) The executable '%s' could not be found. Please check " % lldbExecutable)
732 print(" that it exists and is executable.")
733
734 if lldbPythonDir:
735 lldbPythonDir = os.path.normpath(lldbPythonDir)
736 # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
737 # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
738 (before, frameWithVersion, after) = lldbPythonDir.rpartition("LLDB.framework/Versions/A")
739 if frameWithVersion != "" :
740 lldbPythonDir = before + "LLDB.framework" + after
741
742 lldbPythonDir = os.path.abspath(lldbPythonDir)
743
744 # If tests need to find LLDB_FRAMEWORK, now they can do it
745 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPythonDir))
746
747 # This is to locate the lldb.py module. Insert it right after sys.path[0].
748 sys.path[1:1] = [lldbPythonDir]
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000749
750def visit(prefix, dir, names):
751 """Visitor function for os.path.walk(path, visit, arg)."""
752
Zachary Turner50671582015-12-08 20:36:22 +0000753 dir_components = set(dir.split(os.sep))
754 excluded_components = set(['.svn', '.git'])
755 if dir_components.intersection(excluded_components):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000756 #print("Detected an excluded dir component: %s" % dir)
757 return
758
759 for name in names:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000760 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
761
Zachary Turner606e3a52015-12-08 01:15:30 +0000762 if name in configuration.all_tests:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000763 raise Exception("Found multiple tests with the name %s" % name)
Zachary Turner606e3a52015-12-08 01:15:30 +0000764 configuration.all_tests.add(name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000765
766 # Try to match the regexp pattern, if specified.
Zachary Turner606e3a52015-12-08 01:15:30 +0000767 if configuration.regexp:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000768 import re
Zachary Turner606e3a52015-12-08 01:15:30 +0000769 if re.search(configuration.regexp, name):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000770 #print("Filename: '%s' matches pattern: '%s'" % (name, regexp))
771 pass
772 else:
773 #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp))
774 continue
775
776 # We found a match for our test. Add it to the suite.
777
778 # Update the sys.path first.
779 if not sys.path.count(dir):
780 sys.path.insert(0, dir)
781 base = os.path.splitext(name)[0]
782
783 # Thoroughly check the filterspec against the base module and admit
784 # the (base, filterspec) combination only when it makes sense.
785 filterspec = None
Zachary Turner606e3a52015-12-08 01:15:30 +0000786 for filterspec in configuration.filters:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000787 # Optimistically set the flag to True.
788 filtered = True
789 module = __import__(base)
790 parts = filterspec.split('.')
791 obj = module
792 for part in parts:
793 try:
794 parent, obj = obj, getattr(obj, part)
795 except AttributeError:
796 # The filterspec has failed.
797 filtered = False
798 break
799
800 # If filtered, we have a good filterspec. Add it.
801 if filtered:
802 #print("adding filter spec %s to module %s" % (filterspec, module))
Zachary Turner606e3a52015-12-08 01:15:30 +0000803 configuration.suite.addTests(
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000804 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
805 continue
806
807 # Forgo this module if the (base, filterspec) combo is invalid
Zachary Turner75446022015-12-08 18:48:53 +0000808 if configuration.filters and not filtered:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000809 continue
810
811 # Add either the filtered test case(s) (which is done before) or the entire test class.
812 if not filterspec or not filtered:
813 # A simple case of just the module name. Also the failover case
814 # from the filterspec branch when the (base, filterspec) combo
815 # doesn't make sense.
Zachary Turner606e3a52015-12-08 01:15:30 +0000816 configuration.suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000817
818
819def disabledynamics():
820 import lldb
821 ci = lldb.DBG.GetCommandInterpreter()
822 res = lldb.SBCommandReturnObject()
823 ci.HandleCommand("setting set target.prefer-dynamic-value no-dynamic-values", res, False)
824 if not res.Succeeded():
825 raise Exception('disabling dynamic type support failed')
826
827def lldbLoggings():
828 import lldb
829 """Check and do lldb loggings if necessary."""
830
831 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
832 # defined. Use ${LLDB_LOG} to specify the log file.
833 ci = lldb.DBG.GetCommandInterpreter()
834 res = lldb.SBCommandReturnObject()
835 if ("LLDB_LOG" in os.environ):
836 open(os.environ["LLDB_LOG"], 'w').close()
837 if ("LLDB_LOG_OPTION" in os.environ):
838 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
839 else:
840 lldb_log_option = "event process expr state api"
841 ci.HandleCommand(
842 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
843 res)
844 if not res.Succeeded():
845 raise Exception('log enable failed (check LLDB_LOG env variable)')
846
847 if ("LLDB_LINUX_LOG" in os.environ):
848 open(os.environ["LLDB_LINUX_LOG"], 'w').close()
849 if ("LLDB_LINUX_LOG_OPTION" in os.environ):
850 lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"]
851 else:
852 lldb_log_option = "event process expr state api"
853 ci.HandleCommand(
854 "log enable -n -f " + os.environ["LLDB_LINUX_LOG"] + " linux " + lldb_log_option,
855 res)
856 if not res.Succeeded():
857 raise Exception('log enable failed (check LLDB_LINUX_LOG env variable)')
858
859 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
860 # Use ${GDB_REMOTE_LOG} to specify the log file.
861 if ("GDB_REMOTE_LOG" in os.environ):
862 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
863 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
864 else:
865 gdb_remote_log_option = "packets process"
866 ci.HandleCommand(
867 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
868 + gdb_remote_log_option,
869 res)
870 if not res.Succeeded():
871 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable)')
872
873def getMyCommandLine():
874 return ' '.join(sys.argv)
875
876# ======================================== #
877# #
878# Execution of the test driver starts here #
879# #
880# ======================================== #
881
882def checkDsymForUUIDIsNotOn():
883 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
884 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
885 cmd_output = pipe.stdout.read()
886 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
887 print("%s =>" % ' '.join(cmd))
888 print(cmd_output)
889 print("Disable automatic lookup and caching of dSYMs before running the test suite!")
890 print("Exiting...")
891 sys.exit(0)
892
893def exitTestSuite(exitCode = None):
894 import lldb
895 lldb.SBDebugger.Terminate()
896 if exitCode:
897 sys.exit(exitCode)
898
899
900def isMultiprocessTestRunner():
901 # We're not multiprocess when we're either explicitly
902 # the inferior (as specified by the multiprocess test
903 # runner) OR we've been told to skip using the multiprocess
904 # test runner
Zachary Turner606e3a52015-12-08 01:15:30 +0000905 return not (configuration.is_inferior_test_runner or configuration.no_multiprocess_test_runner)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000906
Enrico Granata5f92a132015-11-05 00:46:25 +0000907def getVersionForSDK(sdk):
908 sdk = str.lower(sdk)
909 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
910 basename = os.path.basename(full_path)
911 basename = os.path.splitext(basename)[0]
912 basename = str.lower(basename)
913 ver = basename.replace(sdk, '')
914 return ver
915
916def getPathForSDK(sdk):
917 sdk = str.lower(sdk)
918 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
919 if os.path.exists(full_path): return full_path
920 return None
921
922def setDefaultTripleForPlatform():
Zachary Turner606e3a52015-12-08 01:15:30 +0000923 if configuration.lldb_platform_name == 'ios-simulator':
Enrico Granata5f92a132015-11-05 00:46:25 +0000924 triple_str = 'x86_64-apple-ios%s' % (getVersionForSDK('iphonesimulator'))
925 os.environ['TRIPLE'] = triple_str
926 return {'TRIPLE':triple_str}
927 return {}
928
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000929def run_suite():
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000930 # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
931 # does not exist before proceeding to running the test suite.
932 if sys.platform.startswith("darwin"):
933 checkDsymForUUIDIsNotOn()
934
935 #
936 # Start the actions by first parsing the options while setting up the test
937 # directories, followed by setting up the search paths for lldb utilities;
938 # then, we walk the directory trees and collect the tests into our test suite.
939 #
940 parseOptionsAndInitTestdirs()
941
942 # Setup test results (test results formatter and output handling).
943 setupTestResults()
944
945 # If we are running as the multiprocess test runner, kick off the
946 # multiprocess test runner here.
947 if isMultiprocessTestRunner():
Zachary Turnerc1b7cd72015-11-05 19:22:28 +0000948 from . import dosep
Zachary Turner80310c22015-12-10 18:51:02 +0000949 dosep.main(configuration.num_threads, configuration.multiprocess_test_subdir,
Zachary Turner606e3a52015-12-08 01:15:30 +0000950 configuration.test_runner_name, configuration.results_formatter_object)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000951 raise Exception("should never get here")
Zachary Turner606e3a52015-12-08 01:15:30 +0000952 elif configuration.is_inferior_test_runner:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000953 # Shut off Ctrl-C processing in inferiors. The parallel
954 # test runner handles this more holistically.
955 signal.signal(signal.SIGINT, signal.SIG_IGN)
956
957 setupSysPath()
Pavel Labath9cbf7dd2015-12-08 13:32:07 +0000958 configuration.setupCrashInfoHook()
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000959
960 #
961 # If '-l' is specified, do not skip the long running tests.
Zachary Turner606e3a52015-12-08 01:15:30 +0000962 if not configuration.skip_long_running_test:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000963 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
964
965 # For the time being, let's bracket the test runner within the
966 # lldb.SBDebugger.Initialize()/Terminate() pair.
967 import lldb
968
969 # Create a singleton SBDebugger in the lldb namespace.
970 lldb.DBG = lldb.SBDebugger.Create()
971
Zachary Turner606e3a52015-12-08 01:15:30 +0000972 if configuration.lldb_platform_name:
973 print("Setting up remote platform '%s'" % (configuration.lldb_platform_name))
974 lldb.remote_platform = lldb.SBPlatform(configuration.lldb_platform_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000975 if not lldb.remote_platform.IsValid():
Zachary Turner606e3a52015-12-08 01:15:30 +0000976 print("error: unable to create the LLDB platform named '%s'." % (configuration.lldb_platform_name))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000977 exitTestSuite(1)
Zachary Turner606e3a52015-12-08 01:15:30 +0000978 if configuration.lldb_platform_url:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000979 # We must connect to a remote platform if a LLDB platform URL was specified
Zachary Turner606e3a52015-12-08 01:15:30 +0000980 print("Connecting to remote platform '%s' at '%s'..." % (configuration.lldb_platform_name, configuration.lldb_platform_url))
981 platform_connect_options = lldb.SBPlatformConnectOptions(configuration.lldb_platform_url)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000982 err = lldb.remote_platform.ConnectRemote(platform_connect_options)
983 if err.Success():
984 print("Connected.")
985 else:
Zachary Turner606e3a52015-12-08 01:15:30 +0000986 print("error: failed to connect to remote platform using URL '%s': %s" % (configuration.lldb_platform_url, err))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000987 exitTestSuite(1)
988 else:
Zachary Turner606e3a52015-12-08 01:15:30 +0000989 configuration.lldb_platform_url = None
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000990
Enrico Granata5f92a132015-11-05 00:46:25 +0000991 platform_changes = setDefaultTripleForPlatform()
992 first = True
993 for key in platform_changes:
994 if first:
995 print("Environment variables setup for platform support:")
996 first = False
997 print("%s = %s" % (key,platform_changes[key]))
998
Zachary Turner606e3a52015-12-08 01:15:30 +0000999 if configuration.lldb_platform_working_dir:
1000 print("Setting remote platform working directory to '%s'..." % (configuration.lldb_platform_working_dir))
1001 lldb.remote_platform.SetWorkingDirectory(configuration.lldb_platform_working_dir)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001002 lldb.DBG.SetSelectedPlatform(lldb.remote_platform)
1003 else:
1004 lldb.remote_platform = None
Zachary Turner606e3a52015-12-08 01:15:30 +00001005 configuration.lldb_platform_working_dir = None
1006 configuration.lldb_platform_url = None
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001007
1008 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
1009
1010 # By default, both dsym, dwarf and dwo tests are performed.
1011 # Use @dsym_test, @dwarf_test or @dwo_test decorators, defined in lldbtest.py, to mark a test as
1012 # a dsym, dwarf or dwo test. Use '-N dsym', '-N dwarf' or '-N dwo' to exclude dsym, dwarf or
1013 # dwo tests from running.
Zachary Turner606e3a52015-12-08 01:15:30 +00001014 configuration.dont_do_dsym_test = configuration.dont_do_dsym_test \
1015 or any(platform in target_platform for platform in ["linux", "freebsd", "windows"])
1016 configuration.dont_do_dwo_test = configuration.dont_do_dwo_test \
1017 or any(platform in target_platform for platform in ["darwin", "macosx", "ios"])
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001018
1019 # Don't do debugserver tests on everything except OS X.
Zachary Turner606e3a52015-12-08 01:15:30 +00001020 configuration.dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001021
1022 # Don't do lldb-server (llgs) tests on anything except Linux.
Zachary Turner606e3a52015-12-08 01:15:30 +00001023 configuration.dont_do_llgs_test = not ("linux" in target_platform)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001024
1025 #
1026 # Walk through the testdirs while collecting tests.
1027 #
Zachary Turner606e3a52015-12-08 01:15:30 +00001028 for testdir in configuration.testdirs:
Zachary Turnere6ba0532015-11-05 01:33:54 +00001029 for (dirpath, dirnames, filenames) in os.walk(testdir):
1030 visit('Test', dirpath, filenames)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001031
1032 #
1033 # Now that we have loaded all the test cases, run the whole test suite.
1034 #
1035
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001036 # Turn on lldb loggings if necessary.
1037 lldbLoggings()
1038
1039 # Disable default dynamic types for testing purposes
1040 disabledynamics()
1041
1042 # Install the control-c handler.
1043 unittest2.signals.installHandler()
1044
1045 # If sdir_name is not specified through the '-s sdir_name' option, get a
1046 # timestamp string and export it as LLDB_SESSION_DIR environment var. This will
1047 # be used when/if we want to dump the session info of individual test cases
1048 # later on.
1049 #
1050 # See also TestBase.dumpSessionInfo() in lldbtest.py.
1051 import datetime
1052 # The windows platforms don't like ':' in the pathname.
1053 timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Zachary Turner606e3a52015-12-08 01:15:30 +00001054 if not configuration.sdir_name:
1055 configuration.sdir_name = timestamp_started
1056 os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), configuration.sdir_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001057
Zachary Turner35a76102015-12-09 20:48:42 +00001058 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
1059 " will go into directory '%s'\n" % configuration.sdir_name)
1060 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001061
Zachary Turner606e3a52015-12-08 01:15:30 +00001062 if not os.path.isdir(configuration.sdir_name):
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001063 try:
Zachary Turner606e3a52015-12-08 01:15:30 +00001064 os.mkdir(configuration.sdir_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001065 except OSError as exception:
1066 if exception.errno != errno.EEXIST:
1067 raise
1068 where_to_save_session = os.getcwd()
Zachary Turner606e3a52015-12-08 01:15:30 +00001069 fname = os.path.join(configuration.sdir_name, "TestStarted-%d" % os.getpid())
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001070 with open(fname, "w") as f:
1071 print("Test started at: %s\n" % timestamp_started, file=f)
Zachary Turner606e3a52015-12-08 01:15:30 +00001072 print(configuration.svn_info, file=f)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001073 print("Command invoked: %s\n" % getMyCommandLine(), file=f)
1074
1075 #
1076 # Invoke the default TextTestRunner to run the test suite, possibly iterating
1077 # over different configurations.
1078 #
1079
1080 iterArchs = False
1081 iterCompilers = False
1082
Zachary Turner606e3a52015-12-08 01:15:30 +00001083 if isinstance(configuration.archs, list) and len(configuration.archs) >= 1:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001084 iterArchs = True
1085
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001086 #
1087 # Add some intervention here to sanity check that the compilers requested are sane.
1088 # If found not to be an executable program, the invalid one is dropped from the list.
Zachary Turner606e3a52015-12-08 01:15:30 +00001089 for i in range(len(configuration.compilers)):
1090 c = configuration.compilers[i]
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001091 if which(c):
1092 continue
1093 else:
1094 if sys.platform.startswith("darwin"):
1095 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1096 cmd_output = pipe.stdout.read()
1097 if cmd_output:
1098 if "not found" in cmd_output:
1099 print("dropping %s from the compilers used" % c)
Zachary Turner606e3a52015-12-08 01:15:30 +00001100 configuration.compilers.remove(i)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001101 else:
Zachary Turner606e3a52015-12-08 01:15:30 +00001102 configuration.compilers[i] = cmd_output.split('\n')[0]
1103 print("'xcrun -find %s' returning %s" % (c, configuration.compilers[i]))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001104
Zachary Turner606e3a52015-12-08 01:15:30 +00001105 if not configuration.parsable:
1106 print("compilers=%s" % str(configuration.compilers))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001107
Zachary Turner606e3a52015-12-08 01:15:30 +00001108 if not configuration.compilers or len(configuration.compilers) == 0:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001109 print("No eligible compiler found, exiting.")
1110 exitTestSuite(1)
1111
Zachary Turner606e3a52015-12-08 01:15:30 +00001112 if isinstance(configuration.compilers, list) and len(configuration.compilers) >= 1:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001113 iterCompilers = True
1114
1115 # Make a shallow copy of sys.path, we need to manipulate the search paths later.
1116 # This is only necessary if we are relocated and with different configurations.
Zachary Turner606e3a52015-12-08 01:15:30 +00001117 if configuration.rdir:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001118 old_sys_path = sys.path[:]
1119 # If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1120 if iterArchs or iterCompilers:
1121 old_stderr = sys.stderr
1122 old_stdout = sys.stdout
1123 new_stderr = None
1124 new_stdout = None
1125
1126 # Iterating over all possible architecture and compiler combinations.
Zachary Turner606e3a52015-12-08 01:15:30 +00001127 for ia in range(len(configuration.archs) if iterArchs else 1):
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001128 archConfig = ""
1129 if iterArchs:
Zachary Turner606e3a52015-12-08 01:15:30 +00001130 os.environ["ARCH"] = configuration.archs[ia]
1131 archConfig = "arch=%s" % configuration.archs[ia]
1132 for ic in range(len(configuration.compilers) if iterCompilers else 1):
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001133 if iterCompilers:
Zachary Turner606e3a52015-12-08 01:15:30 +00001134 os.environ["CC"] = configuration.compilers[ic]
1135 configString = "%s compiler=%s" % (archConfig, configuration.compilers[ic])
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001136 else:
1137 configString = archConfig
1138
1139 if iterArchs or iterCompilers:
1140 # Translate ' ' to '-' for pathname component.
Zachary Turnere73a0602015-11-06 21:37:33 +00001141 if six.PY2:
Chaoren Linc0a55532015-11-06 22:30:30 +00001142 import string
Zachary Turnere73a0602015-11-06 21:37:33 +00001143 tbl = string.maketrans(' ', '-')
1144 else:
1145 tbl = str.maketrans(' ', '-')
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001146 configPostfix = configString.translate(tbl)
1147
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001148 # If we specified a relocated directory to run the test suite, do
1149 # the extra housekeeping to copy the testdirs to a configStringified
1150 # directory and to update sys.path before invoking the test runner.
1151 # The purpose is to separate the configuration-specific directories
1152 # from each other.
Zachary Turner606e3a52015-12-08 01:15:30 +00001153 if configuration.rdir:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001154 from shutil import copytree, rmtree, ignore_patterns
1155
1156 newrdir = "%s.%s" % (rdir, configPostfix)
1157
1158 # Copy the tree to a new directory with postfix name configPostfix.
1159 if os.path.exists(newrdir):
1160 rmtree(newrdir)
1161 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d'))
1162
1163 # Update the LLDB_TEST environment variable to reflect new top
1164 # level test directory.
1165 #
1166 # See also lldbtest.TestBase.setUpClass(cls).
Zachary Turner606e3a52015-12-08 01:15:30 +00001167 if len(configuration.testdirs) == 1 and os.path.basename(configuration.testdirs[0]) == 'test':
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001168 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test')
1169 else:
1170 os.environ["LLDB_TEST"] = newrdir
1171
1172 # And update the Python search paths for modules.
1173 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path]
1174
1175 # Output the configuration.
Zachary Turner606e3a52015-12-08 01:15:30 +00001176 if not configuration.parsable:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001177 sys.stderr.write("\nConfiguration: " + configString + "\n")
1178
1179 #print("sys.stderr name is", sys.stderr.name)
1180 #print("sys.stdout name is", sys.stdout.name)
1181
1182 # First, write out the number of collected test cases.
Zachary Turner606e3a52015-12-08 01:15:30 +00001183 if not configuration.parsable:
Pavel Labathbddf1802015-12-08 12:09:56 +00001184 sys.stderr.write(configuration.separator + "\n")
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001185 sys.stderr.write("Collected %d test%s\n\n"
Zachary Turner606e3a52015-12-08 01:15:30 +00001186 % (configuration.suite.countTestCases(),
1187 configuration.suite.countTestCases() != 1 and "s" or ""))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001188
Zachary Turner606e3a52015-12-08 01:15:30 +00001189 if configuration.parsable:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001190 v = 0
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001191 else:
Zachary Turner606e3a52015-12-08 01:15:30 +00001192 v = configuration.verbose
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001193
1194 # Invoke the test runner.
Zachary Turner606e3a52015-12-08 01:15:30 +00001195 if configuration.count == 1:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001196 result = unittest2.TextTestRunner(stream=sys.stderr,
1197 verbosity=v,
Zachary Turnerb4733e62015-12-08 01:15:44 +00001198 resultclass=test_result.LLDBTestResult).run(configuration.suite)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001199 else:
1200 # We are invoking the same test suite more than once. In this case,
1201 # mark __ignore_singleton__ flag as True so the signleton pattern is
1202 # not enforced.
Zachary Turnerb4733e62015-12-08 01:15:44 +00001203 test_result.LLDBTestResult.__ignore_singleton__ = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001204 for i in range(count):
1205
1206 result = unittest2.TextTestRunner(stream=sys.stderr,
1207 verbosity=v,
Zachary Turnerb4733e62015-12-08 01:15:44 +00001208 resultclass=test_result.LLDBTestResult).run(configuration.suite)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001209
Zachary Turner606e3a52015-12-08 01:15:30 +00001210 configuration.failed = configuration.failed or not result.wasSuccessful()
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001211
Zachary Turner606e3a52015-12-08 01:15:30 +00001212 if configuration.sdir_has_content and not configuration.parsable:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001213 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
Zachary Turner606e3a52015-12-08 01:15:30 +00001214 " can be found in directory '%s'\n" % configuration.sdir_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001215
Zachary Turner606e3a52015-12-08 01:15:30 +00001216 if configuration.useCategories and len(configuration.failuresPerCategory) > 0:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001217 sys.stderr.write("Failures per category:\n")
Zachary Turner606e3a52015-12-08 01:15:30 +00001218 for category in configuration.failuresPerCategory:
1219 sys.stderr.write("%s - %d\n" % (category, configuration.failuresPerCategory[category]))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001220
1221 os.chdir(where_to_save_session)
Zachary Turner606e3a52015-12-08 01:15:30 +00001222 fname = os.path.join(configuration.sdir_name, "TestFinished-%d" % os.getpid())
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001223 with open(fname, "w") as f:
1224 print("Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S"), file=f)
1225
1226 # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1227 # This should not be necessary now.
1228 if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
1229 print("Terminating Test suite...")
1230 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1231
1232 # Exiting.
Zachary Turner606e3a52015-12-08 01:15:30 +00001233 exitTestSuite(configuration.failed)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001234
1235if __name__ == "__main__":
Zachary Turner7d564542015-11-02 19:19:49 +00001236 print(__file__ + " is for use as a module only. It should not be run as a standalone script.")
1237 sys.exit(-1)