1""" 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 21from __future__ import absolute_import 22from __future__ import print_function 23 24# System modules 25import atexit 26import os 27import errno 28import logging 29import platform 30import re 31import signal 32import socket 33import subprocess 34import sys 35 36# Third-party modules 37import six 38import unittest2 39 40# LLDB Modules 41import lldbsuite 42from . import configuration 43from . import dotest_args 44from . import lldbtest_config 45from . import test_categories 46from lldbsuite.test_event import formatter 47from . import test_result 48from lldbsuite.test_event.event_builder import EventBuilder 49from ..support import seven 50 51 52def is_exe(fpath): 53 """Returns true if fpath is an executable.""" 54 if fpath == None: 55 return False 56 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 57 58 59def which(program): 60 """Returns the full path to a program; None otherwise.""" 61 fpath, fname = os.path.split(program) 62 if fpath: 63 if is_exe(program): 64 return program 65 else: 66 for path in os.environ["PATH"].split(os.pathsep): 67 exe_file = os.path.join(path, program) 68 if is_exe(exe_file): 69 return exe_file 70 return None 71 72 73class _WritelnDecorator(object): 74 """Used to decorate file-like objects with a handy 'writeln' method""" 75 76 def __init__(self, stream): 77 self.stream = stream 78 79 def __getattr__(self, attr): 80 if attr in ('stream', '__getstate__'): 81 raise AttributeError(attr) 82 return getattr(self.stream, attr) 83 84 def writeln(self, arg=None): 85 if arg: 86 self.write(arg) 87 self.write('\n') # text-mode streams translate to \r\n if needed 88 89# 90# Global variables: 91# 92 93 94def usage(parser): 95 parser.print_help() 96 if configuration.verbose > 0: 97 print(""" 98Examples: 99 100This is an example of using the -f option to pinpoint to a specific test class 101and test method to be run: 102 103$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command 104---------------------------------------------------------------------- 105Collected 1 test 106 107test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase) 108Test 'frame variable this' when stopped on a class constructor. ... ok 109 110---------------------------------------------------------------------- 111Ran 1 test in 1.396s 112 113OK 114 115And this is an example of using the -p option to run a single file (the filename 116matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'): 117 118$ ./dotest.py -v -p ObjC 119---------------------------------------------------------------------- 120Collected 4 tests 121 122test_break_with_dsym (TestObjCMethods.FoundationTestCase) 123Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok 124test_break_with_dwarf (TestObjCMethods.FoundationTestCase) 125Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok 126test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase) 127Lookup objective-c data types and evaluate expressions. ... ok 128test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase) 129Lookup objective-c data types and evaluate expressions. ... ok 130 131---------------------------------------------------------------------- 132Ran 4 tests in 16.661s 133 134OK 135 136Running of this script also sets up the LLDB_TEST environment variable so that 137individual test cases can locate their supporting files correctly. The script 138tries to set up Python's search paths for modules by looking at the build tree 139relative to this script. See also the '-i' option in the following example. 140 141Finally, this is an example of using the lldb.py module distributed/installed by 142Xcode4 to run against the tests under the 'forward' directory, and with the '-w' 143option to add some delay between two tests. It uses ARCH=x86_64 to specify that 144as the architecture and CC=clang to specify the compiler used for the test run: 145 146$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward 147 148Session logs for test failures/errors will go into directory '2010-11-11-13_56_16' 149---------------------------------------------------------------------- 150Collected 2 tests 151 152test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase) 153Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok 154test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase) 155Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok 156 157---------------------------------------------------------------------- 158Ran 2 tests in 5.659s 159 160OK 161 162The 'Session ...' verbiage is recently introduced (see also the '-s' option) to 163notify the directory containing the session logs for test failures or errors. 164In case there is any test failure/error, a similar message is appended at the 165end of the stderr output for your convenience. 166 167ENABLING LOGS FROM TESTS 168 169Option 1: 170 171Writing logs into different files per test case:: 172 173This option is particularly useful when multiple dotest instances are created 174by dosep.py 175 176$ ./dotest.py --channel "lldb all" 177 178$ ./dotest.py --channel "lldb all" --channel "gdb-remote packets" 179 180These log files are written to: 181 182<session-dir>/<test-id>-host.log (logs from lldb host process) 183<session-dir>/<test-id>-server.log (logs from debugserver/lldb-server) 184<session-dir>/<test-id>-<test-result>.log (console logs) 185 186By default, logs from successful runs are deleted. Use the --log-success flag 187to create reference logs for debugging. 188 189$ ./dotest.py --log-success 190 191Option 2: (DEPRECATED) 192 193The following options can only enable logs from the host lldb process. 194Only categories from the "lldb" or "gdb-remote" channels can be enabled 195They also do not automatically enable logs in locally running debug servers. 196Also, logs from all test case are written into each log file 197 198o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem 199 with a default option of 'event process' if LLDB_LOG_OPTION is not defined. 200 201o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the 202 'process.gdb-remote' subsystem with a default option of 'packets' if 203 GDB_REMOTE_LOG_OPTION is not defined. 204 205""") 206 sys.exit(0) 207 208 209def parseExclusion(exclusion_file): 210 """Parse an exclusion file, of the following format, where 211 'skip files', 'skip methods', 'xfail files', and 'xfail methods' 212 are the possible list heading values: 213 214 skip files 215 <file name> 216 <file name> 217 218 xfail methods 219 <method name> 220 """ 221 excl_type = None 222 223 with open(exclusion_file) as f: 224 for line in f: 225 line = line.strip() 226 if not excl_type: 227 excl_type = line 228 continue 229 230 if not line: 231 excl_type = None 232 elif excl_type == 'skip': 233 if not configuration.skip_tests: 234 configuration.skip_tests = [] 235 configuration.skip_tests.append(line) 236 elif excl_type == 'xfail': 237 if not configuration.xfail_tests: 238 configuration.xfail_tests = [] 239 configuration.xfail_tests.append(line) 240 241 242def parseOptionsAndInitTestdirs(): 243 """Initialize the list of directories containing our unittest scripts. 244 245 '-h/--help as the first option prints out usage info and exit the program. 246 """ 247 248 do_help = False 249 250 platform_system = platform.system() 251 platform_machine = platform.machine() 252 253 parser = dotest_args.create_parser() 254 args = dotest_args.parse_args(parser, sys.argv[1:]) 255 256 if args.unset_env_varnames: 257 for env_var in args.unset_env_varnames: 258 if env_var in os.environ: 259 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ 260 # is automatically translated into a corresponding call to 261 # unsetenv(). 262 del os.environ[env_var] 263 # os.unsetenv(env_var) 264 265 if args.set_env_vars: 266 for env_var in args.set_env_vars: 267 parts = env_var.split('=', 1) 268 if len(parts) == 1: 269 os.environ[parts[0]] = "" 270 else: 271 os.environ[parts[0]] = parts[1] 272 273 # only print the args if being verbose (and parsable is off) 274 if args.v and not args.q: 275 print(sys.argv) 276 277 if args.h: 278 do_help = True 279 280 if args.compiler: 281 configuration.compiler = os.path.realpath(args.compiler) 282 if not is_exe(configuration.compiler): 283 configuration.compiler = which(args.compiler) 284 if not is_exe(configuration.compiler): 285 logging.error( 286 '%s is not a valid compiler executable; aborting...', 287 args.compiler) 288 sys.exit(-1) 289 else: 290 # Use a compiler appropriate appropriate for the Apple SDK if one was 291 # specified 292 if platform_system == 'Darwin' and args.apple_sdk: 293 configuration.compiler = seven.get_command_output( 294 'xcrun -sdk "%s" -find clang 2> /dev/null' % 295 (args.apple_sdk)) 296 else: 297 # 'clang' on ubuntu 14.04 is 3.4 so we try clang-3.5 first 298 candidateCompilers = ['clang-3.5', 'clang', 'gcc'] 299 for candidate in candidateCompilers: 300 if which(candidate): 301 configuration.compiler = candidate 302 break 303 304 if args.channels: 305 lldbtest_config.channels = args.channels 306 307 if args.log_success: 308 lldbtest_config.log_success = args.log_success 309 310 # Set SDKROOT if we are using an Apple SDK 311 if platform_system == 'Darwin' and args.apple_sdk: 312 os.environ['SDKROOT'] = seven.get_command_output( 313 'xcrun --sdk "%s" --show-sdk-path 2> /dev/null' % 314 (args.apple_sdk)) 315 316 if args.arch: 317 configuration.arch = args.arch 318 if configuration.arch.startswith( 319 'arm') and platform_system == 'Darwin' and not args.apple_sdk: 320 os.environ['SDKROOT'] = seven.get_command_output( 321 'xcrun --sdk iphoneos.internal --show-sdk-path 2> /dev/null') 322 if not os.path.exists(os.environ['SDKROOT']): 323 os.environ['SDKROOT'] = seven.get_command_output( 324 'xcrun --sdk iphoneos --show-sdk-path 2> /dev/null') 325 else: 326 configuration.arch = platform_machine 327 328 if args.categoriesList: 329 configuration.categoriesList = set( 330 test_categories.validate( 331 args.categoriesList, False)) 332 configuration.useCategories = True 333 else: 334 configuration.categoriesList = [] 335 336 if args.skipCategories: 337 configuration.skipCategories = test_categories.validate( 338 args.skipCategories, False) 339 340 if args.E: 341 cflags_extras = args.E 342 os.environ['CFLAGS_EXTRAS'] = cflags_extras 343 344 if args.d: 345 sys.stdout.write( 346 "Suspending the process %d to wait for debugger to attach...\n" % 347 os.getpid()) 348 sys.stdout.flush() 349 os.kill(os.getpid(), signal.SIGSTOP) 350 351 if args.f: 352 if any([x.startswith('-') for x in args.f]): 353 usage(parser) 354 configuration.filters.extend(args.f) 355 # Shut off multiprocessing mode when additional filters are specified. 356 # The rational is that the user is probably going after a very specific 357 # test and doesn't need a bunch of parallel test runners all looking for 358 # it in a frenzy. Also, '-v' now spits out all test run output even 359 # on success, so the standard recipe for redoing a failing test (with -v 360 # and a -f to filter to the specific test) now causes all test scanning 361 # (in parallel) to print results for do-nothing runs in a very distracting 362 # manner. If we really need filtered parallel runs in the future, consider 363 # adding a --no-output-on-success that prevents -v from setting 364 # output-on-success. 365 configuration.no_multiprocess_test_runner = True 366 367 if args.l: 368 configuration.skip_long_running_test = False 369 370 if args.framework: 371 configuration.lldbFrameworkPath = args.framework 372 373 if args.executable: 374 # lldb executable is passed explicitly 375 lldbtest_config.lldbExec = os.path.realpath(args.executable) 376 if not is_exe(lldbtest_config.lldbExec): 377 lldbtest_config.lldbExec = which(args.executable) 378 if not is_exe(lldbtest_config.lldbExec): 379 logging.error( 380 '%s is not a valid executable to test; aborting...', 381 args.executable) 382 sys.exit(-1) 383 384 if args.server: 385 os.environ['LLDB_DEBUGSERVER_PATH'] = args.server 386 387 if args.excluded: 388 for excl_file in args.excluded: 389 parseExclusion(excl_file) 390 391 if args.p: 392 if args.p.startswith('-'): 393 usage(parser) 394 configuration.regexp = args.p 395 396 if args.q: 397 configuration.parsable = True 398 399 if args.s: 400 if args.s.startswith('-'): 401 usage(parser) 402 configuration.sdir_name = args.s 403 configuration.session_file_format = args.session_file_format 404 405 if args.t: 406 os.environ['LLDB_COMMAND_TRACE'] = 'YES' 407 408 if args.v: 409 configuration.verbose = 2 410 411 # argparse makes sure we have a number 412 if args.sharp: 413 configuration.count = args.sharp 414 415 if sys.platform.startswith('win32'): 416 os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str( 417 args.disable_crash_dialog) 418 os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(True) 419 420 if do_help: 421 usage(parser) 422 423 if args.no_multiprocess: 424 configuration.no_multiprocess_test_runner = True 425 426 if args.inferior: 427 configuration.is_inferior_test_runner = True 428 429 if args.num_threads: 430 configuration.num_threads = args.num_threads 431 432 if args.test_subdir: 433 configuration.multiprocess_test_subdir = args.test_subdir 434 435 if args.test_runner_name: 436 configuration.test_runner_name = args.test_runner_name 437 438 # Capture test results-related args. 439 if args.curses and not args.inferior: 440 # Act as if the following args were set. 441 args.results_formatter = "lldbsuite.test_event.formatter.curses.Curses" 442 args.results_file = "stdout" 443 444 if args.results_file: 445 configuration.results_filename = args.results_file 446 447 if args.results_port: 448 configuration.results_port = args.results_port 449 450 if args.results_file and args.results_port: 451 sys.stderr.write( 452 "only one of --results-file and --results-port should " 453 "be specified\n") 454 usage(args) 455 456 if args.results_formatter: 457 configuration.results_formatter_name = args.results_formatter 458 if args.results_formatter_options: 459 configuration.results_formatter_options = args.results_formatter_options 460 461 # Default to using the BasicResultsFormatter if no formatter is specified 462 # and we're not a test inferior. 463 if not args.inferior and configuration.results_formatter_name is None: 464 configuration.results_formatter_name = ( 465 "lldbsuite.test_event.formatter.results_formatter.ResultsFormatter") 466 467 # rerun-related arguments 468 configuration.rerun_all_issues = args.rerun_all_issues 469 configuration.rerun_max_file_threshold = args.rerun_max_file_threshold 470 471 if args.lldb_platform_name: 472 configuration.lldb_platform_name = args.lldb_platform_name 473 if args.lldb_platform_url: 474 configuration.lldb_platform_url = args.lldb_platform_url 475 if args.lldb_platform_working_dir: 476 configuration.lldb_platform_working_dir = args.lldb_platform_working_dir 477 if args.test_build_dir: 478 configuration.test_build_dir = args.test_build_dir 479 480 if args.event_add_entries and len(args.event_add_entries) > 0: 481 entries = {} 482 # Parse out key=val pairs, separated by comma 483 for keyval in args.event_add_entries.split(","): 484 key_val_entry = keyval.split("=") 485 if len(key_val_entry) == 2: 486 (key, val) = key_val_entry 487 val_parts = val.split(':') 488 if len(val_parts) > 1: 489 (val, val_type) = val_parts 490 if val_type == 'int': 491 val = int(val) 492 entries[key] = val 493 # Tell the event builder to create all events with these 494 # key/val pairs in them. 495 if len(entries) > 0: 496 EventBuilder.add_entries_to_all_events(entries) 497 498 # Gather all the dirs passed on the command line. 499 if len(args.args) > 0: 500 configuration.testdirs = list( 501 map(lambda x: os.path.realpath(os.path.abspath(x)), args.args)) 502 # Shut off multiprocessing mode when test directories are specified. 503 configuration.no_multiprocess_test_runner = True 504 505 lldbtest_config.codesign_identity = args.codesign_identity 506 507 #print("testdirs:", testdirs) 508 509 510def getXcodeOutputPaths(lldbRootDirectory): 511 result = [] 512 513 # These are for xcode build directories. 514 xcode3_build_dir = ['build'] 515 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products'] 516 517 configurations = [ 518 ['Debug'], 519 ['DebugClang'], 520 ['Release'], 521 ['BuildAndIntegration']] 522 xcode_build_dirs = [xcode3_build_dir, xcode4_build_dir] 523 for configuration in configurations: 524 for xcode_build_dir in xcode_build_dirs: 525 outputPath = os.path.join( 526 lldbRootDirectory, *(xcode_build_dir + configuration)) 527 result.append(outputPath) 528 529 return result 530 531 532def createSocketToLocalPort(port): 533 def socket_closer(s): 534 """Close down an opened socket properly.""" 535 s.shutdown(socket.SHUT_RDWR) 536 s.close() 537 538 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 539 sock.connect(("localhost", port)) 540 return (sock, lambda: socket_closer(sock)) 541 542 543def setupTestResults(): 544 """Sets up test results-related objects based on arg settings.""" 545 # Setup the results formatter configuration. 546 formatter_config = formatter.FormatterConfig() 547 formatter_config.filename = configuration.results_filename 548 formatter_config.formatter_name = configuration.results_formatter_name 549 formatter_config.formatter_options = ( 550 configuration.results_formatter_options) 551 formatter_config.port = configuration.results_port 552 553 # Create the results formatter. 554 formatter_spec = formatter.create_results_formatter( 555 formatter_config) 556 if formatter_spec is not None and formatter_spec.formatter is not None: 557 configuration.results_formatter_object = formatter_spec.formatter 558 559 # Send an initialize message to the formatter. 560 initialize_event = EventBuilder.bare_event("initialize") 561 if isMultiprocessTestRunner(): 562 if (configuration.test_runner_name is not None and 563 configuration.test_runner_name == "serial"): 564 # Only one worker queue here. 565 worker_count = 1 566 else: 567 # Workers will be the number of threads specified. 568 worker_count = configuration.num_threads 569 else: 570 worker_count = 1 571 initialize_event["worker_count"] = worker_count 572 573 formatter_spec.formatter.handle_event(initialize_event) 574 575 # Make sure we clean up the formatter on shutdown. 576 if formatter_spec.cleanup_func is not None: 577 atexit.register(formatter_spec.cleanup_func) 578 579 580def getOutputPaths(lldbRootDirectory): 581 """ 582 Returns typical build output paths for the lldb executable 583 584 lldbDirectory - path to the root of the lldb svn/git repo 585 """ 586 result = [] 587 588 if sys.platform == 'darwin': 589 result.extend(getXcodeOutputPaths(lldbRootDirectory)) 590 591 # cmake builds? look for build or build/host folder next to llvm directory 592 # lldb is located in llvm/tools/lldb so we need to go up three levels 593 llvmParentDir = os.path.abspath( 594 os.path.join( 595 lldbRootDirectory, 596 os.pardir, 597 os.pardir, 598 os.pardir)) 599 result.append(os.path.join(llvmParentDir, 'build', 'bin')) 600 result.append(os.path.join(llvmParentDir, 'build', 'host', 'bin')) 601 602 # some cmake developers keep their build directory beside their lldb 603 # directory 604 lldbParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir)) 605 result.append(os.path.join(lldbParentDir, 'build', 'bin')) 606 result.append(os.path.join(lldbParentDir, 'build', 'host', 'bin')) 607 608 return result 609 610 611def setupSysPath(): 612 """ 613 Add LLDB.framework/Resources/Python to the search paths for modules. 614 As a side effect, we also discover the 'lldb' executable and export it here. 615 """ 616 617 # Get the directory containing the current script. 618 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ: 619 scriptPath = os.environ["DOTEST_SCRIPT_DIR"] 620 else: 621 scriptPath = os.path.dirname(os.path.realpath(__file__)) 622 if not scriptPath.endswith('test'): 623 print("This script expects to reside in lldb's test directory.") 624 sys.exit(-1) 625 626 os.environ["LLDB_TEST"] = scriptPath 627 628 # Set up the root build directory. 629 builddir = configuration.test_build_dir 630 if not configuration.test_build_dir: 631 raise Exception("test_build_dir is not set") 632 os.environ["LLDB_BUILD"] = os.path.abspath(configuration.test_build_dir) 633 634 # Set up the LLDB_SRC environment variable, so that the tests can locate 635 # the LLDB source code. 636 os.environ["LLDB_SRC"] = lldbsuite.lldb_root 637 638 pluginPath = os.path.join(scriptPath, 'plugins') 639 toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi') 640 toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server') 641 642 # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the 643 # sys.path. 644 sys.path.insert(0, pluginPath) 645 # Adding test/tools/lldb-mi to the path makes it easy 646 sys.path.insert(0, toolsLLDBMIPath) 647 # to "import lldbmi_testcase" from the MI tests 648 # Adding test/tools/lldb-server to the path makes it easy 649 sys.path.insert(0, toolsLLDBServerPath) 650 # to "import lldbgdbserverutils" from the lldb-server tests 651 652 # This is the root of the lldb git/svn checkout 653 # When this changes over to a package instead of a standalone script, this 654 # will be `lldbsuite.lldb_root` 655 lldbRootDirectory = lldbsuite.lldb_root 656 657 # Some of the tests can invoke the 'lldb' command directly. 658 # We'll try to locate the appropriate executable right here. 659 660 # The lldb executable can be set from the command line 661 # if it's not set, we try to find it now 662 # first, we try the environment 663 if not lldbtest_config.lldbExec: 664 # First, you can define an environment variable LLDB_EXEC specifying the 665 # full pathname of the lldb executable. 666 if "LLDB_EXEC" in os.environ: 667 lldbtest_config.lldbExec = os.environ["LLDB_EXEC"] 668 669 if not lldbtest_config.lldbExec: 670 outputPaths = getOutputPaths(lldbRootDirectory) 671 for outputPath in outputPaths: 672 candidatePath = os.path.join(outputPath, 'lldb') 673 if is_exe(candidatePath): 674 lldbtest_config.lldbExec = candidatePath 675 break 676 677 if not lldbtest_config.lldbExec: 678 # Last, check the path 679 lldbtest_config.lldbExec = which('lldb') 680 681 if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec): 682 print( 683 "'{}' is not a path to a valid executable".format( 684 lldbtest_config.lldbExec)) 685 lldbtest_config.lldbExec = None 686 687 if not lldbtest_config.lldbExec: 688 print("The 'lldb' executable cannot be located. Some of the tests may not be run as a result.") 689 sys.exit(-1) 690 691 # confusingly, this is the "bin" directory 692 lldbLibDir = os.path.dirname(lldbtest_config.lldbExec) 693 os.environ["LLDB_LIB_DIR"] = lldbLibDir 694 lldbImpLibDir = os.path.join( 695 lldbLibDir, 696 '..', 697 'lib') if sys.platform.startswith('win32') else lldbLibDir 698 os.environ["LLDB_IMPLIB_DIR"] = lldbImpLibDir 699 print("LLDB library dir:", os.environ["LLDB_LIB_DIR"]) 700 print("LLDB import library dir:", os.environ["LLDB_IMPLIB_DIR"]) 701 os.system('%s -v' % lldbtest_config.lldbExec) 702 703 # Assume lldb-mi is in same place as lldb 704 # If not found, disable the lldb-mi tests 705 # TODO: Append .exe on Windows 706 # - this will be in a separate commit in case the mi tests fail horribly 707 lldbDir = os.path.dirname(lldbtest_config.lldbExec) 708 lldbMiExec = os.path.join(lldbDir, "lldb-mi") 709 if is_exe(lldbMiExec): 710 os.environ["LLDBMI_EXEC"] = lldbMiExec 711 else: 712 if not configuration.shouldSkipBecauseOfCategories(["lldb-mi"]): 713 print( 714 "The 'lldb-mi' executable cannot be located. The lldb-mi tests can not be run as a result.") 715 configuration.skipCategories.append("lldb-mi") 716 717 lldbPythonDir = None # The directory that contains 'lldb/__init__.py' 718 if not configuration.lldbFrameworkPath and os.path.exists(os.path.join(lldbLibDir, "LLDB.framework")): 719 configuration.lldbFrameworkPath = os.path.join(lldbLibDir, "LLDB.framework") 720 if configuration.lldbFrameworkPath: 721 lldbtest_config.lldbFrameworkPath = configuration.lldbFrameworkPath 722 candidatePath = os.path.join( 723 configuration.lldbFrameworkPath, 'Resources', 'Python') 724 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')): 725 lldbPythonDir = candidatePath 726 if not lldbPythonDir: 727 print( 728 'Resources/Python/lldb/__init__.py was not found in ' + 729 configuration.lldbFrameworkPath) 730 sys.exit(-1) 731 else: 732 # If our lldb supports the -P option, use it to find the python path: 733 init_in_python_dir = os.path.join('lldb', '__init__.py') 734 735 lldb_dash_p_result = subprocess.check_output( 736 [lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True) 737 738 if lldb_dash_p_result and not lldb_dash_p_result.startswith( 739 ("<", "lldb: invalid option:")) and not lldb_dash_p_result.startswith("Traceback"): 740 lines = lldb_dash_p_result.splitlines() 741 742 # Workaround for readline vs libedit issue on FreeBSD. If stdout 743 # is not a terminal Python executes 744 # rl_variable_bind ("enable-meta-key", "off"); 745 # This produces a warning with FreeBSD's libedit because the 746 # enable-meta-key variable is unknown. Not an issue on Apple 747 # because cpython commit f0ab6f9f0603 added a #ifndef __APPLE__ 748 # around the call. See http://bugs.python.org/issue19884 for more 749 # information. For now we just discard the warning output. 750 if len(lines) >= 1 and lines[0].startswith( 751 "bind: Invalid command"): 752 lines.pop(0) 753 754 # Taking the last line because lldb outputs 755 # 'Cannot read termcap database;\nusing dumb terminal settings.\n' 756 # before the path 757 if len(lines) >= 1 and os.path.isfile( 758 os.path.join(lines[-1], init_in_python_dir)): 759 lldbPythonDir = lines[-1] 760 if "freebsd" in sys.platform or "linux" in sys.platform: 761 os.environ['LLDB_LIB_DIR'] = os.path.join( 762 lldbPythonDir, '..', '..') 763 764 if not lldbPythonDir: 765 if platform.system() == "Darwin": 766 python_resource_dir = ['LLDB.framework', 'Resources', 'Python'] 767 outputPaths = getXcodeOutputPaths(lldbRootDirectory) 768 for outputPath in outputPaths: 769 candidatePath = os.path.join( 770 outputPath, *python_resource_dir) 771 if os.path.isfile( 772 os.path.join( 773 candidatePath, 774 init_in_python_dir)): 775 lldbPythonDir = candidatePath 776 break 777 778 if not lldbPythonDir: 779 print("lldb.py is not found, some tests may fail.") 780 else: 781 print( 782 "Unable to load lldb extension module. Possible reasons for this include:") 783 print(" 1) LLDB was built with LLDB_DISABLE_PYTHON=1") 784 print( 785 " 2) PYTHONPATH and PYTHONHOME are not set correctly. PYTHONHOME should refer to") 786 print( 787 " the version of Python that LLDB built and linked against, and PYTHONPATH") 788 print( 789 " should contain the Lib directory for the same python distro, as well as the") 790 print(" location of LLDB\'s site-packages folder.") 791 print( 792 " 3) A different version of Python than that which was built against is exported in") 793 print(" the system\'s PATH environment variable, causing conflicts.") 794 print( 795 " 4) The executable '%s' could not be found. Please check " % 796 lldbtest_config.lldbExec) 797 print(" that it exists and is executable.") 798 799 if lldbPythonDir: 800 lldbPythonDir = os.path.normpath(lldbPythonDir) 801 # Some of the code that uses this path assumes it hasn't resolved the Versions... link. 802 # If the path we've constructed looks like that, then we'll strip out 803 # the Versions/A part. 804 (before, frameWithVersion, after) = lldbPythonDir.rpartition( 805 "LLDB.framework/Versions/A") 806 if frameWithVersion != "": 807 lldbPythonDir = before + "LLDB.framework" + after 808 809 lldbPythonDir = os.path.abspath(lldbPythonDir) 810 811 # If tests need to find LLDB_FRAMEWORK, now they can do it 812 os.environ["LLDB_FRAMEWORK"] = os.path.dirname( 813 os.path.dirname(lldbPythonDir)) 814 815 # This is to locate the lldb.py module. Insert it right after 816 # sys.path[0]. 817 sys.path[1:1] = [lldbPythonDir] 818 819 820def visit_file(dir, name): 821 # Try to match the regexp pattern, if specified. 822 if configuration.regexp: 823 if not re.search(configuration.regexp, name): 824 # We didn't match the regex, we're done. 825 return 826 827 if configuration.skip_tests: 828 for file_regexp in configuration.skip_tests: 829 if re.search(file_regexp, name): 830 return 831 832 # We found a match for our test. Add it to the suite. 833 834 # Update the sys.path first. 835 if not sys.path.count(dir): 836 sys.path.insert(0, dir) 837 base = os.path.splitext(name)[0] 838 839 # Thoroughly check the filterspec against the base module and admit 840 # the (base, filterspec) combination only when it makes sense. 841 filterspec = None 842 for filterspec in configuration.filters: 843 # Optimistically set the flag to True. 844 filtered = True 845 module = __import__(base) 846 parts = filterspec.split('.') 847 obj = module 848 for part in parts: 849 try: 850 parent, obj = obj, getattr(obj, part) 851 except AttributeError: 852 # The filterspec has failed. 853 filtered = False 854 break 855 856 # If filtered, we have a good filterspec. Add it. 857 if filtered: 858 # print("adding filter spec %s to module %s" % (filterspec, module)) 859 configuration.suite.addTests( 860 unittest2.defaultTestLoader.loadTestsFromName( 861 filterspec, module)) 862 continue 863 864 # Forgo this module if the (base, filterspec) combo is invalid 865 if configuration.filters and not filtered: 866 return 867 868 if not filterspec or not filtered: 869 # Add the entire file's worth of tests since we're not filtered. 870 # Also the fail-over case when the filterspec branch 871 # (base, filterspec) combo doesn't make sense. 872 configuration.suite.addTests( 873 unittest2.defaultTestLoader.loadTestsFromName(base)) 874 875 876def visit(prefix, dir, names): 877 """Visitor function for os.path.walk(path, visit, arg).""" 878 879 dir_components = set(dir.split(os.sep)) 880 excluded_components = set(['.svn', '.git']) 881 if dir_components.intersection(excluded_components): 882 return 883 884 # Gather all the Python test file names that follow the Test*.py pattern. 885 python_test_files = [ 886 name 887 for name in names 888 if name.endswith('.py') and name.startswith(prefix)] 889 890 # Visit all the python test files. 891 for name in python_test_files: 892 try: 893 # Ensure we error out if we have multiple tests with the same 894 # base name. 895 # Future improvement: find all the places where we work with base 896 # names and convert to full paths. We have directory structure 897 # to disambiguate these, so we shouldn't need this constraint. 898 if name in configuration.all_tests: 899 raise Exception("Found multiple tests with the name %s" % name) 900 configuration.all_tests.add(name) 901 902 # Run the relevant tests in the python file. 903 visit_file(dir, name) 904 except Exception as ex: 905 # Convert this exception to a test event error for the file. 906 test_filename = os.path.abspath(os.path.join(dir, name)) 907 if configuration.results_formatter_object is not None: 908 # Grab the backtrace for the exception. 909 import traceback 910 backtrace = traceback.format_exc() 911 912 # Generate the test event. 913 configuration.results_formatter_object.handle_event( 914 EventBuilder.event_for_job_test_add_error( 915 test_filename, ex, backtrace)) 916 raise 917 918 919def disabledynamics(): 920 import lldb 921 ci = lldb.DBG.GetCommandInterpreter() 922 res = lldb.SBCommandReturnObject() 923 ci.HandleCommand( 924 "setting set target.prefer-dynamic-value no-dynamic-values", 925 res, 926 False) 927 if not res.Succeeded(): 928 raise Exception('disabling dynamic type support failed') 929 930 931def lldbLoggings(): 932 import lldb 933 """Check and do lldb loggings if necessary.""" 934 935 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is 936 # defined. Use ${LLDB_LOG} to specify the log file. 937 ci = lldb.DBG.GetCommandInterpreter() 938 res = lldb.SBCommandReturnObject() 939 if ("LLDB_LOG" in os.environ): 940 open(os.environ["LLDB_LOG"], 'w').close() 941 if ("LLDB_LOG_OPTION" in os.environ): 942 lldb_log_option = os.environ["LLDB_LOG_OPTION"] 943 else: 944 lldb_log_option = "event process expr state api" 945 ci.HandleCommand( 946 "log enable -n -f " + 947 os.environ["LLDB_LOG"] + 948 " lldb " + 949 lldb_log_option, 950 res) 951 if not res.Succeeded(): 952 raise Exception('log enable failed (check LLDB_LOG env variable)') 953 954 if ("LLDB_LINUX_LOG" in os.environ): 955 open(os.environ["LLDB_LINUX_LOG"], 'w').close() 956 if ("LLDB_LINUX_LOG_OPTION" in os.environ): 957 lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"] 958 else: 959 lldb_log_option = "event process expr state api" 960 ci.HandleCommand( 961 "log enable -n -f " + 962 os.environ["LLDB_LINUX_LOG"] + 963 " linux " + 964 lldb_log_option, 965 res) 966 if not res.Succeeded(): 967 raise Exception( 968 'log enable failed (check LLDB_LINUX_LOG env variable)') 969 970 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined. 971 # Use ${GDB_REMOTE_LOG} to specify the log file. 972 if ("GDB_REMOTE_LOG" in os.environ): 973 if ("GDB_REMOTE_LOG_OPTION" in os.environ): 974 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"] 975 else: 976 gdb_remote_log_option = "packets process" 977 ci.HandleCommand( 978 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote " 979 + gdb_remote_log_option, 980 res) 981 if not res.Succeeded(): 982 raise Exception( 983 'log enable failed (check GDB_REMOTE_LOG env variable)') 984 985 986def getMyCommandLine(): 987 return ' '.join(sys.argv) 988 989# ======================================== # 990# # 991# Execution of the test driver starts here # 992# # 993# ======================================== # 994 995 996def checkDsymForUUIDIsNotOn(): 997 cmd = ["defaults", "read", "com.apple.DebugSymbols"] 998 pipe = subprocess.Popen( 999 cmd, 1000 stdout=subprocess.PIPE, 1001 stderr=subprocess.STDOUT) 1002 cmd_output = pipe.stdout.read() 1003 if cmd_output and "DBGFileMappedPaths = " in cmd_output: 1004 print("%s =>" % ' '.join(cmd)) 1005 print(cmd_output) 1006 print( 1007 "Disable automatic lookup and caching of dSYMs before running the test suite!") 1008 print("Exiting...") 1009 sys.exit(0) 1010 1011 1012def exitTestSuite(exitCode=None): 1013 import lldb 1014 lldb.SBDebugger.Terminate() 1015 if exitCode: 1016 sys.exit(exitCode) 1017 1018 1019def isMultiprocessTestRunner(): 1020 # We're not multiprocess when we're either explicitly 1021 # the inferior (as specified by the multiprocess test 1022 # runner) OR we've been told to skip using the multiprocess 1023 # test runner 1024 return not ( 1025 configuration.is_inferior_test_runner or configuration.no_multiprocess_test_runner) 1026 1027 1028def getVersionForSDK(sdk): 1029 sdk = str.lower(sdk) 1030 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) 1031 basename = os.path.basename(full_path) 1032 basename = os.path.splitext(basename)[0] 1033 basename = str.lower(basename) 1034 ver = basename.replace(sdk, '') 1035 return ver 1036 1037 1038def getPathForSDK(sdk): 1039 sdk = str.lower(sdk) 1040 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) 1041 if os.path.exists(full_path): 1042 return full_path 1043 return None 1044 1045 1046def setDefaultTripleForPlatform(): 1047 if configuration.lldb_platform_name == 'ios-simulator': 1048 triple_str = 'x86_64-apple-ios%s' % ( 1049 getVersionForSDK('iphonesimulator')) 1050 os.environ['TRIPLE'] = triple_str 1051 return {'TRIPLE': triple_str} 1052 return {} 1053 1054 1055def checkCompiler(): 1056 # Add some intervention here to sanity check that the compiler requested is sane. 1057 # If found not to be an executable program, we abort. 1058 c = configuration.compiler 1059 if which(c): 1060 return 1061 1062 if not sys.platform.startswith("darwin"): 1063 raise Exception(c + " is not a valid compiler") 1064 1065 pipe = subprocess.Popen( 1066 ['xcrun', '-find', c], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 1067 cmd_output = pipe.stdout.read() 1068 if not cmd_output or "not found" in cmd_output: 1069 raise Exception(c + " is not a valid compiler") 1070 1071 configuration.compiler = cmd_output.split('\n')[0] 1072 print("'xcrun -find %s' returning %s" % (c, configuration.compiler)) 1073 1074def canRunLibcxxTests(): 1075 from lldbsuite.test import lldbplatformutil 1076 1077 platform = lldbplatformutil.getPlatform() 1078 1079 if lldbplatformutil.target_is_android() or lldbplatformutil.platformIsDarwin(): 1080 return True, "libc++ always present" 1081 1082 if platform == "linux": 1083 if not os.path.isdir("/usr/include/c++/v1"): 1084 return False, "Unable to find libc++ installation" 1085 return True, "Headers found, let's hope they work" 1086 1087 return False, "Don't know how to build with libc++ on %s" % platform 1088 1089def checkLibcxxSupport(): 1090 result, reason = canRunLibcxxTests() 1091 if result: 1092 return # libc++ supported 1093 if "libc++" in configuration.categoriesList: 1094 return # libc++ category explicitly requested, let it run. 1095 print("Libc++ tests will not be run because: " + reason) 1096 configuration.skipCategories.append("libc++") 1097 1098def run_suite(): 1099 # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults 1100 # does not exist before proceeding to running the test suite. 1101 if sys.platform.startswith("darwin"): 1102 checkDsymForUUIDIsNotOn() 1103 1104 # 1105 # Start the actions by first parsing the options while setting up the test 1106 # directories, followed by setting up the search paths for lldb utilities; 1107 # then, we walk the directory trees and collect the tests into our test suite. 1108 # 1109 parseOptionsAndInitTestdirs() 1110 1111 # Setup test results (test results formatter and output handling). 1112 setupTestResults() 1113 1114 # If we are running as the multiprocess test runner, kick off the 1115 # multiprocess test runner here. 1116 if isMultiprocessTestRunner(): 1117 from . import dosep 1118 dosep.main( 1119 configuration.num_threads, 1120 configuration.multiprocess_test_subdir, 1121 configuration.test_runner_name, 1122 configuration.results_formatter_object) 1123 raise Exception("should never get here") 1124 elif configuration.is_inferior_test_runner: 1125 # Shut off Ctrl-C processing in inferiors. The parallel 1126 # test runner handles this more holistically. 1127 signal.signal(signal.SIGINT, signal.SIG_IGN) 1128 1129 setupSysPath() 1130 1131 # 1132 # If '-l' is specified, do not skip the long running tests. 1133 if not configuration.skip_long_running_test: 1134 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO" 1135 1136 # For the time being, let's bracket the test runner within the 1137 # lldb.SBDebugger.Initialize()/Terminate() pair. 1138 import lldb 1139 1140 # Create a singleton SBDebugger in the lldb namespace. 1141 lldb.DBG = lldb.SBDebugger.Create() 1142 1143 if configuration.lldb_platform_name: 1144 print("Setting up remote platform '%s'" % 1145 (configuration.lldb_platform_name)) 1146 lldb.remote_platform = lldb.SBPlatform( 1147 configuration.lldb_platform_name) 1148 if not lldb.remote_platform.IsValid(): 1149 print( 1150 "error: unable to create the LLDB platform named '%s'." % 1151 (configuration.lldb_platform_name)) 1152 exitTestSuite(1) 1153 if configuration.lldb_platform_url: 1154 # We must connect to a remote platform if a LLDB platform URL was 1155 # specified 1156 print( 1157 "Connecting to remote platform '%s' at '%s'..." % 1158 (configuration.lldb_platform_name, configuration.lldb_platform_url)) 1159 platform_connect_options = lldb.SBPlatformConnectOptions( 1160 configuration.lldb_platform_url) 1161 err = lldb.remote_platform.ConnectRemote(platform_connect_options) 1162 if err.Success(): 1163 print("Connected.") 1164 else: 1165 print("error: failed to connect to remote platform using URL '%s': %s" % ( 1166 configuration.lldb_platform_url, err)) 1167 exitTestSuite(1) 1168 else: 1169 configuration.lldb_platform_url = None 1170 1171 platform_changes = setDefaultTripleForPlatform() 1172 first = True 1173 for key in platform_changes: 1174 if first: 1175 print("Environment variables setup for platform support:") 1176 first = False 1177 print("%s = %s" % (key, platform_changes[key])) 1178 1179 if configuration.lldb_platform_working_dir: 1180 print("Setting remote platform working directory to '%s'..." % 1181 (configuration.lldb_platform_working_dir)) 1182 error = lldb.remote_platform.MakeDirectory( 1183 configuration.lldb_platform_working_dir, 448) # 448 = 0o700 1184 if error.Fail(): 1185 raise Exception("making remote directory '%s': %s" % ( 1186 remote_test_dir, error)) 1187 1188 if not lldb.remote_platform.SetWorkingDirectory( 1189 configuration.lldb_platform_working_dir): 1190 raise Exception("failed to set working directory '%s'" % remote_test_dir) 1191 lldb.DBG.SetSelectedPlatform(lldb.remote_platform) 1192 else: 1193 lldb.remote_platform = None 1194 configuration.lldb_platform_working_dir = None 1195 configuration.lldb_platform_url = None 1196 1197 # Set up the working directory. 1198 # Note that it's not dotest's job to clean this directory. 1199 import lldbsuite.test.lldbutil as lldbutil 1200 build_dir = configuration.test_build_dir 1201 lldbutil.mkdir_p(build_dir) 1202 1203 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] 1204 1205 checkLibcxxSupport() 1206 1207 # Don't do debugserver tests on everything except OS X. 1208 configuration.dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform 1209 1210 # Don't do lldb-server (llgs) tests on anything except Linux. 1211 configuration.dont_do_llgs_test = not ("linux" in target_platform) 1212 1213 # 1214 # Walk through the testdirs while collecting tests. 1215 # 1216 for testdir in configuration.testdirs: 1217 for (dirpath, dirnames, filenames) in os.walk(testdir): 1218 visit('Test', dirpath, filenames) 1219 1220 # 1221 # Now that we have loaded all the test cases, run the whole test suite. 1222 # 1223 1224 # Turn on lldb loggings if necessary. 1225 lldbLoggings() 1226 1227 # Disable default dynamic types for testing purposes 1228 disabledynamics() 1229 1230 # Install the control-c handler. 1231 unittest2.signals.installHandler() 1232 1233 # If sdir_name is not specified through the '-s sdir_name' option, get a 1234 # timestamp string and export it as LLDB_SESSION_DIR environment var. This will 1235 # be used when/if we want to dump the session info of individual test cases 1236 # later on. 1237 # 1238 # See also TestBase.dumpSessionInfo() in lldbtest.py. 1239 import datetime 1240 # The windows platforms don't like ':' in the pathname. 1241 timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S") 1242 if not configuration.sdir_name: 1243 configuration.sdir_name = timestamp_started 1244 os.environ["LLDB_SESSION_DIRNAME"] = os.path.join( 1245 os.getcwd(), configuration.sdir_name) 1246 1247 sys.stderr.write( 1248 "\nSession logs for test failures/errors/unexpected successes" 1249 " will go into directory '%s'\n" % 1250 configuration.sdir_name) 1251 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine()) 1252 1253 if not os.path.isdir(configuration.sdir_name): 1254 try: 1255 os.mkdir(configuration.sdir_name) 1256 except OSError as exception: 1257 if exception.errno != errno.EEXIST: 1258 raise 1259 1260 # 1261 # Invoke the default TextTestRunner to run the test suite 1262 # 1263 checkCompiler() 1264 1265 if not configuration.parsable: 1266 print("compiler=%s" % configuration.compiler) 1267 1268 # Iterating over all possible architecture and compiler combinations. 1269 os.environ["ARCH"] = configuration.arch 1270 os.environ["CC"] = configuration.compiler 1271 configString = "arch=%s compiler=%s" % (configuration.arch, 1272 configuration.compiler) 1273 1274 # Translate ' ' to '-' for pathname component. 1275 if six.PY2: 1276 import string 1277 tbl = string.maketrans(' ', '-') 1278 else: 1279 tbl = str.maketrans(' ', '-') 1280 configPostfix = configString.translate(tbl) 1281 1282 # Output the configuration. 1283 if not configuration.parsable: 1284 sys.stderr.write("\nConfiguration: " + configString + "\n") 1285 1286 # First, write out the number of collected test cases. 1287 if not configuration.parsable: 1288 sys.stderr.write(configuration.separator + "\n") 1289 sys.stderr.write( 1290 "Collected %d test%s\n\n" % 1291 (configuration.suite.countTestCases(), 1292 configuration.suite.countTestCases() != 1 and "s" or "")) 1293 1294 if configuration.parsable: 1295 v = 0 1296 else: 1297 v = configuration.verbose 1298 1299 # Invoke the test runner. 1300 if configuration.count == 1: 1301 result = unittest2.TextTestRunner( 1302 stream=sys.stderr, 1303 verbosity=v, 1304 resultclass=test_result.LLDBTestResult).run( 1305 configuration.suite) 1306 else: 1307 # We are invoking the same test suite more than once. In this case, 1308 # mark __ignore_singleton__ flag as True so the signleton pattern is 1309 # not enforced. 1310 test_result.LLDBTestResult.__ignore_singleton__ = True 1311 for i in range(configuration.count): 1312 1313 result = unittest2.TextTestRunner( 1314 stream=sys.stderr, 1315 verbosity=v, 1316 resultclass=test_result.LLDBTestResult).run( 1317 configuration.suite) 1318 1319 configuration.failed = not result.wasSuccessful() 1320 1321 if configuration.sdir_has_content and not configuration.parsable: 1322 sys.stderr.write( 1323 "Session logs for test failures/errors/unexpected successes" 1324 " can be found in directory '%s'\n" % 1325 configuration.sdir_name) 1326 1327 if configuration.useCategories and len( 1328 configuration.failuresPerCategory) > 0: 1329 sys.stderr.write("Failures per category:\n") 1330 for category in configuration.failuresPerCategory: 1331 sys.stderr.write( 1332 "%s - %d\n" % 1333 (category, configuration.failuresPerCategory[category])) 1334 1335 # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined. 1336 # This should not be necessary now. 1337 if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ): 1338 print("Terminating Test suite...") 1339 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())]) 1340 1341 # Exiting. 1342 exitTestSuite(configuration.failed) 1343 1344if __name__ == "__main__": 1345 print( 1346 __file__ + 1347 " is for use as a module only. It should not be run as a standalone script.") 1348 sys.exit(-1) 1349