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