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