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