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 importlib 27import os 28import errno 29import platform 30import progress 31import signal 32import socket 33import subprocess 34import sys 35import inspect 36 37# Third-party modules 38import six 39import unittest2 40 41# LLDB Modules 42import lldbsuite 43from . import dotest_args 44from . import lldbtest_config 45from . import test_categories 46from . import test_results 47from .test_results import EventBuilder 48from ..support import seven 49 50def is_exe(fpath): 51 """Returns true if fpath is an executable.""" 52 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 53 54def which(program): 55 """Returns the full path to a program; None otherwise.""" 56 fpath, fname = os.path.split(program) 57 if fpath: 58 if is_exe(program): 59 return program 60 else: 61 for path in os.environ["PATH"].split(os.pathsep): 62 exe_file = os.path.join(path, program) 63 if is_exe(exe_file): 64 return exe_file 65 return None 66 67class _WritelnDecorator(object): 68 """Used to decorate file-like objects with a handy 'writeln' method""" 69 def __init__(self,stream): 70 self.stream = stream 71 72 def __getattr__(self, attr): 73 if attr in ('stream', '__getstate__'): 74 raise AttributeError(attr) 75 return getattr(self.stream,attr) 76 77 def writeln(self, arg=None): 78 if arg: 79 self.write(arg) 80 self.write('\n') # text-mode streams translate to \r\n if needed 81 82# 83# Global variables: 84# 85 86# The test suite. 87suite = unittest2.TestSuite() 88 89# By default, benchmarks tests are not run. 90just_do_benchmarks_test = False 91 92dont_do_dsym_test = False 93dont_do_dwarf_test = False 94dont_do_dwo_test = False 95 96# The blacklist is optional (-b blacklistFile) and allows a central place to skip 97# testclass's and/or testclass.testmethod's. 98blacklist = None 99 100# The dictionary as a result of sourcing blacklistFile. 101blacklistConfig = {} 102 103# The list of categories we said we care about 104categoriesList = None 105# set to true if we are going to use categories for cherry-picking test cases 106useCategories = False 107# Categories we want to skip 108skipCategories = [] 109# use this to track per-category failures 110failuresPerCategory = {} 111 112# The path to LLDB.framework is optional. 113lldbFrameworkPath = None 114 115# The config file is optional. 116configFile = None 117 118# Test suite repeat count. Can be overwritten with '-# count'. 119count = 1 120 121# The dictionary as a result of sourcing configFile. 122config = {} 123# The pre_flight and post_flight functions come from reading a config file. 124pre_flight = None 125post_flight = None 126# So do the lldbtest_remote_sandbox and lldbtest_remote_shell_template variables. 127lldbtest_remote_sandbox = None 128lldbtest_remote_shell_template = None 129 130# The 'archs' and 'compilers' can be specified via either command line or configFile, 131# with the command line overriding the configFile. The corresponding options can be 132# specified more than once. For example, "-A x86_64 -A i386" => archs=['x86_64', 'i386'] 133# and "-C gcc -C clang" => compilers=['gcc', 'clang']. 134archs = None # Must be initialized after option parsing 135compilers = None # Must be initialized after option parsing 136 137# The arch might dictate some specific CFLAGS to be passed to the toolchain to build 138# the inferior programs. The global variable cflags_extras provides a hook to do 139# just that. 140cflags_extras = '' 141 142# Dump the Python sys.path variable. Use '-D' to dump sys.path. 143dumpSysPath = False 144 145# Full path of the benchmark executable, as specified by the '-e' option. 146bmExecutable = None 147# The breakpoint specification of bmExecutable, as specified by the '-x' option. 148bmBreakpointSpec = None 149# The benchmark iteration count, as specified by the '-y' option. 150bmIterationCount = -1 151 152# By default, don't exclude any directories. Use '-X' to add one excluded directory. 153excluded = set(['.svn', '.git']) 154 155# By default, failfast is False. Use '-F' to overwrite it. 156failfast = False 157 158# The filters (testclass.testmethod) used to admit tests into our test suite. 159filters = [] 160 161# The runhooks is a list of lldb commands specifically for the debugger. 162# Use '-k' to specify a runhook. 163runHooks = [] 164 165# If '-g' is specified, the filterspec is not exclusive. If a test module does 166# not contain testclass.testmethod which matches the filterspec, the whole test 167# module is still admitted into our test suite. fs4all flag defaults to True. 168fs4all = True 169 170# Ignore the build search path relative to this script to locate the lldb.py module. 171ignore = False 172 173# By default, we do not skip build and cleanup. Use '-S' option to override. 174skip_build_and_cleanup = False 175 176# By default, we skip long running test case. Use '-l' option to override. 177skip_long_running_test = True 178 179# By default, we print the build dir, lldb version, and svn info. Use '-n' option to 180# turn it off. 181noHeaders = False 182 183# Parsable mode silences headers, and any other output this script might generate, and instead 184# prints machine-readable output similar to what clang tests produce. 185parsable = False 186 187# The regular expression pattern to match against eligible filenames as our test cases. 188regexp = None 189 190# By default, tests are executed in place and cleanups are performed afterwards. 191# Use '-r dir' option to relocate the tests and their intermediate files to a 192# different directory and to forgo any cleanups. The directory specified must 193# not exist yet. 194rdir = None 195 196# By default, recorded session info for errored/failed test are dumped into its 197# own file under a session directory named after the timestamp of the test suite 198# run. Use '-s session-dir-name' to specify a specific dir name. 199sdir_name = None 200 201# Set this flag if there is any session info dumped during the test run. 202sdir_has_content = False 203 204# svn_info stores the output from 'svn info lldb.base.dir'. 205svn_info = '' 206 207# svn_silent means do not try to obtain svn status 208svn_silent = True 209 210# Default verbosity is 0. 211verbose = 1 212 213# Set to True only if verbose is 0 and LLDB trace mode is off. 214progress_bar = False 215 216# By default, search from the script directory. 217# We can't use sys.path[0] to determine the script directory 218# because it doesn't work under a debugger 219testdirs = [ os.path.dirname(os.path.realpath(__file__)) ] 220 221# Separator string. 222separator = '-' * 70 223 224failed = False 225 226# LLDB Remote platform setting 227lldb_platform_name = None 228lldb_platform_url = None 229lldb_platform_working_dir = None 230 231# Parallel execution settings 232is_inferior_test_runner = False 233multiprocess_test_subdir = None 234num_threads = None 235output_on_success = False 236no_multiprocess_test_runner = False 237test_runner_name = None 238 239# Test results handling globals 240results_filename = None 241results_port = None 242results_file_object = None 243results_formatter_name = None 244results_formatter_object = None 245results_formatter_options = None 246 247# The names of all tests. Used to assert we don't have two tests with the same base name. 248all_tests = set() 249 250def usage(parser): 251 parser.print_help() 252 if verbose > 0: 253 print(""" 254Examples: 255 256This is an example of using the -f option to pinpoint to a specific test class 257and test method to be run: 258 259$ ./dotest.py -f ClassTypesTestCase.test_with_dsym_and_run_command 260---------------------------------------------------------------------- 261Collected 1 test 262 263test_with_dsym_and_run_command (TestClassTypes.ClassTypesTestCase) 264Test 'frame variable this' when stopped on a class constructor. ... ok 265 266---------------------------------------------------------------------- 267Ran 1 test in 1.396s 268 269OK 270 271And this is an example of using the -p option to run a single file (the filename 272matches the pattern 'ObjC' and it happens to be 'TestObjCMethods.py'): 273 274$ ./dotest.py -v -p ObjC 275---------------------------------------------------------------------- 276Collected 4 tests 277 278test_break_with_dsym (TestObjCMethods.FoundationTestCase) 279Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok 280test_break_with_dwarf (TestObjCMethods.FoundationTestCase) 281Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok 282test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase) 283Lookup objective-c data types and evaluate expressions. ... ok 284test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase) 285Lookup objective-c data types and evaluate expressions. ... ok 286 287---------------------------------------------------------------------- 288Ran 4 tests in 16.661s 289 290OK 291 292Running of this script also sets up the LLDB_TEST environment variable so that 293individual test cases can locate their supporting files correctly. The script 294tries to set up Python's search paths for modules by looking at the build tree 295relative to this script. See also the '-i' option in the following example. 296 297Finally, this is an example of using the lldb.py module distributed/installed by 298Xcode4 to run against the tests under the 'forward' directory, and with the '-w' 299option to add some delay between two tests. It uses ARCH=x86_64 to specify that 300as the architecture and CC=clang to specify the compiler used for the test run: 301 302$ PYTHONPATH=/Xcode4/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python ARCH=x86_64 CC=clang ./dotest.py -v -w -i forward 303 304Session logs for test failures/errors will go into directory '2010-11-11-13_56_16' 305---------------------------------------------------------------------- 306Collected 2 tests 307 308test_with_dsym_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase) 309Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok 310test_with_dwarf_and_run_command (TestForwardDeclaration.ForwardDeclarationTestCase) 311Display *bar_ptr when stopped on a function with forward declaration of struct bar. ... ok 312 313---------------------------------------------------------------------- 314Ran 2 tests in 5.659s 315 316OK 317 318The 'Session ...' verbiage is recently introduced (see also the '-s' option) to 319notify the directory containing the session logs for test failures or errors. 320In case there is any test failure/error, a similar message is appended at the 321end of the stderr output for your convenience. 322 323ENABLING LOGS FROM TESTS 324 325Option 1: 326 327Writing logs into different files per test case:: 328 329This option is particularly useful when multiple dotest instances are created 330by dosep.py 331 332$ ./dotest.py --channel "lldb all" 333 334$ ./dotest.py --channel "lldb all" --channel "gdb-remote packets" 335 336These log files are written to: 337 338<session-dir>/<test-id>-host.log (logs from lldb host process) 339<session-dir>/<test-id>-server.log (logs from debugserver/lldb-server) 340<session-dir>/<test-id>-<test-result>.log (console logs) 341 342By default, logs from successful runs are deleted. Use the --log-success flag 343to create reference logs for debugging. 344 345$ ./dotest.py --log-success 346 347Option 2: (DEPRECATED) 348 349The following options can only enable logs from the host lldb process. 350Only categories from the "lldb" or "gdb-remote" channels can be enabled 351They also do not automatically enable logs in locally running debug servers. 352Also, logs from all test case are written into each log file 353 354o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem 355 with a default option of 'event process' if LLDB_LOG_OPTION is not defined. 356 357o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the 358 'process.gdb-remote' subsystem with a default option of 'packets' if 359 GDB_REMOTE_LOG_OPTION is not defined. 360 361""") 362 sys.exit(0) 363 364 365def setCrashInfoHook_Mac(text): 366 from . import crashinfo 367 crashinfo.setCrashReporterDescription(text) 368 369# implement this in some suitable way for your platform, and then bind it 370# to setCrashInfoHook 371def setCrashInfoHook_NonMac(text): 372 pass 373 374setCrashInfoHook = None 375 376def deleteCrashInfoDylib(dylib_path): 377 try: 378 # Need to modify this to handle multiple tests running at the same time. If we move this 379 # to the test's real dir, all should be we run sequentially within a test directory. 380 # os.remove(dylib_path) 381 None 382 finally: 383 pass 384 385def setupCrashInfoHook(): 386 global setCrashInfoHook 387 setCrashInfoHook = setCrashInfoHook_NonMac # safe default 388 if platform.system() == "Darwin": 389 from . import lock 390 test_dir = os.environ['LLDB_TEST'] 391 if not test_dir or not os.path.exists(test_dir): 392 return 393 dylib_lock = os.path.join(test_dir,"crashinfo.lock") 394 dylib_src = os.path.join(test_dir,"crashinfo.c") 395 dylib_dst = os.path.join(test_dir,"crashinfo.so") 396 try: 397 compile_lock = lock.Lock(dylib_lock) 398 compile_lock.acquire() 399 if not os.path.isfile(dylib_dst) or os.path.getmtime(dylib_dst) < os.path.getmtime(dylib_src): 400 # we need to compile 401 cmd = "SDKROOT= xcrun clang %s -o %s -framework Python -Xlinker -dylib -iframework /System/Library/Frameworks/ -Xlinker -F /System/Library/Frameworks/" % (dylib_src,dylib_dst) 402 if subprocess.call(cmd,shell=True) != 0 or not os.path.isfile(dylib_dst): 403 raise Exception('command failed: "{}"'.format(cmd)) 404 finally: 405 compile_lock.release() 406 del compile_lock 407 408 setCrashInfoHook = setCrashInfoHook_Mac 409 410 else: 411 pass 412 413def shouldSkipBecauseOfCategories(test_categories): 414 global useCategories, categoriesList, skipCategories 415 416 if useCategories: 417 if len(test_categories) == 0 or len(categoriesList & set(test_categories)) == 0: 418 return True 419 420 for category in skipCategories: 421 if category in test_categories: 422 return True 423 424 return False 425 426def parseOptionsAndInitTestdirs(): 427 """Initialize the list of directories containing our unittest scripts. 428 429 '-h/--help as the first option prints out usage info and exit the program. 430 """ 431 432 global just_do_benchmarks_test 433 global dont_do_dsym_test 434 global dont_do_dwarf_test 435 global dont_do_dwo_test 436 global blacklist 437 global blacklistConfig 438 global categoriesList 439 global validCategories 440 global useCategories 441 global skipCategories 442 global lldbFrameworkPath 443 global configFile 444 global archs 445 global compilers 446 global count 447 global dumpSysPath 448 global bmExecutable 449 global bmBreakpointSpec 450 global bmIterationCount 451 global failfast 452 global filters 453 global fs4all 454 global ignore 455 global progress_bar 456 global runHooks 457 global skip_build_and_cleanup 458 global skip_long_running_test 459 global noHeaders 460 global parsable 461 global regexp 462 global rdir 463 global sdir_name 464 global svn_silent 465 global verbose 466 global testdirs 467 global lldb_platform_name 468 global lldb_platform_url 469 global lldb_platform_working_dir 470 global setCrashInfoHook 471 global is_inferior_test_runner 472 global multiprocess_test_subdir 473 global num_threads 474 global output_on_success 475 global no_multiprocess_test_runner 476 global test_runner_name 477 global results_filename 478 global results_formatter_name 479 global results_formatter_options 480 global results_port 481 482 do_help = False 483 484 platform_system = platform.system() 485 platform_machine = platform.machine() 486 487 parser = dotest_args.create_parser() 488 args = dotest_args.parse_args(parser, sys.argv[1:]) 489 490 if args.unset_env_varnames: 491 for env_var in args.unset_env_varnames: 492 if env_var in os.environ: 493 # From Python Doc: When unsetenv() is supported, deletion of items in os.environ 494 # is automatically translated into a corresponding call to unsetenv(). 495 del os.environ[env_var] 496 #os.unsetenv(env_var) 497 498 if args.set_env_vars: 499 for env_var in args.set_env_vars: 500 parts = env_var.split('=', 1) 501 if len(parts) == 1: 502 os.environ[parts[0]] = "" 503 else: 504 os.environ[parts[0]] = parts[1] 505 506 # only print the args if being verbose (and parsable is off) 507 if args.v and not args.q: 508 print(sys.argv) 509 510 if args.h: 511 do_help = True 512 513 if args.compilers: 514 compilers = args.compilers 515 else: 516 # Use a compiler appropriate appropriate for the Apple SDK if one was specified 517 if platform_system == 'Darwin' and args.apple_sdk: 518 compilers = [seven.get_command_output('xcrun -sdk "%s" -find clang 2> /dev/null' % (args.apple_sdk))] 519 else: 520 # 'clang' on ubuntu 14.04 is 3.4 so we try clang-3.5 first 521 candidateCompilers = ['clang-3.5', 'clang', 'gcc'] 522 for candidate in candidateCompilers: 523 if which(candidate): 524 compilers = [candidate] 525 break 526 527 if args.channels: 528 lldbtest_config.channels = args.channels 529 530 if args.log_success: 531 lldbtest_config.log_success = args.log_success 532 533 # Set SDKROOT if we are using an Apple SDK 534 if platform_system == 'Darwin' and args.apple_sdk: 535 os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk "%s" --show-sdk-path 2> /dev/null' % (args.apple_sdk)) 536 537 if args.archs: 538 archs = args.archs 539 for arch in archs: 540 if arch.startswith('arm') and platform_system == 'Darwin' and not args.apple_sdk: 541 os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk iphoneos.internal --show-sdk-path 2> /dev/null') 542 if not os.path.exists(os.environ['SDKROOT']): 543 os.environ['SDKROOT'] = seven.get_command_output('xcrun --sdk iphoneos --show-sdk-path 2> /dev/null') 544 else: 545 archs = [platform_machine] 546 547 if args.categoriesList: 548 categoriesList = set(test_categories.validate(args.categoriesList, False)) 549 useCategories = True 550 else: 551 categoriesList = [] 552 553 if args.skipCategories: 554 skipCategories = test_categories.validate(args.skipCategories, False) 555 556 if args.D: 557 dumpSysPath = True 558 559 if args.E: 560 cflags_extras = args.E 561 os.environ['CFLAGS_EXTRAS'] = cflags_extras 562 563 # argparse makes sure we have correct options 564 if args.N == 'dwarf': 565 dont_do_dwarf_test = True 566 elif args.N == 'dwo': 567 dont_do_dwo_test = True 568 elif args.N == 'dsym': 569 dont_do_dsym_test = True 570 571 if args.a or args.plus_a: 572 print("Options '-a' and '+a' have been deprecated. Please use the test category\n" 573 "functionality (-G pyapi, --skip-category pyapi) instead.") 574 sys.exit(1) 575 576 if args.m or args.plus_m: 577 print("Options '-m' and '+m' have been deprecated. Please use the test category\n" 578 "functionality (-G lldb-mi, --skip-category lldb-mi) instead.") 579 sys.exit(1) 580 581 if args.plus_b: 582 just_do_benchmarks_test = True 583 584 if args.b: 585 if args.b.startswith('-'): 586 usage(parser) 587 blacklistFile = args.b 588 if not os.path.isfile(blacklistFile): 589 print('Blacklist file:', blacklistFile, 'does not exist!') 590 usage(parser) 591 # Now read the blacklist contents and assign it to blacklist. 592 execfile(blacklistFile, globals(), blacklistConfig) 593 blacklist = blacklistConfig.get('blacklist') 594 595 if args.c: 596 if args.c.startswith('-'): 597 usage(parser) 598 configFile = args.c 599 if not os.path.isfile(configFile): 600 print('Config file:', configFile, 'does not exist!') 601 usage(parser) 602 603 if args.d: 604 sys.stdout.write("Suspending the process %d to wait for debugger to attach...\n" % os.getpid()) 605 sys.stdout.flush() 606 os.kill(os.getpid(), signal.SIGSTOP) 607 608 if args.e: 609 if args.e.startswith('-'): 610 usage(parser) 611 bmExecutable = args.e 612 if not is_exe(bmExecutable): 613 usage(parser) 614 615 if args.F: 616 failfast = True 617 618 if args.f: 619 if any([x.startswith('-') for x in args.f]): 620 usage(parser) 621 filters.extend(args.f) 622 # Shut off multiprocessing mode when additional filters are specified. 623 # The rational is that the user is probably going after a very specific 624 # test and doesn't need a bunch of parallel test runners all looking for 625 # it in a frenzy. Also, '-v' now spits out all test run output even 626 # on success, so the standard recipe for redoing a failing test (with -v 627 # and a -f to filter to the specific test) now causes all test scanning 628 # (in parallel) to print results for do-nothing runs in a very distracting 629 # manner. If we really need filtered parallel runs in the future, consider 630 # adding a --no-output-on-success that prevents -v from setting 631 # output-on-success. 632 no_multiprocess_test_runner = True 633 634 if args.g: 635 fs4all = False 636 637 if args.i: 638 ignore = True 639 640 if args.k: 641 runHooks.extend(args.k) 642 643 if args.l: 644 skip_long_running_test = False 645 646 if args.framework: 647 lldbFrameworkPath = args.framework 648 649 if args.executable: 650 lldbtest_config.lldbExec = args.executable 651 652 if args.libcxx: 653 os.environ["LIBCXX_PATH"] = args.libcxx 654 655 if args.n: 656 noHeaders = True 657 658 if args.p: 659 if args.p.startswith('-'): 660 usage(parser) 661 regexp = args.p 662 663 if args.q: 664 noHeaders = True 665 parsable = True 666 667 if args.P and not args.v: 668 progress_bar = True 669 verbose = 0 670 671 if args.R: 672 if args.R.startswith('-'): 673 usage(parser) 674 rdir = os.path.abspath(args.R) 675 if os.path.exists(rdir): 676 import shutil 677 print('Removing tree:', rdir) 678 shutil.rmtree(rdir) 679 680 if args.r: 681 if args.r.startswith('-'): 682 usage(parser) 683 rdir = os.path.abspath(args.r) 684 if os.path.exists(rdir): 685 print('Relocated directory:', rdir, 'must not exist!') 686 usage(parser) 687 688 if args.S: 689 skip_build_and_cleanup = True 690 691 if args.s: 692 if args.s.startswith('-'): 693 usage(parser) 694 sdir_name = args.s 695 696 if args.t: 697 os.environ['LLDB_COMMAND_TRACE'] = 'YES' 698 699 if args.T: 700 svn_silent = False 701 702 if args.v: 703 verbose = 2 704 705 if args.w: 706 os.environ['LLDB_WAIT_BETWEEN_TEST_CASES'] = 'YES' 707 708 if args.X: 709 if args.X.startswith('-'): 710 usage(parser) 711 excluded.add(args.X) 712 713 if args.x: 714 if args.x.startswith('-'): 715 usage(parser) 716 bmBreakpointSpec = args.x 717 718 # argparse makes sure we have a number 719 if args.y: 720 bmIterationCount = args.y 721 722 # argparse makes sure we have a number 723 if args.sharp: 724 count = args.sharp 725 726 if sys.platform.startswith('win32'): 727 os.environ['LLDB_DISABLE_CRASH_DIALOG'] = str(args.disable_crash_dialog) 728 os.environ['LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE'] = str(args.hide_inferior_console) 729 730 if do_help == True: 731 usage(parser) 732 733 if args.no_multiprocess: 734 no_multiprocess_test_runner = True 735 736 if args.inferior: 737 is_inferior_test_runner = True 738 739 # Turn on output_on_sucess if either explicitly added or -v specified. 740 if args.output_on_success or args.v: 741 output_on_success = True 742 743 if args.num_threads: 744 num_threads = args.num_threads 745 746 if args.test_subdir: 747 multiprocess_test_subdir = args.test_subdir 748 749 if args.test_runner_name: 750 test_runner_name = args.test_runner_name 751 752 # Capture test results-related args. 753 if args.curses and not args.inferior: 754 # Act as if the following args were set. 755 args.results_formatter = "lldbsuite.test.curses_results.Curses" 756 args.results_file = "stdout" 757 758 if args.results_file: 759 results_filename = args.results_file 760 761 if args.results_port: 762 results_port = args.results_port 763 764 if args.results_file and args.results_port: 765 sys.stderr.write( 766 "only one of --results-file and --results-port should " 767 "be specified\n") 768 usage(args) 769 770 if args.results_formatter: 771 results_formatter_name = args.results_formatter 772 if args.results_formatter_options: 773 results_formatter_options = args.results_formatter_options 774 775 if args.lldb_platform_name: 776 lldb_platform_name = args.lldb_platform_name 777 if args.lldb_platform_url: 778 lldb_platform_url = args.lldb_platform_url 779 if args.lldb_platform_working_dir: 780 lldb_platform_working_dir = args.lldb_platform_working_dir 781 782 if args.event_add_entries and len(args.event_add_entries) > 0: 783 entries = {} 784 # Parse out key=val pairs, separated by comma 785 for keyval in args.event_add_entries.split(","): 786 key_val_entry = keyval.split("=") 787 if len(key_val_entry) == 2: 788 (key, val) = key_val_entry 789 val_parts = val.split(':') 790 if len(val_parts) > 1: 791 (val, val_type) = val_parts 792 if val_type == 'int': 793 val = int(val) 794 entries[key] = val 795 # Tell the event builder to create all events with these 796 # key/val pairs in them. 797 if len(entries) > 0: 798 test_results.EventBuilder.add_entries_to_all_events(entries) 799 800 # Gather all the dirs passed on the command line. 801 if len(args.args) > 0: 802 testdirs = list(map(os.path.abspath, args.args)) 803 # Shut off multiprocessing mode when test directories are specified. 804 no_multiprocess_test_runner = True 805 806 # If '-r dir' is specified, the tests should be run under the relocated 807 # directory. Let's copy the testdirs over. 808 if rdir: 809 from shutil import copytree, ignore_patterns 810 811 tmpdirs = [] 812 orig_testdirs = testdirs[:] 813 for srcdir in testdirs: 814 # For example, /Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/hello_watchpoint 815 # shall be split into ['/Volumes/data/lldb/svn/ToT/', 'functionalities/watchpoint/hello_watchpoint']. 816 # Utilize the relative path to the 'test' directory to make our destination dir path. 817 if ("test" + os.sep) in srcdir: 818 to_split_on = "test" + os.sep 819 else: 820 to_split_on = "test" 821 dstdir = os.path.join(rdir, srcdir.split(to_split_on)[1]) 822 dstdir = dstdir.rstrip(os.sep) 823 # Don't copy the *.pyc and .svn stuffs. 824 copytree(srcdir, dstdir, ignore=ignore_patterns('*.pyc', '.svn')) 825 tmpdirs.append(dstdir) 826 827 # This will be our modified testdirs. 828 testdirs = tmpdirs 829 830 # With '-r dir' specified, there's no cleanup of intermediate test files. 831 os.environ["LLDB_DO_CLEANUP"] = 'NO' 832 833 # If the original testdirs is ['test'], the make directory has already been copied 834 # recursively and is contained within the rdir/test dir. For anything 835 # else, we would need to copy over the make directory and its contents, 836 # so that, os.listdir(rdir) looks like, for example: 837 # 838 # array_types conditional_break make 839 # 840 # where the make directory contains the Makefile.rules file. 841 if len(testdirs) != 1 or os.path.basename(orig_testdirs[0]) != 'test': 842 scriptdir = os.path.dirname(__file__) 843 # Don't copy the .svn stuffs. 844 copytree(os.path.join(scriptdir, 'make'), os.path.join(rdir, 'make'), 845 ignore=ignore_patterns('.svn')) 846 847 #print("testdirs:", testdirs) 848 849 # Source the configFile if specified. 850 # The side effect, if any, will be felt from this point on. An example 851 # config file may be these simple two lines: 852 # 853 # sys.stderr = open("/tmp/lldbtest-stderr", "w") 854 # sys.stdout = open("/tmp/lldbtest-stdout", "w") 855 # 856 # which will reassign the two file objects to sys.stderr and sys.stdout, 857 # respectively. 858 # 859 # See also lldb-trunk/examples/test/usage-config. 860 global config, pre_flight, post_flight, lldbtest_remote_sandbox, lldbtest_remote_shell_template 861 if configFile: 862 # Pass config (a dictionary) as the locals namespace for side-effect. 863 execfile(configFile, globals(), config) 864 #print("config:", config) 865 if "pre_flight" in config: 866 pre_flight = config["pre_flight"] 867 if not six.callable(pre_flight): 868 print("fatal error: pre_flight is not callable, exiting.") 869 sys.exit(1) 870 if "post_flight" in config: 871 post_flight = config["post_flight"] 872 if not six.callable(post_flight): 873 print("fatal error: post_flight is not callable, exiting.") 874 sys.exit(1) 875 if "lldbtest_remote_sandbox" in config: 876 lldbtest_remote_sandbox = config["lldbtest_remote_sandbox"] 877 if "lldbtest_remote_shell_template" in config: 878 lldbtest_remote_shell_template = config["lldbtest_remote_shell_template"] 879 #print("sys.stderr:", sys.stderr) 880 #print("sys.stdout:", sys.stdout) 881 882def getXcodeOutputPaths(lldbRootDirectory): 883 result = [] 884 885 # These are for xcode build directories. 886 xcode3_build_dir = ['build'] 887 xcode4_build_dir = ['build', 'lldb', 'Build', 'Products'] 888 889 configurations = [['Debug'], ['DebugClang'], ['Release'], ['BuildAndIntegration']] 890 xcode_build_dirs = [xcode3_build_dir, xcode4_build_dir] 891 for configuration in configurations: 892 for xcode_build_dir in xcode_build_dirs: 893 outputPath = os.path.join(lldbRootDirectory, *(xcode_build_dir+configuration) ) 894 result.append(outputPath) 895 896 return result 897 898 899def createSocketToLocalPort(port): 900 def socket_closer(s): 901 """Close down an opened socket properly.""" 902 s.shutdown(socket.SHUT_RDWR) 903 s.close() 904 905 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 906 sock.connect(("localhost", port)) 907 return (sock, lambda: socket_closer(sock)) 908 909 910def setupTestResults(): 911 """Sets up test results-related objects based on arg settings.""" 912 global results_filename 913 global results_file_object 914 global results_formatter_name 915 global results_formatter_object 916 global results_formatter_options 917 global results_port 918 919 default_formatter_name = None 920 cleanup_func = None 921 922 if results_filename: 923 # Open the results file for writing. 924 if results_filename == 'stdout': 925 results_file_object = sys.stdout 926 cleanup_func = None 927 elif results_filename == 'stderr': 928 results_file_object = sys.stderr 929 cleanup_func = None 930 else: 931 results_file_object = open(results_filename, "w") 932 cleanup_func = results_file_object.close 933 default_formatter_name = "lldbsuite.test.test_results.XunitFormatter" 934 elif results_port: 935 # Connect to the specified localhost port. 936 results_file_object, cleanup_func = createSocketToLocalPort( 937 results_port) 938 default_formatter_name = ( 939 "lldbsuite.test.test_results.RawPickledFormatter") 940 941 # If we have a results formatter name specified and we didn't specify 942 # a results file, we should use stdout. 943 if results_formatter_name is not None and results_file_object is None: 944 # Use stdout. 945 results_file_object = sys.stdout 946 cleanup_func = None 947 948 if results_file_object: 949 # We care about the formatter. Choose user-specified or, if 950 # none specified, use the default for the output type. 951 if results_formatter_name: 952 formatter_name = results_formatter_name 953 else: 954 formatter_name = default_formatter_name 955 956 # Create an instance of the class. 957 # First figure out the package/module. 958 components = formatter_name.split(".") 959 module = importlib.import_module(".".join(components[:-1])) 960 961 # Create the class name we need to load. 962 clazz = getattr(module, components[-1]) 963 964 # Handle formatter options for the results formatter class. 965 formatter_arg_parser = clazz.arg_parser() 966 if results_formatter_options and len(results_formatter_options) > 0: 967 command_line_options = results_formatter_options 968 else: 969 command_line_options = [] 970 971 formatter_options = formatter_arg_parser.parse_args( 972 command_line_options) 973 974 # Create the TestResultsFormatter given the processed options. 975 results_formatter_object = clazz( 976 results_file_object, formatter_options) 977 978 # Start the results formatter session - we'll only have one 979 # during a given dotest process invocation. 980 initialize_event = EventBuilder.bare_event("initialize") 981 if isMultiprocessTestRunner(): 982 if test_runner_name is not None and test_runner_name == "serial": 983 # Only one worker queue here. 984 worker_count = 1 985 else: 986 # Workers will be the number of threads specified. 987 worker_count = num_threads 988 else: 989 worker_count = 1 990 initialize_event["worker_count"] = worker_count 991 992 results_formatter_object.handle_event(initialize_event) 993 994 def shutdown_formatter(): 995 # Tell the formatter to write out anything it may have 996 # been saving until the very end (e.g. xUnit results 997 # can't complete its output until this point). 998 results_formatter_object.send_terminate_as_needed() 999 1000 # And now close out the output file-like object. 1001 if cleanup_func is not None: 1002 cleanup_func() 1003 1004 atexit.register(shutdown_formatter) 1005 1006 1007def getOutputPaths(lldbRootDirectory): 1008 """ 1009 Returns typical build output paths for the lldb executable 1010 1011 lldbDirectory - path to the root of the lldb svn/git repo 1012 """ 1013 result = [] 1014 1015 if sys.platform == 'darwin': 1016 result.extend(getXcodeOutputPaths(lldbRootDirectory)) 1017 1018 # cmake builds? look for build or build/host folder next to llvm directory 1019 # lldb is located in llvm/tools/lldb so we need to go up three levels 1020 llvmParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir, os.pardir, os.pardir)) 1021 result.append(os.path.join(llvmParentDir, 'build', 'bin')) 1022 result.append(os.path.join(llvmParentDir, 'build', 'host', 'bin')) 1023 1024 # some cmake developers keep their build directory beside their lldb directory 1025 lldbParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir)) 1026 result.append(os.path.join(lldbParentDir, 'build', 'bin')) 1027 result.append(os.path.join(lldbParentDir, 'build', 'host', 'bin')) 1028 1029 return result 1030 1031def setupSysPath(): 1032 """ 1033 Add LLDB.framework/Resources/Python to the search paths for modules. 1034 As a side effect, we also discover the 'lldb' executable and export it here. 1035 """ 1036 1037 global rdir 1038 global testdirs 1039 global dumpSysPath 1040 global noHeaders 1041 global svn_info 1042 global svn_silent 1043 global lldbFrameworkPath 1044 1045 # Get the directory containing the current script. 1046 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ: 1047 scriptPath = os.environ["DOTEST_SCRIPT_DIR"] 1048 else: 1049 scriptPath = os.path.dirname(os.path.realpath(__file__)) 1050 if not scriptPath.endswith('test'): 1051 print("This script expects to reside in lldb's test directory.") 1052 sys.exit(-1) 1053 1054 if rdir: 1055 # Set up the LLDB_TEST environment variable appropriately, so that the 1056 # individual tests can be located relatively. 1057 # 1058 # See also lldbtest.TestBase.setUpClass(cls). 1059 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test': 1060 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test') 1061 else: 1062 os.environ["LLDB_TEST"] = rdir 1063 else: 1064 os.environ["LLDB_TEST"] = scriptPath 1065 1066 # Set up the LLDB_SRC environment variable, so that the tests can locate 1067 # the LLDB source code. 1068 os.environ["LLDB_SRC"] = lldbsuite.lldb_root 1069 1070 pluginPath = os.path.join(scriptPath, 'plugins') 1071 toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi') 1072 toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server') 1073 1074 # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the sys.path. 1075 sys.path.insert(0, pluginPath) 1076 sys.path.insert(0, toolsLLDBMIPath) # Adding test/tools/lldb-mi to the path makes it easy 1077 # to "import lldbmi_testcase" from the MI tests 1078 sys.path.insert(0, toolsLLDBServerPath) # Adding test/tools/lldb-server to the path makes it easy 1079 # to "import lldbgdbserverutils" from the lldb-server tests 1080 1081 # This is the root of the lldb git/svn checkout 1082 # When this changes over to a package instead of a standalone script, this 1083 # will be `lldbsuite.lldb_root` 1084 lldbRootDirectory = lldbsuite.lldb_root 1085 1086 # Some of the tests can invoke the 'lldb' command directly. 1087 # We'll try to locate the appropriate executable right here. 1088 1089 # The lldb executable can be set from the command line 1090 # if it's not set, we try to find it now 1091 # first, we try the environment 1092 if not lldbtest_config.lldbExec: 1093 # First, you can define an environment variable LLDB_EXEC specifying the 1094 # full pathname of the lldb executable. 1095 if "LLDB_EXEC" in os.environ: 1096 lldbtest_config.lldbExec = os.environ["LLDB_EXEC"] 1097 1098 if not lldbtest_config.lldbExec: 1099 outputPaths = getOutputPaths(lldbRootDirectory) 1100 for outputPath in outputPaths: 1101 candidatePath = os.path.join(outputPath, 'lldb') 1102 if is_exe(candidatePath): 1103 lldbtest_config.lldbExec = candidatePath 1104 break 1105 1106 if not lldbtest_config.lldbExec: 1107 # Last, check the path 1108 lldbtest_config.lldbExec = which('lldb') 1109 1110 if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec): 1111 print("'{}' is not a path to a valid executable".format(lldbtest_config.lldbExec)) 1112 lldbtest_config.lldbExec = None 1113 1114 if not lldbtest_config.lldbExec: 1115 print("The 'lldb' executable cannot be located. Some of the tests may not be run as a result.") 1116 sys.exit(-1) 1117 1118 lldbLibDir = os.path.dirname(lldbtest_config.lldbExec) # confusingly, this is the "bin" directory 1119 os.environ["LLDB_LIB_DIR"] = lldbLibDir 1120 lldbImpLibDir = os.path.join(lldbLibDir, '..', 'lib') if sys.platform.startswith('win32') else lldbLibDir 1121 os.environ["LLDB_IMPLIB_DIR"] = lldbImpLibDir 1122 if not noHeaders: 1123 print("LLDB library dir:", os.environ["LLDB_LIB_DIR"]) 1124 print("LLDB import library dir:", os.environ["LLDB_IMPLIB_DIR"]) 1125 os.system('%s -v' % lldbtest_config.lldbExec) 1126 1127 # Assume lldb-mi is in same place as lldb 1128 # If not found, disable the lldb-mi tests 1129 lldbMiExec = None 1130 if lldbtest_config.lldbExec and is_exe(lldbtest_config.lldbExec + "-mi"): 1131 lldbMiExec = lldbtest_config.lldbExec + "-mi" 1132 if not lldbMiExec: 1133 if not shouldSkipBecauseOfCategories(["lldb-mi"]): 1134 print("The 'lldb-mi' executable cannot be located. The lldb-mi tests can not be run as a result.") 1135 skipCategories.append("lldb-mi") 1136 else: 1137 os.environ["LLDBMI_EXEC"] = lldbMiExec 1138 1139 # Skip printing svn/git information when running in parsable (lit-test compatibility) mode 1140 if not svn_silent and not parsable: 1141 if os.path.isdir(os.path.join(lldbRootDirectory, '.svn')) and which("svn") is not None: 1142 pipe = subprocess.Popen([which("svn"), "info", lldbRootDirectory], stdout = subprocess.PIPE) 1143 svn_info = pipe.stdout.read() 1144 elif os.path.isdir(os.path.join(lldbRootDirectory, '.git')) and which("git") is not None: 1145 pipe = subprocess.Popen([which("git"), "svn", "info", lldbRootDirectory], stdout = subprocess.PIPE) 1146 svn_info = pipe.stdout.read() 1147 if not noHeaders: 1148 print(svn_info) 1149 1150 global ignore 1151 1152 lldbPythonDir = None # The directory that contains 'lldb/__init__.py' 1153 if lldbFrameworkPath: 1154 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python') 1155 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')): 1156 lldbPythonDir = candidatePath 1157 if not lldbPythonDir: 1158 print('Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath) 1159 sys.exit(-1) 1160 else: 1161 # The '-i' option is used to skip looking for lldb.py in the build tree. 1162 if ignore: 1163 return 1164 1165 # If our lldb supports the -P option, use it to find the python path: 1166 init_in_python_dir = os.path.join('lldb', '__init__.py') 1167 1168 lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True) 1169 1170 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")) \ 1171 and not lldb_dash_p_result.startswith("Traceback"): 1172 lines = lldb_dash_p_result.splitlines() 1173 1174 # Workaround for readline vs libedit issue on FreeBSD. If stdout 1175 # is not a terminal Python executes 1176 # rl_variable_bind ("enable-meta-key", "off"); 1177 # This produces a warning with FreeBSD's libedit because the 1178 # enable-meta-key variable is unknown. Not an issue on Apple 1179 # because cpython commit f0ab6f9f0603 added a #ifndef __APPLE__ 1180 # around the call. See http://bugs.python.org/issue19884 for more 1181 # information. For now we just discard the warning output. 1182 if len(lines) >= 1 and lines[0].startswith("bind: Invalid command"): 1183 lines.pop(0) 1184 1185 # Taking the last line because lldb outputs 1186 # 'Cannot read termcap database;\nusing dumb terminal settings.\n' 1187 # before the path 1188 if len(lines) >= 1 and os.path.isfile(os.path.join(lines[-1], init_in_python_dir)): 1189 lldbPythonDir = lines[-1] 1190 if "freebsd" in sys.platform or "linux" in sys.platform: 1191 os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPythonDir, '..', '..') 1192 1193 if not lldbPythonDir: 1194 if platform.system() == "Darwin": 1195 python_resource_dir = ['LLDB.framework', 'Resources', 'Python'] 1196 outputPaths = getXcodeOutputPaths() 1197 for outputPath in outputPaths: 1198 candidatePath = os.path.join(outputPath, python_resource_dir) 1199 if os.path.isfile(os.path.join(candidatePath, init_in_python_dir)): 1200 lldbPythonDir = candidatePath 1201 break 1202 1203 if not lldbPythonDir: 1204 print('This script requires lldb.py to be in either ' + dbgPath + ',', end=' ') 1205 print(relPath + ', or ' + baiPath + '. Some tests might fail.') 1206 else: 1207 print("Unable to load lldb extension module. Possible reasons for this include:") 1208 print(" 1) LLDB was built with LLDB_DISABLE_PYTHON=1") 1209 print(" 2) PYTHONPATH and PYTHONHOME are not set correctly. PYTHONHOME should refer to") 1210 print(" the version of Python that LLDB built and linked against, and PYTHONPATH") 1211 print(" should contain the Lib directory for the same python distro, as well as the") 1212 print(" location of LLDB\'s site-packages folder.") 1213 print(" 3) A different version of Python than that which was built against is exported in") 1214 print(" the system\'s PATH environment variable, causing conflicts.") 1215 print(" 4) The executable '%s' could not be found. Please check " % lldbExecutable) 1216 print(" that it exists and is executable.") 1217 1218 if lldbPythonDir: 1219 lldbPythonDir = os.path.normpath(lldbPythonDir) 1220 # Some of the code that uses this path assumes it hasn't resolved the Versions... link. 1221 # If the path we've constructed looks like that, then we'll strip out the Versions/A part. 1222 (before, frameWithVersion, after) = lldbPythonDir.rpartition("LLDB.framework/Versions/A") 1223 if frameWithVersion != "" : 1224 lldbPythonDir = before + "LLDB.framework" + after 1225 1226 lldbPythonDir = os.path.abspath(lldbPythonDir) 1227 1228 # If tests need to find LLDB_FRAMEWORK, now they can do it 1229 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPythonDir)) 1230 1231 # This is to locate the lldb.py module. Insert it right after sys.path[0]. 1232 sys.path[1:1] = [lldbPythonDir] 1233 if dumpSysPath: 1234 print("sys.path:", sys.path) 1235 1236def visit(prefix, dir, names): 1237 """Visitor function for os.path.walk(path, visit, arg).""" 1238 1239 global suite 1240 global regexp 1241 global filters 1242 global fs4all 1243 global excluded 1244 global all_tests 1245 1246 if set(dir.split(os.sep)).intersection(excluded): 1247 #print("Detected an excluded dir component: %s" % dir) 1248 return 1249 1250 for name in names: 1251 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix): 1252 1253 if name in all_tests: 1254 raise Exception("Found multiple tests with the name %s" % name) 1255 all_tests.add(name) 1256 1257 # Try to match the regexp pattern, if specified. 1258 if regexp: 1259 import re 1260 if re.search(regexp, name): 1261 #print("Filename: '%s' matches pattern: '%s'" % (name, regexp)) 1262 pass 1263 else: 1264 #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp)) 1265 continue 1266 1267 # We found a match for our test. Add it to the suite. 1268 1269 # Update the sys.path first. 1270 if not sys.path.count(dir): 1271 sys.path.insert(0, dir) 1272 base = os.path.splitext(name)[0] 1273 1274 # Thoroughly check the filterspec against the base module and admit 1275 # the (base, filterspec) combination only when it makes sense. 1276 filterspec = None 1277 for filterspec in filters: 1278 # Optimistically set the flag to True. 1279 filtered = True 1280 module = __import__(base) 1281 parts = filterspec.split('.') 1282 obj = module 1283 for part in parts: 1284 try: 1285 parent, obj = obj, getattr(obj, part) 1286 except AttributeError: 1287 # The filterspec has failed. 1288 filtered = False 1289 break 1290 1291 # If filtered, we have a good filterspec. Add it. 1292 if filtered: 1293 #print("adding filter spec %s to module %s" % (filterspec, module)) 1294 suite.addTests( 1295 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module)) 1296 continue 1297 1298 # Forgo this module if the (base, filterspec) combo is invalid 1299 # and no '-g' option is specified 1300 if filters and fs4all and not filtered: 1301 continue 1302 1303 # Add either the filtered test case(s) (which is done before) or the entire test class. 1304 if not filterspec or not filtered: 1305 # A simple case of just the module name. Also the failover case 1306 # from the filterspec branch when the (base, filterspec) combo 1307 # doesn't make sense. 1308 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base)) 1309 1310 1311def disabledynamics(): 1312 import lldb 1313 ci = lldb.DBG.GetCommandInterpreter() 1314 res = lldb.SBCommandReturnObject() 1315 ci.HandleCommand("setting set target.prefer-dynamic-value no-dynamic-values", res, False) 1316 if not res.Succeeded(): 1317 raise Exception('disabling dynamic type support failed') 1318 1319def lldbLoggings(): 1320 import lldb 1321 """Check and do lldb loggings if necessary.""" 1322 1323 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is 1324 # defined. Use ${LLDB_LOG} to specify the log file. 1325 ci = lldb.DBG.GetCommandInterpreter() 1326 res = lldb.SBCommandReturnObject() 1327 if ("LLDB_LOG" in os.environ): 1328 open(os.environ["LLDB_LOG"], 'w').close() 1329 if ("LLDB_LOG_OPTION" in os.environ): 1330 lldb_log_option = os.environ["LLDB_LOG_OPTION"] 1331 else: 1332 lldb_log_option = "event process expr state api" 1333 ci.HandleCommand( 1334 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option, 1335 res) 1336 if not res.Succeeded(): 1337 raise Exception('log enable failed (check LLDB_LOG env variable)') 1338 1339 if ("LLDB_LINUX_LOG" in os.environ): 1340 open(os.environ["LLDB_LINUX_LOG"], 'w').close() 1341 if ("LLDB_LINUX_LOG_OPTION" in os.environ): 1342 lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"] 1343 else: 1344 lldb_log_option = "event process expr state api" 1345 ci.HandleCommand( 1346 "log enable -n -f " + os.environ["LLDB_LINUX_LOG"] + " linux " + lldb_log_option, 1347 res) 1348 if not res.Succeeded(): 1349 raise Exception('log enable failed (check LLDB_LINUX_LOG env variable)') 1350 1351 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined. 1352 # Use ${GDB_REMOTE_LOG} to specify the log file. 1353 if ("GDB_REMOTE_LOG" in os.environ): 1354 if ("GDB_REMOTE_LOG_OPTION" in os.environ): 1355 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"] 1356 else: 1357 gdb_remote_log_option = "packets process" 1358 ci.HandleCommand( 1359 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote " 1360 + gdb_remote_log_option, 1361 res) 1362 if not res.Succeeded(): 1363 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable)') 1364 1365def getMyCommandLine(): 1366 return ' '.join(sys.argv) 1367 1368# ======================================== # 1369# # 1370# Execution of the test driver starts here # 1371# # 1372# ======================================== # 1373 1374def checkDsymForUUIDIsNotOn(): 1375 cmd = ["defaults", "read", "com.apple.DebugSymbols"] 1376 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) 1377 cmd_output = pipe.stdout.read() 1378 if cmd_output and "DBGFileMappedPaths = " in cmd_output: 1379 print("%s =>" % ' '.join(cmd)) 1380 print(cmd_output) 1381 print("Disable automatic lookup and caching of dSYMs before running the test suite!") 1382 print("Exiting...") 1383 sys.exit(0) 1384 1385def exitTestSuite(exitCode = None): 1386 import lldb 1387 lldb.SBDebugger.Terminate() 1388 if exitCode: 1389 sys.exit(exitCode) 1390 1391 1392def isMultiprocessTestRunner(): 1393 # We're not multiprocess when we're either explicitly 1394 # the inferior (as specified by the multiprocess test 1395 # runner) OR we've been told to skip using the multiprocess 1396 # test runner 1397 return not (is_inferior_test_runner or no_multiprocess_test_runner) 1398 1399def getVersionForSDK(sdk): 1400 sdk = str.lower(sdk) 1401 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) 1402 basename = os.path.basename(full_path) 1403 basename = os.path.splitext(basename)[0] 1404 basename = str.lower(basename) 1405 ver = basename.replace(sdk, '') 1406 return ver 1407 1408def getPathForSDK(sdk): 1409 sdk = str.lower(sdk) 1410 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) 1411 if os.path.exists(full_path): return full_path 1412 return None 1413 1414def setDefaultTripleForPlatform(): 1415 if lldb_platform_name == 'ios-simulator': 1416 triple_str = 'x86_64-apple-ios%s' % (getVersionForSDK('iphonesimulator')) 1417 os.environ['TRIPLE'] = triple_str 1418 return {'TRIPLE':triple_str} 1419 return {} 1420 1421def run_suite(): 1422 global just_do_benchmarks_test 1423 global dont_do_dsym_test 1424 global dont_do_dwarf_test 1425 global dont_do_dwo_test 1426 global blacklist 1427 global blacklistConfig 1428 global categoriesList 1429 global validCategories 1430 global useCategories 1431 global skipCategories 1432 global lldbFrameworkPath 1433 global configFile 1434 global archs 1435 global compilers 1436 global count 1437 global dumpSysPath 1438 global bmExecutable 1439 global bmBreakpointSpec 1440 global bmIterationCount 1441 global failed 1442 global failfast 1443 global filters 1444 global fs4all 1445 global ignore 1446 global progress_bar 1447 global runHooks 1448 global skip_build_and_cleanup 1449 global skip_long_running_test 1450 global noHeaders 1451 global parsable 1452 global regexp 1453 global rdir 1454 global sdir_name 1455 global svn_silent 1456 global verbose 1457 global testdirs 1458 global lldb_platform_name 1459 global lldb_platform_url 1460 global lldb_platform_working_dir 1461 global setCrashInfoHook 1462 global is_inferior_test_runner 1463 global multiprocess_test_subdir 1464 global num_threads 1465 global output_on_success 1466 global no_multiprocess_test_runner 1467 global test_runner_name 1468 global results_filename 1469 global results_formatter_name 1470 global results_formatter_options 1471 global results_port 1472 1473 # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults 1474 # does not exist before proceeding to running the test suite. 1475 if sys.platform.startswith("darwin"): 1476 checkDsymForUUIDIsNotOn() 1477 1478 # 1479 # Start the actions by first parsing the options while setting up the test 1480 # directories, followed by setting up the search paths for lldb utilities; 1481 # then, we walk the directory trees and collect the tests into our test suite. 1482 # 1483 parseOptionsAndInitTestdirs() 1484 1485 # Setup test results (test results formatter and output handling). 1486 setupTestResults() 1487 1488 # If we are running as the multiprocess test runner, kick off the 1489 # multiprocess test runner here. 1490 if isMultiprocessTestRunner(): 1491 from . import dosep 1492 dosep.main(output_on_success, num_threads, multiprocess_test_subdir, 1493 test_runner_name, results_formatter_object) 1494 raise Exception("should never get here") 1495 elif is_inferior_test_runner: 1496 # Shut off Ctrl-C processing in inferiors. The parallel 1497 # test runner handles this more holistically. 1498 signal.signal(signal.SIGINT, signal.SIG_IGN) 1499 1500 setupSysPath() 1501 setupCrashInfoHook() 1502 1503 # 1504 # If '-l' is specified, do not skip the long running tests. 1505 if not skip_long_running_test: 1506 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO" 1507 1508 # For the time being, let's bracket the test runner within the 1509 # lldb.SBDebugger.Initialize()/Terminate() pair. 1510 import lldb 1511 1512 # Create a singleton SBDebugger in the lldb namespace. 1513 lldb.DBG = lldb.SBDebugger.Create() 1514 1515 if lldb_platform_name: 1516 print("Setting up remote platform '%s'" % (lldb_platform_name)) 1517 lldb.remote_platform = lldb.SBPlatform(lldb_platform_name) 1518 lldb.remote_platform_name = lldb_platform_name 1519 if not lldb.remote_platform.IsValid(): 1520 print("error: unable to create the LLDB platform named '%s'." % (lldb_platform_name)) 1521 exitTestSuite(1) 1522 if lldb_platform_url: 1523 # We must connect to a remote platform if a LLDB platform URL was specified 1524 print("Connecting to remote platform '%s' at '%s'..." % (lldb_platform_name, lldb_platform_url)) 1525 lldb.platform_url = lldb_platform_url 1526 platform_connect_options = lldb.SBPlatformConnectOptions(lldb_platform_url) 1527 err = lldb.remote_platform.ConnectRemote(platform_connect_options) 1528 if err.Success(): 1529 print("Connected.") 1530 else: 1531 print("error: failed to connect to remote platform using URL '%s': %s" % (lldb_platform_url, err)) 1532 exitTestSuite(1) 1533 else: 1534 lldb.platform_url = None 1535 1536 platform_changes = setDefaultTripleForPlatform() 1537 first = True 1538 for key in platform_changes: 1539 if first: 1540 print("Environment variables setup for platform support:") 1541 first = False 1542 print("%s = %s" % (key,platform_changes[key])) 1543 1544 if lldb_platform_working_dir: 1545 print("Setting remote platform working directory to '%s'..." % (lldb_platform_working_dir)) 1546 lldb.remote_platform.SetWorkingDirectory(lldb_platform_working_dir) 1547 lldb.remote_platform_working_dir = lldb_platform_working_dir 1548 lldb.DBG.SetSelectedPlatform(lldb.remote_platform) 1549 else: 1550 lldb.remote_platform = None 1551 lldb.remote_platform_working_dir = None 1552 lldb.platform_url = None 1553 1554 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] 1555 1556 # By default, both dsym, dwarf and dwo tests are performed. 1557 # Use @dsym_test, @dwarf_test or @dwo_test decorators, defined in lldbtest.py, to mark a test as 1558 # a dsym, dwarf or dwo test. Use '-N dsym', '-N dwarf' or '-N dwo' to exclude dsym, dwarf or 1559 # dwo tests from running. 1560 dont_do_dsym_test = dont_do_dsym_test or any(platform in target_platform for platform in ["linux", "freebsd", "windows"]) 1561 dont_do_dwo_test = dont_do_dwo_test or any(platform in target_platform for platform in ["darwin", "macosx", "ios"]) 1562 1563 # Don't do debugserver tests on everything except OS X. 1564 dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform 1565 1566 # Don't do lldb-server (llgs) tests on anything except Linux. 1567 dont_do_llgs_test = not ("linux" in target_platform) 1568 1569 # 1570 # Walk through the testdirs while collecting tests. 1571 # 1572 for testdir in testdirs: 1573 for (dirpath, dirnames, filenames) in os.walk(testdir): 1574 visit('Test', dirpath, filenames) 1575 1576 # 1577 # Now that we have loaded all the test cases, run the whole test suite. 1578 # 1579 1580 # Put the blacklist in the lldb namespace, to be used by lldb.TestBase. 1581 lldb.blacklist = blacklist 1582 1583 # The pre_flight and post_flight come from reading a config file. 1584 lldb.pre_flight = pre_flight 1585 lldb.post_flight = post_flight 1586 def getsource_if_available(obj): 1587 """ 1588 Return the text of the source code for an object if available. Otherwise, 1589 a print representation is returned. 1590 """ 1591 import inspect 1592 try: 1593 return inspect.getsource(obj) 1594 except: 1595 return repr(obj) 1596 1597 if not noHeaders: 1598 print("lldb.pre_flight:", getsource_if_available(lldb.pre_flight)) 1599 print("lldb.post_flight:", getsource_if_available(lldb.post_flight)) 1600 1601 # If either pre_flight or post_flight is defined, set lldb.test_remote to True. 1602 if lldb.pre_flight or lldb.post_flight: 1603 lldb.test_remote = True 1604 else: 1605 lldb.test_remote = False 1606 1607 # So do the lldbtest_remote_sandbox and lldbtest_remote_shell_template variables. 1608 lldb.lldbtest_remote_sandbox = lldbtest_remote_sandbox 1609 lldb.lldbtest_remote_sandboxed_executable = None 1610 lldb.lldbtest_remote_shell_template = lldbtest_remote_shell_template 1611 1612 # Put all these test decorators in the lldb namespace. 1613 lldb.just_do_benchmarks_test = just_do_benchmarks_test 1614 lldb.dont_do_dsym_test = dont_do_dsym_test 1615 lldb.dont_do_dwarf_test = dont_do_dwarf_test 1616 lldb.dont_do_dwo_test = dont_do_dwo_test 1617 lldb.dont_do_debugserver_test = dont_do_debugserver_test 1618 lldb.dont_do_llgs_test = dont_do_llgs_test 1619 1620 # Do we need to skip build and cleanup? 1621 lldb.skip_build_and_cleanup = skip_build_and_cleanup 1622 1623 # Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too. 1624 lldb.bmExecutable = bmExecutable 1625 lldb.bmBreakpointSpec = bmBreakpointSpec 1626 lldb.bmIterationCount = bmIterationCount 1627 1628 # And don't forget the runHooks! 1629 lldb.runHooks = runHooks 1630 1631 # Turn on lldb loggings if necessary. 1632 lldbLoggings() 1633 1634 # Disable default dynamic types for testing purposes 1635 disabledynamics() 1636 1637 # Install the control-c handler. 1638 unittest2.signals.installHandler() 1639 1640 # If sdir_name is not specified through the '-s sdir_name' option, get a 1641 # timestamp string and export it as LLDB_SESSION_DIR environment var. This will 1642 # be used when/if we want to dump the session info of individual test cases 1643 # later on. 1644 # 1645 # See also TestBase.dumpSessionInfo() in lldbtest.py. 1646 import datetime 1647 # The windows platforms don't like ':' in the pathname. 1648 timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S") 1649 if not sdir_name: 1650 sdir_name = timestamp_started 1651 os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name) 1652 1653 if not noHeaders: 1654 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes" 1655 " will go into directory '%s'\n" % sdir_name) 1656 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine()) 1657 1658 if not os.path.isdir(sdir_name): 1659 try: 1660 os.mkdir(sdir_name) 1661 except OSError as exception: 1662 if exception.errno != errno.EEXIST: 1663 raise 1664 where_to_save_session = os.getcwd() 1665 fname = os.path.join(sdir_name, "TestStarted-%d" % os.getpid()) 1666 with open(fname, "w") as f: 1667 print("Test started at: %s\n" % timestamp_started, file=f) 1668 print(svn_info, file=f) 1669 print("Command invoked: %s\n" % getMyCommandLine(), file=f) 1670 1671 # 1672 # Invoke the default TextTestRunner to run the test suite, possibly iterating 1673 # over different configurations. 1674 # 1675 1676 iterArchs = False 1677 iterCompilers = False 1678 1679 if not archs and "archs" in config: 1680 archs = config["archs"] 1681 1682 if isinstance(archs, list) and len(archs) >= 1: 1683 iterArchs = True 1684 1685 if not compilers and "compilers" in config: 1686 compilers = config["compilers"] 1687 1688 # 1689 # Add some intervention here to sanity check that the compilers requested are sane. 1690 # If found not to be an executable program, the invalid one is dropped from the list. 1691 for i in range(len(compilers)): 1692 c = compilers[i] 1693 if which(c): 1694 continue 1695 else: 1696 if sys.platform.startswith("darwin"): 1697 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT) 1698 cmd_output = pipe.stdout.read() 1699 if cmd_output: 1700 if "not found" in cmd_output: 1701 print("dropping %s from the compilers used" % c) 1702 compilers.remove(i) 1703 else: 1704 compilers[i] = cmd_output.split('\n')[0] 1705 print("'xcrun -find %s' returning %s" % (c, compilers[i])) 1706 1707 if not parsable: 1708 print("compilers=%s" % str(compilers)) 1709 1710 if not compilers or len(compilers) == 0: 1711 print("No eligible compiler found, exiting.") 1712 exitTestSuite(1) 1713 1714 if isinstance(compilers, list) and len(compilers) >= 1: 1715 iterCompilers = True 1716 1717 # Make a shallow copy of sys.path, we need to manipulate the search paths later. 1718 # This is only necessary if we are relocated and with different configurations. 1719 if rdir: 1720 old_sys_path = sys.path[:] 1721 # If we iterate on archs or compilers, there is a chance we want to split stderr/stdout. 1722 if iterArchs or iterCompilers: 1723 old_stderr = sys.stderr 1724 old_stdout = sys.stdout 1725 new_stderr = None 1726 new_stdout = None 1727 1728 # Iterating over all possible architecture and compiler combinations. 1729 for ia in range(len(archs) if iterArchs else 1): 1730 archConfig = "" 1731 if iterArchs: 1732 os.environ["ARCH"] = archs[ia] 1733 archConfig = "arch=%s" % archs[ia] 1734 for ic in range(len(compilers) if iterCompilers else 1): 1735 if iterCompilers: 1736 os.environ["CC"] = compilers[ic] 1737 configString = "%s compiler=%s" % (archConfig, compilers[ic]) 1738 else: 1739 configString = archConfig 1740 1741 if iterArchs or iterCompilers: 1742 # Translate ' ' to '-' for pathname component. 1743 if six.PY2: 1744 import string 1745 tbl = string.maketrans(' ', '-') 1746 else: 1747 tbl = str.maketrans(' ', '-') 1748 configPostfix = configString.translate(tbl) 1749 1750 # Check whether we need to split stderr/stdout into configuration 1751 # specific files. 1752 if old_stderr.name != '<stderr>' and config.get('split_stderr'): 1753 if new_stderr: 1754 new_stderr.close() 1755 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w") 1756 sys.stderr = new_stderr 1757 if old_stdout.name != '<stdout>' and config.get('split_stdout'): 1758 if new_stdout: 1759 new_stdout.close() 1760 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w") 1761 sys.stdout = new_stdout 1762 1763 # If we specified a relocated directory to run the test suite, do 1764 # the extra housekeeping to copy the testdirs to a configStringified 1765 # directory and to update sys.path before invoking the test runner. 1766 # The purpose is to separate the configuration-specific directories 1767 # from each other. 1768 if rdir: 1769 from shutil import copytree, rmtree, ignore_patterns 1770 1771 newrdir = "%s.%s" % (rdir, configPostfix) 1772 1773 # Copy the tree to a new directory with postfix name configPostfix. 1774 if os.path.exists(newrdir): 1775 rmtree(newrdir) 1776 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d')) 1777 1778 # Update the LLDB_TEST environment variable to reflect new top 1779 # level test directory. 1780 # 1781 # See also lldbtest.TestBase.setUpClass(cls). 1782 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test': 1783 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test') 1784 else: 1785 os.environ["LLDB_TEST"] = newrdir 1786 1787 # And update the Python search paths for modules. 1788 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path] 1789 1790 # Output the configuration. 1791 if not parsable: 1792 sys.stderr.write("\nConfiguration: " + configString + "\n") 1793 1794 #print("sys.stderr name is", sys.stderr.name) 1795 #print("sys.stdout name is", sys.stdout.name) 1796 1797 # First, write out the number of collected test cases. 1798 if not parsable: 1799 sys.stderr.write(separator + "\n") 1800 sys.stderr.write("Collected %d test%s\n\n" 1801 % (suite.countTestCases(), 1802 suite.countTestCases() != 1 and "s" or "")) 1803 1804 class LLDBTestResult(unittest2.TextTestResult): 1805 """ 1806 Enforce a singleton pattern to allow introspection of test progress. 1807 1808 Overwrite addError(), addFailure(), and addExpectedFailure() methods 1809 to enable each test instance to track its failure/error status. It 1810 is used in the LLDB test framework to emit detailed trace messages 1811 to a log file for easier human inspection of test failures/errors. 1812 """ 1813 __singleton__ = None 1814 __ignore_singleton__ = False 1815 1816 @staticmethod 1817 def getTerminalSize(): 1818 import os 1819 env = os.environ 1820 def ioctl_GWINSZ(fd): 1821 try: 1822 import fcntl, termios, struct, os 1823 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, 1824 '1234')) 1825 except: 1826 return 1827 return cr 1828 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) 1829 if not cr: 1830 try: 1831 fd = os.open(os.ctermid(), os.O_RDONLY) 1832 cr = ioctl_GWINSZ(fd) 1833 os.close(fd) 1834 except: 1835 pass 1836 if not cr: 1837 cr = (env.get('LINES', 25), env.get('COLUMNS', 80)) 1838 return int(cr[1]), int(cr[0]) 1839 1840 def __init__(self, *args): 1841 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__: 1842 raise Exception("LLDBTestResult instantiated more than once") 1843 super(LLDBTestResult, self).__init__(*args) 1844 LLDBTestResult.__singleton__ = self 1845 # Now put this singleton into the lldb module namespace. 1846 lldb.test_result = self 1847 # Computes the format string for displaying the counter. 1848 global suite 1849 counterWidth = len(str(suite.countTestCases())) 1850 self.fmt = "%" + str(counterWidth) + "d: " 1851 self.indentation = ' ' * (counterWidth + 2) 1852 # This counts from 1 .. suite.countTestCases(). 1853 self.counter = 0 1854 (width, height) = LLDBTestResult.getTerminalSize() 1855 self.progressbar = None 1856 global progress_bar 1857 if width > 10 and not parsable and progress_bar: 1858 try: 1859 self.progressbar = progress.ProgressWithEvents(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10) 1860 except: 1861 self.progressbar = None 1862 self.results_formatter = results_formatter_object 1863 1864 def _config_string(self, test): 1865 compiler = getattr(test, "getCompiler", None) 1866 arch = getattr(test, "getArchitecture", None) 1867 return "%s-%s" % (compiler() if compiler else "", arch() if arch else "") 1868 1869 def _exc_info_to_string(self, err, test): 1870 """Overrides superclass TestResult's method in order to append 1871 our test config info string to the exception info string.""" 1872 if hasattr(test, "getArchitecture") and hasattr(test, "getCompiler"): 1873 return '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test), 1874 test.getArchitecture(), 1875 test.getCompiler()) 1876 else: 1877 return super(LLDBTestResult, self)._exc_info_to_string(err, test) 1878 1879 def getDescription(self, test): 1880 doc_first_line = test.shortDescription() 1881 if self.descriptions and doc_first_line: 1882 return '\n'.join((str(test), self.indentation + doc_first_line)) 1883 else: 1884 return str(test) 1885 1886 def getCategoriesForTest(self,test): 1887 if hasattr(test,"_testMethodName"): 1888 test_method = getattr(test,"_testMethodName") 1889 test_method = getattr(test,test_method) 1890 else: 1891 test_method = None 1892 if test_method != None and hasattr(test_method,"getCategories"): 1893 test_categories = test_method.getCategories(test) 1894 elif hasattr(test,"getCategories"): 1895 test_categories = test.getCategories() 1896 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"): 1897 test_categories = test.__self__.getCategories() 1898 else: 1899 test_categories = [] 1900 if test_categories == None: 1901 test_categories = [] 1902 return test_categories 1903 1904 def hardMarkAsSkipped(self,test): 1905 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True 1906 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" 1907 test.__class__.__unittest_skip__ = True 1908 test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" 1909 1910 def startTest(self, test): 1911 if shouldSkipBecauseOfCategories(self.getCategoriesForTest(test)): 1912 self.hardMarkAsSkipped(test) 1913 global setCrashInfoHook 1914 setCrashInfoHook("%s at %s" % (str(test),inspect.getfile(test.__class__))) 1915 self.counter += 1 1916 #if self.counter == 4: 1917 # import crashinfo 1918 # crashinfo.testCrashReporterDescription(None) 1919 test.test_number = self.counter 1920 if self.showAll: 1921 self.stream.write(self.fmt % self.counter) 1922 super(LLDBTestResult, self).startTest(test) 1923 if self.results_formatter: 1924 self.results_formatter.handle_event( 1925 EventBuilder.event_for_start(test)) 1926 1927 def addSuccess(self, test): 1928 global parsable 1929 super(LLDBTestResult, self).addSuccess(test) 1930 if parsable: 1931 self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1932 if self.results_formatter: 1933 self.results_formatter.handle_event( 1934 EventBuilder.event_for_success(test)) 1935 1936 def addError(self, test, err): 1937 global sdir_has_content 1938 global parsable 1939 sdir_has_content = True 1940 super(LLDBTestResult, self).addError(test, err) 1941 method = getattr(test, "markError", None) 1942 if method: 1943 method() 1944 if parsable: 1945 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1946 if self.results_formatter: 1947 self.results_formatter.handle_event( 1948 EventBuilder.event_for_error(test, err)) 1949 1950 def addCleanupError(self, test, err): 1951 global sdir_has_content 1952 global parsable 1953 sdir_has_content = True 1954 super(LLDBTestResult, self).addCleanupError(test, err) 1955 method = getattr(test, "markCleanupError", None) 1956 if method: 1957 method() 1958 if parsable: 1959 self.stream.write("CLEANUP ERROR: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1960 if self.results_formatter: 1961 self.results_formatter.handle_event( 1962 EventBuilder.event_for_cleanup_error( 1963 test, err)) 1964 1965 def addFailure(self, test, err): 1966 global sdir_has_content 1967 global failuresPerCategory 1968 global parsable 1969 sdir_has_content = True 1970 super(LLDBTestResult, self).addFailure(test, err) 1971 method = getattr(test, "markFailure", None) 1972 if method: 1973 method() 1974 if parsable: 1975 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1976 if useCategories: 1977 test_categories = self.getCategoriesForTest(test) 1978 for category in test_categories: 1979 if category in failuresPerCategory: 1980 failuresPerCategory[category] = failuresPerCategory[category] + 1 1981 else: 1982 failuresPerCategory[category] = 1 1983 if self.results_formatter: 1984 self.results_formatter.handle_event( 1985 EventBuilder.event_for_failure(test, err)) 1986 1987 1988 def addExpectedFailure(self, test, err, bugnumber): 1989 global sdir_has_content 1990 global parsable 1991 sdir_has_content = True 1992 super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber) 1993 method = getattr(test, "markExpectedFailure", None) 1994 if method: 1995 method(err, bugnumber) 1996 if parsable: 1997 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1998 if self.results_formatter: 1999 self.results_formatter.handle_event( 2000 EventBuilder.event_for_expected_failure( 2001 test, err, bugnumber)) 2002 2003 def addSkip(self, test, reason): 2004 global sdir_has_content 2005 global parsable 2006 sdir_has_content = True 2007 super(LLDBTestResult, self).addSkip(test, reason) 2008 method = getattr(test, "markSkippedTest", None) 2009 if method: 2010 method() 2011 if parsable: 2012 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason)) 2013 if self.results_formatter: 2014 self.results_formatter.handle_event( 2015 EventBuilder.event_for_skip(test, reason)) 2016 2017 def addUnexpectedSuccess(self, test, bugnumber): 2018 global sdir_has_content 2019 global parsable 2020 sdir_has_content = True 2021 super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber) 2022 method = getattr(test, "markUnexpectedSuccess", None) 2023 if method: 2024 method(bugnumber) 2025 if parsable: 2026 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 2027 if self.results_formatter: 2028 self.results_formatter.handle_event( 2029 EventBuilder.event_for_unexpected_success( 2030 test, bugnumber)) 2031 2032 2033 if parsable: 2034 v = 0 2035 elif progress_bar: 2036 v = 1 2037 else: 2038 v = verbose 2039 2040 # Invoke the test runner. 2041 if count == 1: 2042 result = unittest2.TextTestRunner(stream=sys.stderr, 2043 verbosity=v, 2044 failfast=failfast, 2045 resultclass=LLDBTestResult).run(suite) 2046 else: 2047 # We are invoking the same test suite more than once. In this case, 2048 # mark __ignore_singleton__ flag as True so the signleton pattern is 2049 # not enforced. 2050 LLDBTestResult.__ignore_singleton__ = True 2051 for i in range(count): 2052 2053 result = unittest2.TextTestRunner(stream=sys.stderr, 2054 verbosity=v, 2055 failfast=failfast, 2056 resultclass=LLDBTestResult).run(suite) 2057 2058 failed = failed or not result.wasSuccessful() 2059 2060 if sdir_has_content and not parsable: 2061 sys.stderr.write("Session logs for test failures/errors/unexpected successes" 2062 " can be found in directory '%s'\n" % sdir_name) 2063 2064 if useCategories and len(failuresPerCategory) > 0: 2065 sys.stderr.write("Failures per category:\n") 2066 for category in failuresPerCategory: 2067 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category])) 2068 2069 os.chdir(where_to_save_session) 2070 fname = os.path.join(sdir_name, "TestFinished-%d" % os.getpid()) 2071 with open(fname, "w") as f: 2072 print("Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S"), file=f) 2073 2074 # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined. 2075 # This should not be necessary now. 2076 if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ): 2077 print("Terminating Test suite...") 2078 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())]) 2079 2080 # Exiting. 2081 exitTestSuite(failed) 2082 2083if __name__ == "__main__": 2084 print(__file__ + " is for use as a module only. It should not be run as a standalone script.") 2085 sys.exit(-1) 2086