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