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