blob: 723f26a417e449db684adb89086883982cb2df5a [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
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000284 if args.d:
285 sys.stdout.write("Suspending the process %d to wait for debugger to attach...\n" % os.getpid())
286 sys.stdout.flush()
287 os.kill(os.getpid(), signal.SIGSTOP)
288
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000289 if args.f:
290 if any([x.startswith('-') for x in args.f]):
291 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000292 configuration.filters.extend(args.f)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000293 # Shut off multiprocessing mode when additional filters are specified.
294 # The rational is that the user is probably going after a very specific
295 # test and doesn't need a bunch of parallel test runners all looking for
296 # it in a frenzy. Also, '-v' now spits out all test run output even
297 # on success, so the standard recipe for redoing a failing test (with -v
298 # and a -f to filter to the specific test) now causes all test scanning
299 # (in parallel) to print results for do-nothing runs in a very distracting
300 # manner. If we really need filtered parallel runs in the future, consider
301 # adding a --no-output-on-success that prevents -v from setting
302 # output-on-success.
Zachary Turner606e3a52015-12-08 01:15:30 +0000303 configuration.no_multiprocess_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000304
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000305 if args.l:
Zachary Turner606e3a52015-12-08 01:15:30 +0000306 configuration.skip_long_running_test = False
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000307
308 if args.framework:
Zachary Turner606e3a52015-12-08 01:15:30 +0000309 configuration.lldbFrameworkPath = args.framework
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000310
311 if args.executable:
312 lldbtest_config.lldbExec = args.executable
313
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000314 if args.p:
315 if args.p.startswith('-'):
316 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000317 configuration.regexp = args.p
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000318
319 if args.q:
Zachary Turner606e3a52015-12-08 01:15:30 +0000320 configuration.parsable = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000321
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000322 if args.s:
323 if args.s.startswith('-'):
324 usage(parser)
Zachary Turner606e3a52015-12-08 01:15:30 +0000325 configuration.sdir_name = args.s
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000326
327 if args.t:
328 os.environ['LLDB_COMMAND_TRACE'] = 'YES'
329
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000330 if args.v:
Zachary Turner606e3a52015-12-08 01:15:30 +0000331 configuration.verbose = 2
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000332
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000333 # argparse makes sure we have a number
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000334 if args.sharp:
Zachary Turner606e3a52015-12-08 01:15:30 +0000335 configuration.count = args.sharp
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000336
337 if sys.platform.startswith('win32'):
338 os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str(args.disable_crash_dialog)
Zachary Turner80310c22015-12-10 18:51:02 +0000339 os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(True)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000340
341 if do_help == True:
342 usage(parser)
343
344 if args.no_multiprocess:
Zachary Turner606e3a52015-12-08 01:15:30 +0000345 configuration.no_multiprocess_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000346
347 if args.inferior:
Zachary Turner606e3a52015-12-08 01:15:30 +0000348 configuration.is_inferior_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000349
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000350 if args.num_threads:
Zachary Turner606e3a52015-12-08 01:15:30 +0000351 configuration.num_threads = args.num_threads
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000352
353 if args.test_subdir:
Zachary Turner606e3a52015-12-08 01:15:30 +0000354 configuration.multiprocess_test_subdir = args.test_subdir
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000355
356 if args.test_runner_name:
Zachary Turner606e3a52015-12-08 01:15:30 +0000357 configuration.test_runner_name = args.test_runner_name
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000358
359 # Capture test results-related args.
Todd Fialacee6a6a2015-11-09 18:51:04 +0000360 if args.curses and not args.inferior:
361 # Act as if the following args were set.
362 args.results_formatter = "lldbsuite.test.curses_results.Curses"
363 args.results_file = "stdout"
364
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000365 if args.results_file:
Zachary Turner606e3a52015-12-08 01:15:30 +0000366 configuration.results_filename = args.results_file
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000367
368 if args.results_port:
Zachary Turner606e3a52015-12-08 01:15:30 +0000369 configuration.results_port = args.results_port
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000370
371 if args.results_file and args.results_port:
372 sys.stderr.write(
373 "only one of --results-file and --results-port should "
374 "be specified\n")
375 usage(args)
376
377 if args.results_formatter:
Zachary Turner606e3a52015-12-08 01:15:30 +0000378 configuration.results_formatter_name = args.results_formatter
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000379 if args.results_formatter_options:
Zachary Turner606e3a52015-12-08 01:15:30 +0000380 configuration.results_formatter_options = args.results_formatter_options
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000381
Todd Fialab68dbfa22015-12-11 22:29:34 +0000382 # Default to using the BasicResultsFormatter if no formatter is specified
383 # and we're not a test inferior.
384 if not args.inferior and configuration.results_formatter_name is None:
385 configuration.results_formatter_name = (
Todd Fiala6d3de122015-12-15 21:33:38 +0000386 "lldbsuite.test.result_formatter.ResultsFormatter")
Todd Fialab68dbfa22015-12-11 22:29:34 +0000387
Todd Fiala93153922015-12-12 19:26:56 +0000388 # rerun-related arguments
389 configuration.rerun_all_issues = args.rerun_all_issues
Todd Fiala685a7572015-12-14 21:28:46 +0000390 configuration.rerun_max_file_threshold = args.rerun_max_file_threshold
Todd Fiala93153922015-12-12 19:26:56 +0000391
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000392 if args.lldb_platform_name:
Zachary Turner606e3a52015-12-08 01:15:30 +0000393 configuration.lldb_platform_name = args.lldb_platform_name
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000394 if args.lldb_platform_url:
Zachary Turner606e3a52015-12-08 01:15:30 +0000395 configuration.lldb_platform_url = args.lldb_platform_url
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000396 if args.lldb_platform_working_dir:
Zachary Turner606e3a52015-12-08 01:15:30 +0000397 configuration.lldb_platform_working_dir = args.lldb_platform_working_dir
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000398
399 if args.event_add_entries and len(args.event_add_entries) > 0:
400 entries = {}
401 # Parse out key=val pairs, separated by comma
402 for keyval in args.event_add_entries.split(","):
403 key_val_entry = keyval.split("=")
404 if len(key_val_entry) == 2:
405 (key, val) = key_val_entry
406 val_parts = val.split(':')
407 if len(val_parts) > 1:
408 (val, val_type) = val_parts
409 if val_type == 'int':
410 val = int(val)
411 entries[key] = val
412 # Tell the event builder to create all events with these
413 # key/val pairs in them.
414 if len(entries) > 0:
Zachary Turner905a9882015-12-07 21:23:41 +0000415 result_formatter.EventBuilder.add_entries_to_all_events(entries)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000416
417 # Gather all the dirs passed on the command line.
418 if len(args.args) > 0:
Enrico Granatab1329382015-12-16 01:15:49 +0000419 configuration.testdirs = list(map(lambda x: os.path.realpath(os.path.abspath(x)), args.args))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000420 # Shut off multiprocessing mode when test directories are specified.
Zachary Turner606e3a52015-12-08 01:15:30 +0000421 configuration.no_multiprocess_test_runner = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000422
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000423 #print("testdirs:", testdirs)
424
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000425def getXcodeOutputPaths(lldbRootDirectory):
426 result = []
427
428 # These are for xcode build directories.
429 xcode3_build_dir = ['build']
430 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products']
431
432 configurations = [['Debug'], ['DebugClang'], ['Release'], ['BuildAndIntegration']]
433 xcode_build_dirs = [xcode3_build_dir, xcode4_build_dir]
434 for configuration in configurations:
435 for xcode_build_dir in xcode_build_dirs:
436 outputPath = os.path.join(lldbRootDirectory, *(xcode_build_dir+configuration) )
437 result.append(outputPath)
438
439 return result
440
441
442def createSocketToLocalPort(port):
443 def socket_closer(s):
444 """Close down an opened socket properly."""
445 s.shutdown(socket.SHUT_RDWR)
446 s.close()
447
448 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
449 sock.connect(("localhost", port))
450 return (sock, lambda: socket_closer(sock))
451
452
453def setupTestResults():
454 """Sets up test results-related objects based on arg settings."""
Todd Fiala51831472015-12-09 06:45:43 +0000455 # Setup the results formatter configuration.
456 formatter_config = result_formatter.FormatterConfig()
457 formatter_config.filename = configuration.results_filename
458 formatter_config.formatter_name = configuration.results_formatter_name
459 formatter_config.formatter_options = (
460 configuration.results_formatter_options)
461 formatter_config.port = configuration.results_port
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000462
Todd Fialade029392015-12-08 00:53:56 +0000463 # Create the results formatter.
Todd Fiala51831472015-12-09 06:45:43 +0000464 formatter_spec = result_formatter.create_results_formatter(
465 formatter_config)
Todd Fialade029392015-12-08 00:53:56 +0000466 if formatter_spec is not None and formatter_spec.formatter is not None:
Zachary Turner606e3a52015-12-08 01:15:30 +0000467 configuration.results_formatter_object = formatter_spec.formatter
Todd Fiala194913f2015-12-02 21:12:17 +0000468
Todd Fialade029392015-12-08 00:53:56 +0000469 # Send an intialize message to the formatter.
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000470 initialize_event = EventBuilder.bare_event("initialize")
471 if isMultiprocessTestRunner():
Todd Fiala51831472015-12-09 06:45:43 +0000472 if (configuration.test_runner_name is not None and
473 configuration.test_runner_name == "serial"):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000474 # Only one worker queue here.
475 worker_count = 1
476 else:
477 # Workers will be the number of threads specified.
Zachary Turner606e3a52015-12-08 01:15:30 +0000478 worker_count = configuration.num_threads
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000479 else:
480 worker_count = 1
481 initialize_event["worker_count"] = worker_count
482
Todd Fialade029392015-12-08 00:53:56 +0000483 formatter_spec.formatter.handle_event(initialize_event)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000484
Todd Fialade029392015-12-08 00:53:56 +0000485 # Make sure we clean up the formatter on shutdown.
486 if formatter_spec.cleanup_func is not None:
487 atexit.register(formatter_spec.cleanup_func)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000488
489
490def getOutputPaths(lldbRootDirectory):
491 """
492 Returns typical build output paths for the lldb executable
493
494 lldbDirectory - path to the root of the lldb svn/git repo
495 """
496 result = []
497
498 if sys.platform == 'darwin':
499 result.extend(getXcodeOutputPaths(lldbRootDirectory))
500
501 # cmake builds? look for build or build/host folder next to llvm directory
502 # lldb is located in llvm/tools/lldb so we need to go up three levels
503 llvmParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir, os.pardir, os.pardir))
504 result.append(os.path.join(llvmParentDir, 'build', 'bin'))
505 result.append(os.path.join(llvmParentDir, 'build', 'host', 'bin'))
506
507 # some cmake developers keep their build directory beside their lldb directory
508 lldbParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir))
509 result.append(os.path.join(lldbParentDir, 'build', 'bin'))
510 result.append(os.path.join(lldbParentDir, 'build', 'host', 'bin'))
511
512 return result
513
514def setupSysPath():
515 """
516 Add LLDB.framework/Resources/Python to the search paths for modules.
517 As a side effect, we also discover the 'lldb' executable and export it here.
518 """
519
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000520 # Get the directory containing the current script.
521 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ:
522 scriptPath = os.environ["DOTEST_SCRIPT_DIR"]
523 else:
524 scriptPath = os.path.dirname(os.path.realpath(__file__))
525 if not scriptPath.endswith('test'):
526 print("This script expects to reside in lldb's test directory.")
527 sys.exit(-1)
528
Zachary Turner6a188e62015-12-11 19:21:34 +0000529 os.environ["LLDB_TEST"] = scriptPath
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000530
531 # Set up the LLDB_SRC environment variable, so that the tests can locate
532 # the LLDB source code.
533 os.environ["LLDB_SRC"] = lldbsuite.lldb_root
534
535 pluginPath = os.path.join(scriptPath, 'plugins')
536 toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi')
537 toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')
538
539 # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the sys.path.
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000540 sys.path.insert(0, pluginPath)
541 sys.path.insert(0, toolsLLDBMIPath) # Adding test/tools/lldb-mi to the path makes it easy
542 # to "import lldbmi_testcase" from the MI tests
543 sys.path.insert(0, toolsLLDBServerPath) # Adding test/tools/lldb-server to the path makes it easy
544 # to "import lldbgdbserverutils" from the lldb-server tests
545
546 # This is the root of the lldb git/svn checkout
547 # When this changes over to a package instead of a standalone script, this
548 # will be `lldbsuite.lldb_root`
549 lldbRootDirectory = lldbsuite.lldb_root
550
551 # Some of the tests can invoke the 'lldb' command directly.
552 # We'll try to locate the appropriate executable right here.
553
554 # The lldb executable can be set from the command line
555 # if it's not set, we try to find it now
556 # first, we try the environment
557 if not lldbtest_config.lldbExec:
558 # First, you can define an environment variable LLDB_EXEC specifying the
559 # full pathname of the lldb executable.
560 if "LLDB_EXEC" in os.environ:
561 lldbtest_config.lldbExec = os.environ["LLDB_EXEC"]
562
563 if not lldbtest_config.lldbExec:
564 outputPaths = getOutputPaths(lldbRootDirectory)
565 for outputPath in outputPaths:
566 candidatePath = os.path.join(outputPath, 'lldb')
567 if is_exe(candidatePath):
568 lldbtest_config.lldbExec = candidatePath
569 break
570
571 if not lldbtest_config.lldbExec:
572 # Last, check the path
573 lldbtest_config.lldbExec = which('lldb')
574
575 if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec):
576 print("'{}' is not a path to a valid executable".format(lldbtest_config.lldbExec))
577 lldbtest_config.lldbExec = None
578
579 if not lldbtest_config.lldbExec:
580 print("The 'lldb' executable cannot be located. Some of the tests may not be run as a result.")
581 sys.exit(-1)
582
583 lldbLibDir = os.path.dirname(lldbtest_config.lldbExec) # confusingly, this is the "bin" directory
584 os.environ["LLDB_LIB_DIR"] = lldbLibDir
585 lldbImpLibDir = os.path.join(lldbLibDir, '..', 'lib') if sys.platform.startswith('win32') else lldbLibDir
586 os.environ["LLDB_IMPLIB_DIR"] = lldbImpLibDir
Zachary Turner35a76102015-12-09 20:48:42 +0000587 print("LLDB library dir:", os.environ["LLDB_LIB_DIR"])
588 print("LLDB import library dir:", os.environ["LLDB_IMPLIB_DIR"])
589 os.system('%s -v' % lldbtest_config.lldbExec)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000590
591 # Assume lldb-mi is in same place as lldb
592 # If not found, disable the lldb-mi tests
593 lldbMiExec = None
594 if lldbtest_config.lldbExec and is_exe(lldbtest_config.lldbExec + "-mi"):
595 lldbMiExec = lldbtest_config.lldbExec + "-mi"
596 if not lldbMiExec:
Zachary Turnerb4733e62015-12-08 01:15:44 +0000597 if not configuration.shouldSkipBecauseOfCategories(["lldb-mi"]):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000598 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 +0000599 configuration.skipCategories.append("lldb-mi")
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000600 else:
601 os.environ["LLDBMI_EXEC"] = lldbMiExec
602
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000603 lldbPythonDir = None # The directory that contains 'lldb/__init__.py'
Zachary Turner606e3a52015-12-08 01:15:30 +0000604 if configuration.lldbFrameworkPath:
605 candidatePath = os.path.join(configuration.lldbFrameworkPath, 'Resources', 'Python')
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000606 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')):
607 lldbPythonDir = candidatePath
608 if not lldbPythonDir:
Zachary Turner606e3a52015-12-08 01:15:30 +0000609 print('Resources/Python/lldb/__init__.py was not found in ' + configuration.lldbFrameworkPath)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000610 sys.exit(-1)
611 else:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000612 # If our lldb supports the -P option, use it to find the python path:
613 init_in_python_dir = os.path.join('lldb', '__init__.py')
614
Zachary Turnerbbc5b462015-11-04 01:03:47 +0000615 lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000616
617 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")) \
618 and not lldb_dash_p_result.startswith("Traceback"):
619 lines = lldb_dash_p_result.splitlines()
620
621 # Workaround for readline vs libedit issue on FreeBSD. If stdout
622 # is not a terminal Python executes
623 # rl_variable_bind ("enable-meta-key", "off");
624 # This produces a warning with FreeBSD's libedit because the
625 # enable-meta-key variable is unknown. Not an issue on Apple
626 # because cpython commit f0ab6f9f0603 added a #ifndef __APPLE__
627 # around the call. See http://bugs.python.org/issue19884 for more
628 # information. For now we just discard the warning output.
629 if len(lines) >= 1 and lines[0].startswith("bind: Invalid command"):
630 lines.pop(0)
631
632 # Taking the last line because lldb outputs
633 # 'Cannot read termcap database;\nusing dumb terminal settings.\n'
634 # before the path
635 if len(lines) >= 1 and os.path.isfile(os.path.join(lines[-1], init_in_python_dir)):
636 lldbPythonDir = lines[-1]
637 if "freebsd" in sys.platform or "linux" in sys.platform:
638 os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPythonDir, '..', '..')
639
640 if not lldbPythonDir:
641 if platform.system() == "Darwin":
642 python_resource_dir = ['LLDB.framework', 'Resources', 'Python']
643 outputPaths = getXcodeOutputPaths()
644 for outputPath in outputPaths:
645 candidatePath = os.path.join(outputPath, python_resource_dir)
646 if os.path.isfile(os.path.join(candidatePath, init_in_python_dir)):
647 lldbPythonDir = candidatePath
648 break
649
650 if not lldbPythonDir:
651 print('This script requires lldb.py to be in either ' + dbgPath + ',', end=' ')
652 print(relPath + ', or ' + baiPath + '. Some tests might fail.')
653 else:
654 print("Unable to load lldb extension module. Possible reasons for this include:")
655 print(" 1) LLDB was built with LLDB_DISABLE_PYTHON=1")
656 print(" 2) PYTHONPATH and PYTHONHOME are not set correctly. PYTHONHOME should refer to")
657 print(" the version of Python that LLDB built and linked against, and PYTHONPATH")
658 print(" should contain the Lib directory for the same python distro, as well as the")
659 print(" location of LLDB\'s site-packages folder.")
660 print(" 3) A different version of Python than that which was built against is exported in")
661 print(" the system\'s PATH environment variable, causing conflicts.")
662 print(" 4) The executable '%s' could not be found. Please check " % lldbExecutable)
663 print(" that it exists and is executable.")
664
665 if lldbPythonDir:
666 lldbPythonDir = os.path.normpath(lldbPythonDir)
667 # Some of the code that uses this path assumes it hasn't resolved the Versions... link.
668 # If the path we've constructed looks like that, then we'll strip out the Versions/A part.
669 (before, frameWithVersion, after) = lldbPythonDir.rpartition("LLDB.framework/Versions/A")
670 if frameWithVersion != "" :
671 lldbPythonDir = before + "LLDB.framework" + after
672
673 lldbPythonDir = os.path.abspath(lldbPythonDir)
674
675 # If tests need to find LLDB_FRAMEWORK, now they can do it
676 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPythonDir))
677
678 # This is to locate the lldb.py module. Insert it right after sys.path[0].
679 sys.path[1:1] = [lldbPythonDir]
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000680
681def visit(prefix, dir, names):
682 """Visitor function for os.path.walk(path, visit, arg)."""
683
Zachary Turner50671582015-12-08 20:36:22 +0000684 dir_components = set(dir.split(os.sep))
685 excluded_components = set(['.svn', '.git'])
686 if dir_components.intersection(excluded_components):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000687 #print("Detected an excluded dir component: %s" % dir)
688 return
689
690 for name in names:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000691 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
692
Zachary Turner606e3a52015-12-08 01:15:30 +0000693 if name in configuration.all_tests:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000694 raise Exception("Found multiple tests with the name %s" % name)
Zachary Turner606e3a52015-12-08 01:15:30 +0000695 configuration.all_tests.add(name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000696
697 # Try to match the regexp pattern, if specified.
Zachary Turner606e3a52015-12-08 01:15:30 +0000698 if configuration.regexp:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000699 import re
Zachary Turner606e3a52015-12-08 01:15:30 +0000700 if re.search(configuration.regexp, name):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000701 #print("Filename: '%s' matches pattern: '%s'" % (name, regexp))
702 pass
703 else:
704 #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp))
705 continue
706
707 # We found a match for our test. Add it to the suite.
708
709 # Update the sys.path first.
710 if not sys.path.count(dir):
711 sys.path.insert(0, dir)
712 base = os.path.splitext(name)[0]
713
714 # Thoroughly check the filterspec against the base module and admit
715 # the (base, filterspec) combination only when it makes sense.
716 filterspec = None
Zachary Turner606e3a52015-12-08 01:15:30 +0000717 for filterspec in configuration.filters:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000718 # Optimistically set the flag to True.
719 filtered = True
720 module = __import__(base)
721 parts = filterspec.split('.')
722 obj = module
723 for part in parts:
724 try:
725 parent, obj = obj, getattr(obj, part)
726 except AttributeError:
727 # The filterspec has failed.
728 filtered = False
729 break
730
731 # If filtered, we have a good filterspec. Add it.
732 if filtered:
733 #print("adding filter spec %s to module %s" % (filterspec, module))
Zachary Turner606e3a52015-12-08 01:15:30 +0000734 configuration.suite.addTests(
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000735 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
736 continue
737
738 # Forgo this module if the (base, filterspec) combo is invalid
Zachary Turner75446022015-12-08 18:48:53 +0000739 if configuration.filters and not filtered:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000740 continue
741
742 # Add either the filtered test case(s) (which is done before) or the entire test class.
743 if not filterspec or not filtered:
744 # A simple case of just the module name. Also the failover case
745 # from the filterspec branch when the (base, filterspec) combo
746 # doesn't make sense.
Zachary Turner606e3a52015-12-08 01:15:30 +0000747 configuration.suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000748
749
750def disabledynamics():
751 import lldb
752 ci = lldb.DBG.GetCommandInterpreter()
753 res = lldb.SBCommandReturnObject()
754 ci.HandleCommand("setting set target.prefer-dynamic-value no-dynamic-values", res, False)
755 if not res.Succeeded():
756 raise Exception('disabling dynamic type support failed')
757
758def lldbLoggings():
759 import lldb
760 """Check and do lldb loggings if necessary."""
761
762 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is
763 # defined. Use ${LLDB_LOG} to specify the log file.
764 ci = lldb.DBG.GetCommandInterpreter()
765 res = lldb.SBCommandReturnObject()
766 if ("LLDB_LOG" in os.environ):
767 open(os.environ["LLDB_LOG"], 'w').close()
768 if ("LLDB_LOG_OPTION" in os.environ):
769 lldb_log_option = os.environ["LLDB_LOG_OPTION"]
770 else:
771 lldb_log_option = "event process expr state api"
772 ci.HandleCommand(
773 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option,
774 res)
775 if not res.Succeeded():
776 raise Exception('log enable failed (check LLDB_LOG env variable)')
777
778 if ("LLDB_LINUX_LOG" in os.environ):
779 open(os.environ["LLDB_LINUX_LOG"], 'w').close()
780 if ("LLDB_LINUX_LOG_OPTION" in os.environ):
781 lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"]
782 else:
783 lldb_log_option = "event process expr state api"
784 ci.HandleCommand(
785 "log enable -n -f " + os.environ["LLDB_LINUX_LOG"] + " linux " + lldb_log_option,
786 res)
787 if not res.Succeeded():
788 raise Exception('log enable failed (check LLDB_LINUX_LOG env variable)')
789
790 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined.
791 # Use ${GDB_REMOTE_LOG} to specify the log file.
792 if ("GDB_REMOTE_LOG" in os.environ):
793 if ("GDB_REMOTE_LOG_OPTION" in os.environ):
794 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"]
795 else:
796 gdb_remote_log_option = "packets process"
797 ci.HandleCommand(
798 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote "
799 + gdb_remote_log_option,
800 res)
801 if not res.Succeeded():
802 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable)')
803
804def getMyCommandLine():
805 return ' '.join(sys.argv)
806
807# ======================================== #
808# #
809# Execution of the test driver starts here #
810# #
811# ======================================== #
812
813def checkDsymForUUIDIsNotOn():
814 cmd = ["defaults", "read", "com.apple.DebugSymbols"]
815 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
816 cmd_output = pipe.stdout.read()
817 if cmd_output and "DBGFileMappedPaths = " in cmd_output:
818 print("%s =>" % ' '.join(cmd))
819 print(cmd_output)
820 print("Disable automatic lookup and caching of dSYMs before running the test suite!")
821 print("Exiting...")
822 sys.exit(0)
823
824def exitTestSuite(exitCode = None):
825 import lldb
826 lldb.SBDebugger.Terminate()
827 if exitCode:
828 sys.exit(exitCode)
829
830
831def isMultiprocessTestRunner():
832 # We're not multiprocess when we're either explicitly
833 # the inferior (as specified by the multiprocess test
834 # runner) OR we've been told to skip using the multiprocess
835 # test runner
Zachary Turner606e3a52015-12-08 01:15:30 +0000836 return not (configuration.is_inferior_test_runner or configuration.no_multiprocess_test_runner)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000837
Enrico Granata5f92a132015-11-05 00:46:25 +0000838def getVersionForSDK(sdk):
839 sdk = str.lower(sdk)
840 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
841 basename = os.path.basename(full_path)
842 basename = os.path.splitext(basename)[0]
843 basename = str.lower(basename)
844 ver = basename.replace(sdk, '')
845 return ver
846
847def getPathForSDK(sdk):
848 sdk = str.lower(sdk)
849 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk)
850 if os.path.exists(full_path): return full_path
851 return None
852
853def setDefaultTripleForPlatform():
Zachary Turner606e3a52015-12-08 01:15:30 +0000854 if configuration.lldb_platform_name == 'ios-simulator':
Enrico Granata5f92a132015-11-05 00:46:25 +0000855 triple_str = 'x86_64-apple-ios%s' % (getVersionForSDK('iphonesimulator'))
856 os.environ['TRIPLE'] = triple_str
857 return {'TRIPLE':triple_str}
858 return {}
859
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000860def run_suite():
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000861 # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults
862 # does not exist before proceeding to running the test suite.
863 if sys.platform.startswith("darwin"):
864 checkDsymForUUIDIsNotOn()
865
866 #
867 # Start the actions by first parsing the options while setting up the test
868 # directories, followed by setting up the search paths for lldb utilities;
869 # then, we walk the directory trees and collect the tests into our test suite.
870 #
871 parseOptionsAndInitTestdirs()
872
873 # Setup test results (test results formatter and output handling).
874 setupTestResults()
875
876 # If we are running as the multiprocess test runner, kick off the
877 # multiprocess test runner here.
878 if isMultiprocessTestRunner():
Zachary Turnerc1b7cd72015-11-05 19:22:28 +0000879 from . import dosep
Zachary Turner80310c22015-12-10 18:51:02 +0000880 dosep.main(configuration.num_threads, configuration.multiprocess_test_subdir,
Zachary Turner606e3a52015-12-08 01:15:30 +0000881 configuration.test_runner_name, configuration.results_formatter_object)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000882 raise Exception("should never get here")
Zachary Turner606e3a52015-12-08 01:15:30 +0000883 elif configuration.is_inferior_test_runner:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000884 # Shut off Ctrl-C processing in inferiors. The parallel
885 # test runner handles this more holistically.
886 signal.signal(signal.SIGINT, signal.SIG_IGN)
887
888 setupSysPath()
Pavel Labath9cbf7dd2015-12-08 13:32:07 +0000889 configuration.setupCrashInfoHook()
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000890
891 #
892 # If '-l' is specified, do not skip the long running tests.
Zachary Turner606e3a52015-12-08 01:15:30 +0000893 if not configuration.skip_long_running_test:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000894 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO"
895
896 # For the time being, let's bracket the test runner within the
897 # lldb.SBDebugger.Initialize()/Terminate() pair.
898 import lldb
899
900 # Create a singleton SBDebugger in the lldb namespace.
901 lldb.DBG = lldb.SBDebugger.Create()
902
Zachary Turner606e3a52015-12-08 01:15:30 +0000903 if configuration.lldb_platform_name:
904 print("Setting up remote platform '%s'" % (configuration.lldb_platform_name))
905 lldb.remote_platform = lldb.SBPlatform(configuration.lldb_platform_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000906 if not lldb.remote_platform.IsValid():
Zachary Turner606e3a52015-12-08 01:15:30 +0000907 print("error: unable to create the LLDB platform named '%s'." % (configuration.lldb_platform_name))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000908 exitTestSuite(1)
Zachary Turner606e3a52015-12-08 01:15:30 +0000909 if configuration.lldb_platform_url:
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000910 # We must connect to a remote platform if a LLDB platform URL was specified
Zachary Turner606e3a52015-12-08 01:15:30 +0000911 print("Connecting to remote platform '%s' at '%s'..." % (configuration.lldb_platform_name, configuration.lldb_platform_url))
912 platform_connect_options = lldb.SBPlatformConnectOptions(configuration.lldb_platform_url)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000913 err = lldb.remote_platform.ConnectRemote(platform_connect_options)
914 if err.Success():
915 print("Connected.")
916 else:
Zachary Turner606e3a52015-12-08 01:15:30 +0000917 print("error: failed to connect to remote platform using URL '%s': %s" % (configuration.lldb_platform_url, err))
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000918 exitTestSuite(1)
919 else:
Zachary Turner606e3a52015-12-08 01:15:30 +0000920 configuration.lldb_platform_url = None
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000921
Enrico Granata5f92a132015-11-05 00:46:25 +0000922 platform_changes = setDefaultTripleForPlatform()
923 first = True
924 for key in platform_changes:
925 if first:
926 print("Environment variables setup for platform support:")
927 first = False
928 print("%s = %s" % (key,platform_changes[key]))
929
Zachary Turner606e3a52015-12-08 01:15:30 +0000930 if configuration.lldb_platform_working_dir:
931 print("Setting remote platform working directory to '%s'..." % (configuration.lldb_platform_working_dir))
932 lldb.remote_platform.SetWorkingDirectory(configuration.lldb_platform_working_dir)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000933 lldb.DBG.SetSelectedPlatform(lldb.remote_platform)
934 else:
935 lldb.remote_platform = None
Zachary Turner606e3a52015-12-08 01:15:30 +0000936 configuration.lldb_platform_working_dir = None
937 configuration.lldb_platform_url = None
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000938
939 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
940
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000941 # Don't do debugserver tests on everything except OS X.
Zachary Turner606e3a52015-12-08 01:15:30 +0000942 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 +0000943
944 # Don't do lldb-server (llgs) tests on anything except Linux.
Zachary Turner606e3a52015-12-08 01:15:30 +0000945 configuration.dont_do_llgs_test = not ("linux" in target_platform)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000946
947 #
948 # Walk through the testdirs while collecting tests.
949 #
Zachary Turner606e3a52015-12-08 01:15:30 +0000950 for testdir in configuration.testdirs:
Zachary Turnere6ba0532015-11-05 01:33:54 +0000951 for (dirpath, dirnames, filenames) in os.walk(testdir):
952 visit('Test', dirpath, filenames)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000953
954 #
955 # Now that we have loaded all the test cases, run the whole test suite.
956 #
957
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000958 # Turn on lldb loggings if necessary.
959 lldbLoggings()
960
961 # Disable default dynamic types for testing purposes
962 disabledynamics()
963
964 # Install the control-c handler.
965 unittest2.signals.installHandler()
966
967 # If sdir_name is not specified through the '-s sdir_name' option, get a
968 # timestamp string and export it as LLDB_SESSION_DIR environment var. This will
969 # be used when/if we want to dump the session info of individual test cases
970 # later on.
971 #
972 # See also TestBase.dumpSessionInfo() in lldbtest.py.
973 import datetime
974 # The windows platforms don't like ':' in the pathname.
975 timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S")
Zachary Turner606e3a52015-12-08 01:15:30 +0000976 if not configuration.sdir_name:
977 configuration.sdir_name = timestamp_started
978 os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), configuration.sdir_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000979
Zachary Turner35a76102015-12-09 20:48:42 +0000980 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes"
981 " will go into directory '%s'\n" % configuration.sdir_name)
982 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine())
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000983
Zachary Turner606e3a52015-12-08 01:15:30 +0000984 if not os.path.isdir(configuration.sdir_name):
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000985 try:
Zachary Turner606e3a52015-12-08 01:15:30 +0000986 os.mkdir(configuration.sdir_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000987 except OSError as exception:
988 if exception.errno != errno.EEXIST:
989 raise
990 where_to_save_session = os.getcwd()
Zachary Turner606e3a52015-12-08 01:15:30 +0000991 fname = os.path.join(configuration.sdir_name, "TestStarted-%d" % os.getpid())
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000992 with open(fname, "w") as f:
993 print("Test started at: %s\n" % timestamp_started, file=f)
Zachary Turner606e3a52015-12-08 01:15:30 +0000994 print(configuration.svn_info, file=f)
Zachary Turnerc432c8f2015-10-28 17:43:26 +0000995 print("Command invoked: %s\n" % getMyCommandLine(), file=f)
996
997 #
998 # Invoke the default TextTestRunner to run the test suite, possibly iterating
999 # over different configurations.
1000 #
1001
1002 iterArchs = False
1003 iterCompilers = False
1004
Zachary Turner606e3a52015-12-08 01:15:30 +00001005 if isinstance(configuration.archs, list) and len(configuration.archs) >= 1:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001006 iterArchs = True
1007
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001008 #
1009 # Add some intervention here to sanity check that the compilers requested are sane.
1010 # If found not to be an executable program, the invalid one is dropped from the list.
Zachary Turner606e3a52015-12-08 01:15:30 +00001011 for i in range(len(configuration.compilers)):
1012 c = configuration.compilers[i]
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001013 if which(c):
1014 continue
1015 else:
1016 if sys.platform.startswith("darwin"):
1017 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
1018 cmd_output = pipe.stdout.read()
1019 if cmd_output:
1020 if "not found" in cmd_output:
1021 print("dropping %s from the compilers used" % c)
Zachary Turner606e3a52015-12-08 01:15:30 +00001022 configuration.compilers.remove(i)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001023 else:
Zachary Turner606e3a52015-12-08 01:15:30 +00001024 configuration.compilers[i] = cmd_output.split('\n')[0]
1025 print("'xcrun -find %s' returning %s" % (c, configuration.compilers[i]))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001026
Zachary Turner606e3a52015-12-08 01:15:30 +00001027 if not configuration.parsable:
1028 print("compilers=%s" % str(configuration.compilers))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001029
Zachary Turner606e3a52015-12-08 01:15:30 +00001030 if not configuration.compilers or len(configuration.compilers) == 0:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001031 print("No eligible compiler found, exiting.")
1032 exitTestSuite(1)
1033
Zachary Turner606e3a52015-12-08 01:15:30 +00001034 if isinstance(configuration.compilers, list) and len(configuration.compilers) >= 1:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001035 iterCompilers = True
1036
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001037 # If we iterate on archs or compilers, there is a chance we want to split stderr/stdout.
1038 if iterArchs or iterCompilers:
1039 old_stderr = sys.stderr
1040 old_stdout = sys.stdout
1041 new_stderr = None
1042 new_stdout = None
1043
1044 # Iterating over all possible architecture and compiler combinations.
Zachary Turner606e3a52015-12-08 01:15:30 +00001045 for ia in range(len(configuration.archs) if iterArchs else 1):
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001046 archConfig = ""
1047 if iterArchs:
Zachary Turner606e3a52015-12-08 01:15:30 +00001048 os.environ["ARCH"] = configuration.archs[ia]
1049 archConfig = "arch=%s" % configuration.archs[ia]
1050 for ic in range(len(configuration.compilers) if iterCompilers else 1):
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001051 if iterCompilers:
Zachary Turner606e3a52015-12-08 01:15:30 +00001052 os.environ["CC"] = configuration.compilers[ic]
1053 configString = "%s compiler=%s" % (archConfig, configuration.compilers[ic])
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001054 else:
1055 configString = archConfig
1056
1057 if iterArchs or iterCompilers:
1058 # Translate ' ' to '-' for pathname component.
Zachary Turnere73a0602015-11-06 21:37:33 +00001059 if six.PY2:
Chaoren Linc0a55532015-11-06 22:30:30 +00001060 import string
Zachary Turnere73a0602015-11-06 21:37:33 +00001061 tbl = string.maketrans(' ', '-')
1062 else:
1063 tbl = str.maketrans(' ', '-')
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001064 configPostfix = configString.translate(tbl)
1065
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001066 # Output the configuration.
Zachary Turner606e3a52015-12-08 01:15:30 +00001067 if not configuration.parsable:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001068 sys.stderr.write("\nConfiguration: " + configString + "\n")
1069
1070 #print("sys.stderr name is", sys.stderr.name)
1071 #print("sys.stdout name is", sys.stdout.name)
1072
1073 # First, write out the number of collected test cases.
Zachary Turner606e3a52015-12-08 01:15:30 +00001074 if not configuration.parsable:
Pavel Labathbddf1802015-12-08 12:09:56 +00001075 sys.stderr.write(configuration.separator + "\n")
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001076 sys.stderr.write("Collected %d test%s\n\n"
Zachary Turner606e3a52015-12-08 01:15:30 +00001077 % (configuration.suite.countTestCases(),
1078 configuration.suite.countTestCases() != 1 and "s" or ""))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001079
Zachary Turner606e3a52015-12-08 01:15:30 +00001080 if configuration.parsable:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001081 v = 0
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001082 else:
Zachary Turner606e3a52015-12-08 01:15:30 +00001083 v = configuration.verbose
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001084
1085 # Invoke the test runner.
Zachary Turner606e3a52015-12-08 01:15:30 +00001086 if configuration.count == 1:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001087 result = unittest2.TextTestRunner(stream=sys.stderr,
1088 verbosity=v,
Zachary Turnerb4733e62015-12-08 01:15:44 +00001089 resultclass=test_result.LLDBTestResult).run(configuration.suite)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001090 else:
1091 # We are invoking the same test suite more than once. In this case,
1092 # mark __ignore_singleton__ flag as True so the signleton pattern is
1093 # not enforced.
Zachary Turnerb4733e62015-12-08 01:15:44 +00001094 test_result.LLDBTestResult.__ignore_singleton__ = True
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001095 for i in range(count):
1096
1097 result = unittest2.TextTestRunner(stream=sys.stderr,
1098 verbosity=v,
Zachary Turnerb4733e62015-12-08 01:15:44 +00001099 resultclass=test_result.LLDBTestResult).run(configuration.suite)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001100
Zachary Turner606e3a52015-12-08 01:15:30 +00001101 configuration.failed = configuration.failed or not result.wasSuccessful()
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001102
Zachary Turner606e3a52015-12-08 01:15:30 +00001103 if configuration.sdir_has_content and not configuration.parsable:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001104 sys.stderr.write("Session logs for test failures/errors/unexpected successes"
Zachary Turner606e3a52015-12-08 01:15:30 +00001105 " can be found in directory '%s'\n" % configuration.sdir_name)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001106
Zachary Turner606e3a52015-12-08 01:15:30 +00001107 if configuration.useCategories and len(configuration.failuresPerCategory) > 0:
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001108 sys.stderr.write("Failures per category:\n")
Zachary Turner606e3a52015-12-08 01:15:30 +00001109 for category in configuration.failuresPerCategory:
1110 sys.stderr.write("%s - %d\n" % (category, configuration.failuresPerCategory[category]))
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001111
1112 os.chdir(where_to_save_session)
Zachary Turner606e3a52015-12-08 01:15:30 +00001113 fname = os.path.join(configuration.sdir_name, "TestFinished-%d" % os.getpid())
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001114 with open(fname, "w") as f:
1115 print("Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S"), file=f)
1116
1117 # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined.
1118 # This should not be necessary now.
1119 if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ):
1120 print("Terminating Test suite...")
1121 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())])
1122
1123 # Exiting.
Zachary Turner606e3a52015-12-08 01:15:30 +00001124 exitTestSuite(configuration.failed)
Zachary Turnerc432c8f2015-10-28 17:43:26 +00001125
1126if __name__ == "__main__":
Zachary Turner7d564542015-11-02 19:19:49 +00001127 print(__file__ + " is for use as a module only. It should not be run as a standalone script.")
1128 sys.exit(-1)