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