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