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 = "lldbsuite.test.test_results.RawPickledFormatter" 939 940 if results_file_object: 941 # We care about the formatter. Choose user-specified or, if 942 # none specified, use the default for the output type. 943 if results_formatter_name: 944 formatter_name = results_formatter_name 945 else: 946 formatter_name = default_formatter_name 947 948 # Create an instance of the class. First figure out the package/module. 949 components = formatter_name.split(".") 950 module = importlib.import_module(".".join(components[:-1])) 951 952 # Create the class name we need to load. 953 clazz = getattr(module, components[-1]) 954 955 # Handle formatter options for the results formatter class. 956 formatter_arg_parser = clazz.arg_parser() 957 if results_formatter_options and len(results_formatter_options) > 0: 958 command_line_options = results_formatter_options 959 else: 960 command_line_options = [] 961 962 formatter_options = formatter_arg_parser.parse_args( 963 command_line_options) 964 965 # Create the TestResultsFormatter given the processed options. 966 results_formatter_object = clazz(results_file_object, formatter_options) 967 968 # Start the results formatter session - we'll only have one 969 # during a given dotest process invocation. 970 initialize_event = EventBuilder.bare_event("initialize") 971 if isMultiprocessTestRunner(): 972 if test_runner_name is not None and test_runner_name == "serial": 973 # Only one worker queue here. 974 worker_count = 1 975 else: 976 # Workers will be the number of threads specified. 977 worker_count = num_threads 978 else: 979 worker_count = 1 980 initialize_event["worker_count"] = worker_count 981 982 results_formatter_object.handle_event(initialize_event) 983 984 def shutdown_formatter(): 985 # Tell the formatter to write out anything it may have 986 # been saving until the very end (e.g. xUnit results 987 # can't complete its output until this point). 988 results_formatter_object.send_terminate_as_needed() 989 990 # And now close out the output file-like object. 991 if cleanup_func is not None: 992 cleanup_func() 993 994 atexit.register(shutdown_formatter) 995 996 997def getOutputPaths(lldbRootDirectory): 998 """ 999 Returns typical build output paths for the lldb executable 1000 1001 lldbDirectory - path to the root of the lldb svn/git repo 1002 """ 1003 result = [] 1004 1005 if sys.platform == 'darwin': 1006 result.extend(getXcodeOutputPaths(lldbRootDirectory)) 1007 1008 # cmake builds? look for build or build/host folder next to llvm directory 1009 # lldb is located in llvm/tools/lldb so we need to go up three levels 1010 llvmParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir, os.pardir, os.pardir)) 1011 result.append(os.path.join(llvmParentDir, 'build', 'bin')) 1012 result.append(os.path.join(llvmParentDir, 'build', 'host', 'bin')) 1013 1014 # some cmake developers keep their build directory beside their lldb directory 1015 lldbParentDir = os.path.abspath(os.path.join(lldbRootDirectory, os.pardir)) 1016 result.append(os.path.join(lldbParentDir, 'build', 'bin')) 1017 result.append(os.path.join(lldbParentDir, 'build', 'host', 'bin')) 1018 1019 return result 1020 1021def setupSysPath(): 1022 """ 1023 Add LLDB.framework/Resources/Python to the search paths for modules. 1024 As a side effect, we also discover the 'lldb' executable and export it here. 1025 """ 1026 1027 global rdir 1028 global testdirs 1029 global dumpSysPath 1030 global noHeaders 1031 global svn_info 1032 global svn_silent 1033 global lldbFrameworkPath 1034 1035 # Get the directory containing the current script. 1036 if "DOTEST_PROFILE" in os.environ and "DOTEST_SCRIPT_DIR" in os.environ: 1037 scriptPath = os.environ["DOTEST_SCRIPT_DIR"] 1038 else: 1039 scriptPath = os.path.dirname(os.path.realpath(__file__)) 1040 if not scriptPath.endswith('test'): 1041 print("This script expects to reside in lldb's test directory.") 1042 sys.exit(-1) 1043 1044 if rdir: 1045 # Set up the LLDB_TEST environment variable appropriately, so that the 1046 # individual tests can be located relatively. 1047 # 1048 # See also lldbtest.TestBase.setUpClass(cls). 1049 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test': 1050 os.environ["LLDB_TEST"] = os.path.join(rdir, 'test') 1051 else: 1052 os.environ["LLDB_TEST"] = rdir 1053 else: 1054 os.environ["LLDB_TEST"] = scriptPath 1055 1056 # Set up the LLDB_SRC environment variable, so that the tests can locate 1057 # the LLDB source code. 1058 os.environ["LLDB_SRC"] = lldbsuite.lldb_root 1059 1060 pluginPath = os.path.join(scriptPath, 'plugins') 1061 toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi') 1062 toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server') 1063 1064 # Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the sys.path. 1065 sys.path.insert(0, pluginPath) 1066 sys.path.insert(0, toolsLLDBMIPath) # Adding test/tools/lldb-mi to the path makes it easy 1067 # to "import lldbmi_testcase" from the MI tests 1068 sys.path.insert(0, toolsLLDBServerPath) # Adding test/tools/lldb-server to the path makes it easy 1069 # to "import lldbgdbserverutils" from the lldb-server tests 1070 1071 # This is the root of the lldb git/svn checkout 1072 # When this changes over to a package instead of a standalone script, this 1073 # will be `lldbsuite.lldb_root` 1074 lldbRootDirectory = lldbsuite.lldb_root 1075 1076 # Some of the tests can invoke the 'lldb' command directly. 1077 # We'll try to locate the appropriate executable right here. 1078 1079 # The lldb executable can be set from the command line 1080 # if it's not set, we try to find it now 1081 # first, we try the environment 1082 if not lldbtest_config.lldbExec: 1083 # First, you can define an environment variable LLDB_EXEC specifying the 1084 # full pathname of the lldb executable. 1085 if "LLDB_EXEC" in os.environ: 1086 lldbtest_config.lldbExec = os.environ["LLDB_EXEC"] 1087 1088 if not lldbtest_config.lldbExec: 1089 outputPaths = getOutputPaths(lldbRootDirectory) 1090 for outputPath in outputPaths: 1091 candidatePath = os.path.join(outputPath, 'lldb') 1092 if is_exe(candidatePath): 1093 lldbtest_config.lldbExec = candidatePath 1094 break 1095 1096 if not lldbtest_config.lldbExec: 1097 # Last, check the path 1098 lldbtest_config.lldbExec = which('lldb') 1099 1100 if lldbtest_config.lldbExec and not is_exe(lldbtest_config.lldbExec): 1101 print("'{}' is not a path to a valid executable".format(lldbtest_config.lldbExec)) 1102 lldbtest_config.lldbExec = None 1103 1104 if not lldbtest_config.lldbExec: 1105 print("The 'lldb' executable cannot be located. Some of the tests may not be run as a result.") 1106 sys.exit(-1) 1107 1108 lldbLibDir = os.path.dirname(lldbtest_config.lldbExec) # confusingly, this is the "bin" directory 1109 os.environ["LLDB_LIB_DIR"] = lldbLibDir 1110 lldbImpLibDir = os.path.join(lldbLibDir, '..', 'lib') if sys.platform.startswith('win32') else lldbLibDir 1111 os.environ["LLDB_IMPLIB_DIR"] = lldbImpLibDir 1112 if not noHeaders: 1113 print("LLDB library dir:", os.environ["LLDB_LIB_DIR"]) 1114 print("LLDB import library dir:", os.environ["LLDB_IMPLIB_DIR"]) 1115 os.system('%s -v' % lldbtest_config.lldbExec) 1116 1117 # Assume lldb-mi is in same place as lldb 1118 # If not found, disable the lldb-mi tests 1119 lldbMiExec = None 1120 if lldbtest_config.lldbExec and is_exe(lldbtest_config.lldbExec + "-mi"): 1121 lldbMiExec = lldbtest_config.lldbExec + "-mi" 1122 if not lldbMiExec: 1123 if not shouldSkipBecauseOfCategories(["lldb-mi"]): 1124 print("The 'lldb-mi' executable cannot be located. The lldb-mi tests can not be run as a result.") 1125 skipCategories.append("lldb-mi") 1126 else: 1127 os.environ["LLDBMI_EXEC"] = lldbMiExec 1128 1129 # Skip printing svn/git information when running in parsable (lit-test compatibility) mode 1130 if not svn_silent and not parsable: 1131 if os.path.isdir(os.path.join(lldbRootDirectory, '.svn')) and which("svn") is not None: 1132 pipe = subprocess.Popen([which("svn"), "info", lldbRootDirectory], stdout = subprocess.PIPE) 1133 svn_info = pipe.stdout.read() 1134 elif os.path.isdir(os.path.join(lldbRootDirectory, '.git')) and which("git") is not None: 1135 pipe = subprocess.Popen([which("git"), "svn", "info", lldbRootDirectory], stdout = subprocess.PIPE) 1136 svn_info = pipe.stdout.read() 1137 if not noHeaders: 1138 print(svn_info) 1139 1140 global ignore 1141 1142 lldbPythonDir = None # The directory that contains 'lldb/__init__.py' 1143 if lldbFrameworkPath: 1144 candidatePath = os.path.join(lldbFrameworkPath, 'Resources', 'Python') 1145 if os.path.isfile(os.path.join(candidatePath, 'lldb/__init__.py')): 1146 lldbPythonDir = candidatePath 1147 if not lldbPythonDir: 1148 print('Resources/Python/lldb/__init__.py was not found in ' + lldbFrameworkPath) 1149 sys.exit(-1) 1150 else: 1151 # The '-i' option is used to skip looking for lldb.py in the build tree. 1152 if ignore: 1153 return 1154 1155 # If our lldb supports the -P option, use it to find the python path: 1156 init_in_python_dir = os.path.join('lldb', '__init__.py') 1157 1158 lldb_dash_p_result = subprocess.check_output([lldbtest_config.lldbExec, "-P"], stderr=subprocess.STDOUT, universal_newlines=True) 1159 1160 if lldb_dash_p_result and not lldb_dash_p_result.startswith(("<", "lldb: invalid option:")) \ 1161 and not lldb_dash_p_result.startswith("Traceback"): 1162 lines = lldb_dash_p_result.splitlines() 1163 1164 # Workaround for readline vs libedit issue on FreeBSD. If stdout 1165 # is not a terminal Python executes 1166 # rl_variable_bind ("enable-meta-key", "off"); 1167 # This produces a warning with FreeBSD's libedit because the 1168 # enable-meta-key variable is unknown. Not an issue on Apple 1169 # because cpython commit f0ab6f9f0603 added a #ifndef __APPLE__ 1170 # around the call. See http://bugs.python.org/issue19884 for more 1171 # information. For now we just discard the warning output. 1172 if len(lines) >= 1 and lines[0].startswith("bind: Invalid command"): 1173 lines.pop(0) 1174 1175 # Taking the last line because lldb outputs 1176 # 'Cannot read termcap database;\nusing dumb terminal settings.\n' 1177 # before the path 1178 if len(lines) >= 1 and os.path.isfile(os.path.join(lines[-1], init_in_python_dir)): 1179 lldbPythonDir = lines[-1] 1180 if "freebsd" in sys.platform or "linux" in sys.platform: 1181 os.environ['LLDB_LIB_DIR'] = os.path.join(lldbPythonDir, '..', '..') 1182 1183 if not lldbPythonDir: 1184 if platform.system() == "Darwin": 1185 python_resource_dir = ['LLDB.framework', 'Resources', 'Python'] 1186 outputPaths = getXcodeOutputPaths() 1187 for outputPath in outputPaths: 1188 candidatePath = os.path.join(outputPath, python_resource_dir) 1189 if os.path.isfile(os.path.join(candidatePath, init_in_python_dir)): 1190 lldbPythonDir = candidatePath 1191 break 1192 1193 if not lldbPythonDir: 1194 print('This script requires lldb.py to be in either ' + dbgPath + ',', end=' ') 1195 print(relPath + ', or ' + baiPath + '. Some tests might fail.') 1196 else: 1197 print("Unable to load lldb extension module. Possible reasons for this include:") 1198 print(" 1) LLDB was built with LLDB_DISABLE_PYTHON=1") 1199 print(" 2) PYTHONPATH and PYTHONHOME are not set correctly. PYTHONHOME should refer to") 1200 print(" the version of Python that LLDB built and linked against, and PYTHONPATH") 1201 print(" should contain the Lib directory for the same python distro, as well as the") 1202 print(" location of LLDB\'s site-packages folder.") 1203 print(" 3) A different version of Python than that which was built against is exported in") 1204 print(" the system\'s PATH environment variable, causing conflicts.") 1205 print(" 4) The executable '%s' could not be found. Please check " % lldbExecutable) 1206 print(" that it exists and is executable.") 1207 1208 if lldbPythonDir: 1209 lldbPythonDir = os.path.normpath(lldbPythonDir) 1210 # Some of the code that uses this path assumes it hasn't resolved the Versions... link. 1211 # If the path we've constructed looks like that, then we'll strip out the Versions/A part. 1212 (before, frameWithVersion, after) = lldbPythonDir.rpartition("LLDB.framework/Versions/A") 1213 if frameWithVersion != "" : 1214 lldbPythonDir = before + "LLDB.framework" + after 1215 1216 lldbPythonDir = os.path.abspath(lldbPythonDir) 1217 1218 # If tests need to find LLDB_FRAMEWORK, now they can do it 1219 os.environ["LLDB_FRAMEWORK"] = os.path.dirname(os.path.dirname(lldbPythonDir)) 1220 1221 # This is to locate the lldb.py module. Insert it right after sys.path[0]. 1222 sys.path[1:1] = [lldbPythonDir] 1223 if dumpSysPath: 1224 print("sys.path:", sys.path) 1225 1226def visit(prefix, dir, names): 1227 """Visitor function for os.path.walk(path, visit, arg).""" 1228 1229 global suite 1230 global regexp 1231 global filters 1232 global fs4all 1233 global excluded 1234 global all_tests 1235 1236 if set(dir.split(os.sep)).intersection(excluded): 1237 #print("Detected an excluded dir component: %s" % dir) 1238 return 1239 1240 for name in names: 1241 if '.py' == os.path.splitext(name)[1] and name.startswith(prefix): 1242 1243 if name in all_tests: 1244 raise Exception("Found multiple tests with the name %s" % name) 1245 all_tests.add(name) 1246 1247 # Try to match the regexp pattern, if specified. 1248 if regexp: 1249 import re 1250 if re.search(regexp, name): 1251 #print("Filename: '%s' matches pattern: '%s'" % (name, regexp)) 1252 pass 1253 else: 1254 #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp)) 1255 continue 1256 1257 # We found a match for our test. Add it to the suite. 1258 1259 # Update the sys.path first. 1260 if not sys.path.count(dir): 1261 sys.path.insert(0, dir) 1262 base = os.path.splitext(name)[0] 1263 1264 # Thoroughly check the filterspec against the base module and admit 1265 # the (base, filterspec) combination only when it makes sense. 1266 filterspec = None 1267 for filterspec in filters: 1268 # Optimistically set the flag to True. 1269 filtered = True 1270 module = __import__(base) 1271 parts = filterspec.split('.') 1272 obj = module 1273 for part in parts: 1274 try: 1275 parent, obj = obj, getattr(obj, part) 1276 except AttributeError: 1277 # The filterspec has failed. 1278 filtered = False 1279 break 1280 1281 # If filtered, we have a good filterspec. Add it. 1282 if filtered: 1283 #print("adding filter spec %s to module %s" % (filterspec, module)) 1284 suite.addTests( 1285 unittest2.defaultTestLoader.loadTestsFromName(filterspec, module)) 1286 continue 1287 1288 # Forgo this module if the (base, filterspec) combo is invalid 1289 # and no '-g' option is specified 1290 if filters and fs4all and not filtered: 1291 continue 1292 1293 # Add either the filtered test case(s) (which is done before) or the entire test class. 1294 if not filterspec or not filtered: 1295 # A simple case of just the module name. Also the failover case 1296 # from the filterspec branch when the (base, filterspec) combo 1297 # doesn't make sense. 1298 suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base)) 1299 1300 1301def disabledynamics(): 1302 import lldb 1303 ci = lldb.DBG.GetCommandInterpreter() 1304 res = lldb.SBCommandReturnObject() 1305 ci.HandleCommand("setting set target.prefer-dynamic-value no-dynamic-values", res, False) 1306 if not res.Succeeded(): 1307 raise Exception('disabling dynamic type support failed') 1308 1309def lldbLoggings(): 1310 import lldb 1311 """Check and do lldb loggings if necessary.""" 1312 1313 # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is 1314 # defined. Use ${LLDB_LOG} to specify the log file. 1315 ci = lldb.DBG.GetCommandInterpreter() 1316 res = lldb.SBCommandReturnObject() 1317 if ("LLDB_LOG" in os.environ): 1318 open(os.environ["LLDB_LOG"], 'w').close() 1319 if ("LLDB_LOG_OPTION" in os.environ): 1320 lldb_log_option = os.environ["LLDB_LOG_OPTION"] 1321 else: 1322 lldb_log_option = "event process expr state api" 1323 ci.HandleCommand( 1324 "log enable -n -f " + os.environ["LLDB_LOG"] + " lldb " + lldb_log_option, 1325 res) 1326 if not res.Succeeded(): 1327 raise Exception('log enable failed (check LLDB_LOG env variable)') 1328 1329 if ("LLDB_LINUX_LOG" in os.environ): 1330 open(os.environ["LLDB_LINUX_LOG"], 'w').close() 1331 if ("LLDB_LINUX_LOG_OPTION" in os.environ): 1332 lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"] 1333 else: 1334 lldb_log_option = "event process expr state api" 1335 ci.HandleCommand( 1336 "log enable -n -f " + os.environ["LLDB_LINUX_LOG"] + " linux " + lldb_log_option, 1337 res) 1338 if not res.Succeeded(): 1339 raise Exception('log enable failed (check LLDB_LINUX_LOG env variable)') 1340 1341 # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined. 1342 # Use ${GDB_REMOTE_LOG} to specify the log file. 1343 if ("GDB_REMOTE_LOG" in os.environ): 1344 if ("GDB_REMOTE_LOG_OPTION" in os.environ): 1345 gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"] 1346 else: 1347 gdb_remote_log_option = "packets process" 1348 ci.HandleCommand( 1349 "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote " 1350 + gdb_remote_log_option, 1351 res) 1352 if not res.Succeeded(): 1353 raise Exception('log enable failed (check GDB_REMOTE_LOG env variable)') 1354 1355def getMyCommandLine(): 1356 return ' '.join(sys.argv) 1357 1358# ======================================== # 1359# # 1360# Execution of the test driver starts here # 1361# # 1362# ======================================== # 1363 1364def checkDsymForUUIDIsNotOn(): 1365 cmd = ["defaults", "read", "com.apple.DebugSymbols"] 1366 pipe = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT) 1367 cmd_output = pipe.stdout.read() 1368 if cmd_output and "DBGFileMappedPaths = " in cmd_output: 1369 print("%s =>" % ' '.join(cmd)) 1370 print(cmd_output) 1371 print("Disable automatic lookup and caching of dSYMs before running the test suite!") 1372 print("Exiting...") 1373 sys.exit(0) 1374 1375def exitTestSuite(exitCode = None): 1376 import lldb 1377 lldb.SBDebugger.Terminate() 1378 if exitCode: 1379 sys.exit(exitCode) 1380 1381 1382def isMultiprocessTestRunner(): 1383 # We're not multiprocess when we're either explicitly 1384 # the inferior (as specified by the multiprocess test 1385 # runner) OR we've been told to skip using the multiprocess 1386 # test runner 1387 return not (is_inferior_test_runner or no_multiprocess_test_runner) 1388 1389def getVersionForSDK(sdk): 1390 sdk = str.lower(sdk) 1391 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) 1392 basename = os.path.basename(full_path) 1393 basename = os.path.splitext(basename)[0] 1394 basename = str.lower(basename) 1395 ver = basename.replace(sdk, '') 1396 return ver 1397 1398def getPathForSDK(sdk): 1399 sdk = str.lower(sdk) 1400 full_path = seven.get_command_output('xcrun -sdk %s --show-sdk-path' % sdk) 1401 if os.path.exists(full_path): return full_path 1402 return None 1403 1404def setDefaultTripleForPlatform(): 1405 if lldb_platform_name == 'ios-simulator': 1406 triple_str = 'x86_64-apple-ios%s' % (getVersionForSDK('iphonesimulator')) 1407 os.environ['TRIPLE'] = triple_str 1408 return {'TRIPLE':triple_str} 1409 return {} 1410 1411def run_suite(): 1412 global just_do_benchmarks_test 1413 global dont_do_dsym_test 1414 global dont_do_dwarf_test 1415 global dont_do_dwo_test 1416 global blacklist 1417 global blacklistConfig 1418 global categoriesList 1419 global validCategories 1420 global useCategories 1421 global skipCategories 1422 global lldbFrameworkPath 1423 global configFile 1424 global archs 1425 global compilers 1426 global count 1427 global dumpSysPath 1428 global bmExecutable 1429 global bmBreakpointSpec 1430 global bmIterationCount 1431 global failed 1432 global failfast 1433 global filters 1434 global fs4all 1435 global ignore 1436 global progress_bar 1437 global runHooks 1438 global skip_build_and_cleanup 1439 global skip_long_running_test 1440 global noHeaders 1441 global parsable 1442 global regexp 1443 global rdir 1444 global sdir_name 1445 global svn_silent 1446 global verbose 1447 global testdirs 1448 global lldb_platform_name 1449 global lldb_platform_url 1450 global lldb_platform_working_dir 1451 global setCrashInfoHook 1452 global is_inferior_test_runner 1453 global multiprocess_test_subdir 1454 global num_threads 1455 global output_on_success 1456 global no_multiprocess_test_runner 1457 global test_runner_name 1458 global results_filename 1459 global results_formatter_name 1460 global results_formatter_options 1461 global results_port 1462 1463 # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults 1464 # does not exist before proceeding to running the test suite. 1465 if sys.platform.startswith("darwin"): 1466 checkDsymForUUIDIsNotOn() 1467 1468 # 1469 # Start the actions by first parsing the options while setting up the test 1470 # directories, followed by setting up the search paths for lldb utilities; 1471 # then, we walk the directory trees and collect the tests into our test suite. 1472 # 1473 parseOptionsAndInitTestdirs() 1474 1475 # Setup test results (test results formatter and output handling). 1476 setupTestResults() 1477 1478 # If we are running as the multiprocess test runner, kick off the 1479 # multiprocess test runner here. 1480 if isMultiprocessTestRunner(): 1481 from . import dosep 1482 dosep.main(output_on_success, num_threads, multiprocess_test_subdir, 1483 test_runner_name, results_formatter_object) 1484 raise Exception("should never get here") 1485 elif is_inferior_test_runner: 1486 # Shut off Ctrl-C processing in inferiors. The parallel 1487 # test runner handles this more holistically. 1488 signal.signal(signal.SIGINT, signal.SIG_IGN) 1489 1490 setupSysPath() 1491 setupCrashInfoHook() 1492 1493 # 1494 # If '-l' is specified, do not skip the long running tests. 1495 if not skip_long_running_test: 1496 os.environ["LLDB_SKIP_LONG_RUNNING_TEST"] = "NO" 1497 1498 # For the time being, let's bracket the test runner within the 1499 # lldb.SBDebugger.Initialize()/Terminate() pair. 1500 import lldb 1501 1502 # Create a singleton SBDebugger in the lldb namespace. 1503 lldb.DBG = lldb.SBDebugger.Create() 1504 1505 if lldb_platform_name: 1506 print("Setting up remote platform '%s'" % (lldb_platform_name)) 1507 lldb.remote_platform = lldb.SBPlatform(lldb_platform_name) 1508 lldb.remote_platform_name = lldb_platform_name 1509 if not lldb.remote_platform.IsValid(): 1510 print("error: unable to create the LLDB platform named '%s'." % (lldb_platform_name)) 1511 exitTestSuite(1) 1512 if lldb_platform_url: 1513 # We must connect to a remote platform if a LLDB platform URL was specified 1514 print("Connecting to remote platform '%s' at '%s'..." % (lldb_platform_name, lldb_platform_url)) 1515 lldb.platform_url = lldb_platform_url 1516 platform_connect_options = lldb.SBPlatformConnectOptions(lldb_platform_url) 1517 err = lldb.remote_platform.ConnectRemote(platform_connect_options) 1518 if err.Success(): 1519 print("Connected.") 1520 else: 1521 print("error: failed to connect to remote platform using URL '%s': %s" % (lldb_platform_url, err)) 1522 exitTestSuite(1) 1523 else: 1524 lldb.platform_url = None 1525 1526 platform_changes = setDefaultTripleForPlatform() 1527 first = True 1528 for key in platform_changes: 1529 if first: 1530 print("Environment variables setup for platform support:") 1531 first = False 1532 print("%s = %s" % (key,platform_changes[key])) 1533 1534 if lldb_platform_working_dir: 1535 print("Setting remote platform working directory to '%s'..." % (lldb_platform_working_dir)) 1536 lldb.remote_platform.SetWorkingDirectory(lldb_platform_working_dir) 1537 lldb.remote_platform_working_dir = lldb_platform_working_dir 1538 lldb.DBG.SetSelectedPlatform(lldb.remote_platform) 1539 else: 1540 lldb.remote_platform = None 1541 lldb.remote_platform_working_dir = None 1542 lldb.platform_url = None 1543 1544 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] 1545 1546 # By default, both dsym, dwarf and dwo tests are performed. 1547 # Use @dsym_test, @dwarf_test or @dwo_test decorators, defined in lldbtest.py, to mark a test as 1548 # a dsym, dwarf or dwo test. Use '-N dsym', '-N dwarf' or '-N dwo' to exclude dsym, dwarf or 1549 # dwo tests from running. 1550 dont_do_dsym_test = dont_do_dsym_test or any(platform in target_platform for platform in ["linux", "freebsd", "windows"]) 1551 dont_do_dwo_test = dont_do_dwo_test or any(platform in target_platform for platform in ["darwin", "macosx", "ios"]) 1552 1553 # Don't do debugserver tests on everything except OS X. 1554 dont_do_debugserver_test = "linux" in target_platform or "freebsd" in target_platform or "windows" in target_platform 1555 1556 # Don't do lldb-server (llgs) tests on anything except Linux. 1557 dont_do_llgs_test = not ("linux" in target_platform) 1558 1559 # 1560 # Walk through the testdirs while collecting tests. 1561 # 1562 for testdir in testdirs: 1563 for (dirpath, dirnames, filenames) in os.walk(testdir): 1564 visit('Test', dirpath, filenames) 1565 1566 # 1567 # Now that we have loaded all the test cases, run the whole test suite. 1568 # 1569 1570 # Put the blacklist in the lldb namespace, to be used by lldb.TestBase. 1571 lldb.blacklist = blacklist 1572 1573 # The pre_flight and post_flight come from reading a config file. 1574 lldb.pre_flight = pre_flight 1575 lldb.post_flight = post_flight 1576 def getsource_if_available(obj): 1577 """ 1578 Return the text of the source code for an object if available. Otherwise, 1579 a print representation is returned. 1580 """ 1581 import inspect 1582 try: 1583 return inspect.getsource(obj) 1584 except: 1585 return repr(obj) 1586 1587 if not noHeaders: 1588 print("lldb.pre_flight:", getsource_if_available(lldb.pre_flight)) 1589 print("lldb.post_flight:", getsource_if_available(lldb.post_flight)) 1590 1591 # If either pre_flight or post_flight is defined, set lldb.test_remote to True. 1592 if lldb.pre_flight or lldb.post_flight: 1593 lldb.test_remote = True 1594 else: 1595 lldb.test_remote = False 1596 1597 # So do the lldbtest_remote_sandbox and lldbtest_remote_shell_template variables. 1598 lldb.lldbtest_remote_sandbox = lldbtest_remote_sandbox 1599 lldb.lldbtest_remote_sandboxed_executable = None 1600 lldb.lldbtest_remote_shell_template = lldbtest_remote_shell_template 1601 1602 # Put all these test decorators in the lldb namespace. 1603 lldb.just_do_benchmarks_test = just_do_benchmarks_test 1604 lldb.dont_do_dsym_test = dont_do_dsym_test 1605 lldb.dont_do_dwarf_test = dont_do_dwarf_test 1606 lldb.dont_do_dwo_test = dont_do_dwo_test 1607 lldb.dont_do_debugserver_test = dont_do_debugserver_test 1608 lldb.dont_do_llgs_test = dont_do_llgs_test 1609 1610 # Do we need to skip build and cleanup? 1611 lldb.skip_build_and_cleanup = skip_build_and_cleanup 1612 1613 # Put bmExecutable, bmBreakpointSpec, and bmIterationCount into the lldb namespace, too. 1614 lldb.bmExecutable = bmExecutable 1615 lldb.bmBreakpointSpec = bmBreakpointSpec 1616 lldb.bmIterationCount = bmIterationCount 1617 1618 # And don't forget the runHooks! 1619 lldb.runHooks = runHooks 1620 1621 # Turn on lldb loggings if necessary. 1622 lldbLoggings() 1623 1624 # Disable default dynamic types for testing purposes 1625 disabledynamics() 1626 1627 # Install the control-c handler. 1628 unittest2.signals.installHandler() 1629 1630 # If sdir_name is not specified through the '-s sdir_name' option, get a 1631 # timestamp string and export it as LLDB_SESSION_DIR environment var. This will 1632 # be used when/if we want to dump the session info of individual test cases 1633 # later on. 1634 # 1635 # See also TestBase.dumpSessionInfo() in lldbtest.py. 1636 import datetime 1637 # The windows platforms don't like ':' in the pathname. 1638 timestamp_started = datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S") 1639 if not sdir_name: 1640 sdir_name = timestamp_started 1641 os.environ["LLDB_SESSION_DIRNAME"] = os.path.join(os.getcwd(), sdir_name) 1642 1643 if not noHeaders: 1644 sys.stderr.write("\nSession logs for test failures/errors/unexpected successes" 1645 " will go into directory '%s'\n" % sdir_name) 1646 sys.stderr.write("Command invoked: %s\n" % getMyCommandLine()) 1647 1648 if not os.path.isdir(sdir_name): 1649 try: 1650 os.mkdir(sdir_name) 1651 except OSError as exception: 1652 if exception.errno != errno.EEXIST: 1653 raise 1654 where_to_save_session = os.getcwd() 1655 fname = os.path.join(sdir_name, "TestStarted-%d" % os.getpid()) 1656 with open(fname, "w") as f: 1657 print("Test started at: %s\n" % timestamp_started, file=f) 1658 print(svn_info, file=f) 1659 print("Command invoked: %s\n" % getMyCommandLine(), file=f) 1660 1661 # 1662 # Invoke the default TextTestRunner to run the test suite, possibly iterating 1663 # over different configurations. 1664 # 1665 1666 iterArchs = False 1667 iterCompilers = False 1668 1669 if not archs and "archs" in config: 1670 archs = config["archs"] 1671 1672 if isinstance(archs, list) and len(archs) >= 1: 1673 iterArchs = True 1674 1675 if not compilers and "compilers" in config: 1676 compilers = config["compilers"] 1677 1678 # 1679 # Add some intervention here to sanity check that the compilers requested are sane. 1680 # If found not to be an executable program, the invalid one is dropped from the list. 1681 for i in range(len(compilers)): 1682 c = compilers[i] 1683 if which(c): 1684 continue 1685 else: 1686 if sys.platform.startswith("darwin"): 1687 pipe = subprocess.Popen(['xcrun', '-find', c], stdout = subprocess.PIPE, stderr = subprocess.STDOUT) 1688 cmd_output = pipe.stdout.read() 1689 if cmd_output: 1690 if "not found" in cmd_output: 1691 print("dropping %s from the compilers used" % c) 1692 compilers.remove(i) 1693 else: 1694 compilers[i] = cmd_output.split('\n')[0] 1695 print("'xcrun -find %s' returning %s" % (c, compilers[i])) 1696 1697 if not parsable: 1698 print("compilers=%s" % str(compilers)) 1699 1700 if not compilers or len(compilers) == 0: 1701 print("No eligible compiler found, exiting.") 1702 exitTestSuite(1) 1703 1704 if isinstance(compilers, list) and len(compilers) >= 1: 1705 iterCompilers = True 1706 1707 # Make a shallow copy of sys.path, we need to manipulate the search paths later. 1708 # This is only necessary if we are relocated and with different configurations. 1709 if rdir: 1710 old_sys_path = sys.path[:] 1711 # If we iterate on archs or compilers, there is a chance we want to split stderr/stdout. 1712 if iterArchs or iterCompilers: 1713 old_stderr = sys.stderr 1714 old_stdout = sys.stdout 1715 new_stderr = None 1716 new_stdout = None 1717 1718 # Iterating over all possible architecture and compiler combinations. 1719 for ia in range(len(archs) if iterArchs else 1): 1720 archConfig = "" 1721 if iterArchs: 1722 os.environ["ARCH"] = archs[ia] 1723 archConfig = "arch=%s" % archs[ia] 1724 for ic in range(len(compilers) if iterCompilers else 1): 1725 if iterCompilers: 1726 os.environ["CC"] = compilers[ic] 1727 configString = "%s compiler=%s" % (archConfig, compilers[ic]) 1728 else: 1729 configString = archConfig 1730 1731 if iterArchs or iterCompilers: 1732 # Translate ' ' to '-' for pathname component. 1733 if six.PY2: 1734 import string 1735 tbl = string.maketrans(' ', '-') 1736 else: 1737 tbl = str.maketrans(' ', '-') 1738 configPostfix = configString.translate(tbl) 1739 1740 # Check whether we need to split stderr/stdout into configuration 1741 # specific files. 1742 if old_stderr.name != '<stderr>' and config.get('split_stderr'): 1743 if new_stderr: 1744 new_stderr.close() 1745 new_stderr = open("%s.%s" % (old_stderr.name, configPostfix), "w") 1746 sys.stderr = new_stderr 1747 if old_stdout.name != '<stdout>' and config.get('split_stdout'): 1748 if new_stdout: 1749 new_stdout.close() 1750 new_stdout = open("%s.%s" % (old_stdout.name, configPostfix), "w") 1751 sys.stdout = new_stdout 1752 1753 # If we specified a relocated directory to run the test suite, do 1754 # the extra housekeeping to copy the testdirs to a configStringified 1755 # directory and to update sys.path before invoking the test runner. 1756 # The purpose is to separate the configuration-specific directories 1757 # from each other. 1758 if rdir: 1759 from shutil import copytree, rmtree, ignore_patterns 1760 1761 newrdir = "%s.%s" % (rdir, configPostfix) 1762 1763 # Copy the tree to a new directory with postfix name configPostfix. 1764 if os.path.exists(newrdir): 1765 rmtree(newrdir) 1766 copytree(rdir, newrdir, ignore=ignore_patterns('*.pyc', '*.o', '*.d')) 1767 1768 # Update the LLDB_TEST environment variable to reflect new top 1769 # level test directory. 1770 # 1771 # See also lldbtest.TestBase.setUpClass(cls). 1772 if len(testdirs) == 1 and os.path.basename(testdirs[0]) == 'test': 1773 os.environ["LLDB_TEST"] = os.path.join(newrdir, 'test') 1774 else: 1775 os.environ["LLDB_TEST"] = newrdir 1776 1777 # And update the Python search paths for modules. 1778 sys.path = [x.replace(rdir, newrdir, 1) for x in old_sys_path] 1779 1780 # Output the configuration. 1781 if not parsable: 1782 sys.stderr.write("\nConfiguration: " + configString + "\n") 1783 1784 #print("sys.stderr name is", sys.stderr.name) 1785 #print("sys.stdout name is", sys.stdout.name) 1786 1787 # First, write out the number of collected test cases. 1788 if not parsable: 1789 sys.stderr.write(separator + "\n") 1790 sys.stderr.write("Collected %d test%s\n\n" 1791 % (suite.countTestCases(), 1792 suite.countTestCases() != 1 and "s" or "")) 1793 1794 class LLDBTestResult(unittest2.TextTestResult): 1795 """ 1796 Enforce a singleton pattern to allow introspection of test progress. 1797 1798 Overwrite addError(), addFailure(), and addExpectedFailure() methods 1799 to enable each test instance to track its failure/error status. It 1800 is used in the LLDB test framework to emit detailed trace messages 1801 to a log file for easier human inspection of test failures/errors. 1802 """ 1803 __singleton__ = None 1804 __ignore_singleton__ = False 1805 1806 @staticmethod 1807 def getTerminalSize(): 1808 import os 1809 env = os.environ 1810 def ioctl_GWINSZ(fd): 1811 try: 1812 import fcntl, termios, struct, os 1813 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, 1814 '1234')) 1815 except: 1816 return 1817 return cr 1818 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) 1819 if not cr: 1820 try: 1821 fd = os.open(os.ctermid(), os.O_RDONLY) 1822 cr = ioctl_GWINSZ(fd) 1823 os.close(fd) 1824 except: 1825 pass 1826 if not cr: 1827 cr = (env.get('LINES', 25), env.get('COLUMNS', 80)) 1828 return int(cr[1]), int(cr[0]) 1829 1830 def __init__(self, *args): 1831 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__: 1832 raise Exception("LLDBTestResult instantiated more than once") 1833 super(LLDBTestResult, self).__init__(*args) 1834 LLDBTestResult.__singleton__ = self 1835 # Now put this singleton into the lldb module namespace. 1836 lldb.test_result = self 1837 # Computes the format string for displaying the counter. 1838 global suite 1839 counterWidth = len(str(suite.countTestCases())) 1840 self.fmt = "%" + str(counterWidth) + "d: " 1841 self.indentation = ' ' * (counterWidth + 2) 1842 # This counts from 1 .. suite.countTestCases(). 1843 self.counter = 0 1844 (width, height) = LLDBTestResult.getTerminalSize() 1845 self.progressbar = None 1846 global progress_bar 1847 if width > 10 and not parsable and progress_bar: 1848 try: 1849 self.progressbar = progress.ProgressWithEvents(stdout=self.stream,start=0,end=suite.countTestCases(),width=width-10) 1850 except: 1851 self.progressbar = None 1852 self.results_formatter = results_formatter_object 1853 1854 def _config_string(self, test): 1855 compiler = getattr(test, "getCompiler", None) 1856 arch = getattr(test, "getArchitecture", None) 1857 return "%s-%s" % (compiler() if compiler else "", arch() if arch else "") 1858 1859 def _exc_info_to_string(self, err, test): 1860 """Overrides superclass TestResult's method in order to append 1861 our test config info string to the exception info string.""" 1862 if hasattr(test, "getArchitecture") and hasattr(test, "getCompiler"): 1863 return '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test), 1864 test.getArchitecture(), 1865 test.getCompiler()) 1866 else: 1867 return super(LLDBTestResult, self)._exc_info_to_string(err, test) 1868 1869 def getDescription(self, test): 1870 doc_first_line = test.shortDescription() 1871 if self.descriptions and doc_first_line: 1872 return '\n'.join((str(test), self.indentation + doc_first_line)) 1873 else: 1874 return str(test) 1875 1876 def getCategoriesForTest(self,test): 1877 if hasattr(test,"_testMethodName"): 1878 test_method = getattr(test,"_testMethodName") 1879 test_method = getattr(test,test_method) 1880 else: 1881 test_method = None 1882 if test_method != None and hasattr(test_method,"getCategories"): 1883 test_categories = test_method.getCategories(test) 1884 elif hasattr(test,"getCategories"): 1885 test_categories = test.getCategories() 1886 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"): 1887 test_categories = test.__self__.getCategories() 1888 else: 1889 test_categories = [] 1890 if test_categories == None: 1891 test_categories = [] 1892 return test_categories 1893 1894 def hardMarkAsSkipped(self,test): 1895 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True 1896 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" 1897 test.__class__.__unittest_skip__ = True 1898 test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" 1899 1900 def startTest(self, test): 1901 if shouldSkipBecauseOfCategories(self.getCategoriesForTest(test)): 1902 self.hardMarkAsSkipped(test) 1903 global setCrashInfoHook 1904 setCrashInfoHook("%s at %s" % (str(test),inspect.getfile(test.__class__))) 1905 self.counter += 1 1906 #if self.counter == 4: 1907 # import crashinfo 1908 # crashinfo.testCrashReporterDescription(None) 1909 test.test_number = self.counter 1910 if self.showAll: 1911 self.stream.write(self.fmt % self.counter) 1912 super(LLDBTestResult, self).startTest(test) 1913 if self.results_formatter: 1914 self.results_formatter.handle_event( 1915 EventBuilder.event_for_start(test)) 1916 1917 def addSuccess(self, test): 1918 global parsable 1919 super(LLDBTestResult, self).addSuccess(test) 1920 if parsable: 1921 self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1922 if self.results_formatter: 1923 self.results_formatter.handle_event( 1924 EventBuilder.event_for_success(test)) 1925 1926 def addError(self, test, err): 1927 global sdir_has_content 1928 global parsable 1929 sdir_has_content = True 1930 super(LLDBTestResult, self).addError(test, err) 1931 method = getattr(test, "markError", None) 1932 if method: 1933 method() 1934 if parsable: 1935 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1936 if self.results_formatter: 1937 self.results_formatter.handle_event( 1938 EventBuilder.event_for_error(test, err)) 1939 1940 def addCleanupError(self, test, err): 1941 global sdir_has_content 1942 global parsable 1943 sdir_has_content = True 1944 super(LLDBTestResult, self).addCleanupError(test, err) 1945 method = getattr(test, "markCleanupError", None) 1946 if method: 1947 method() 1948 if parsable: 1949 self.stream.write("CLEANUP ERROR: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1950 if self.results_formatter: 1951 self.results_formatter.handle_event( 1952 EventBuilder.event_for_cleanup_error( 1953 test, err)) 1954 1955 def addFailure(self, test, err): 1956 global sdir_has_content 1957 global failuresPerCategory 1958 global parsable 1959 sdir_has_content = True 1960 super(LLDBTestResult, self).addFailure(test, err) 1961 method = getattr(test, "markFailure", None) 1962 if method: 1963 method() 1964 if parsable: 1965 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1966 if useCategories: 1967 test_categories = self.getCategoriesForTest(test) 1968 for category in test_categories: 1969 if category in failuresPerCategory: 1970 failuresPerCategory[category] = failuresPerCategory[category] + 1 1971 else: 1972 failuresPerCategory[category] = 1 1973 if self.results_formatter: 1974 self.results_formatter.handle_event( 1975 EventBuilder.event_for_failure(test, err)) 1976 1977 1978 def addExpectedFailure(self, test, err, bugnumber): 1979 global sdir_has_content 1980 global parsable 1981 sdir_has_content = True 1982 super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber) 1983 method = getattr(test, "markExpectedFailure", None) 1984 if method: 1985 method(err, bugnumber) 1986 if parsable: 1987 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 1988 if self.results_formatter: 1989 self.results_formatter.handle_event( 1990 EventBuilder.event_for_expected_failure( 1991 test, err, bugnumber)) 1992 1993 def addSkip(self, test, reason): 1994 global sdir_has_content 1995 global parsable 1996 sdir_has_content = True 1997 super(LLDBTestResult, self).addSkip(test, reason) 1998 method = getattr(test, "markSkippedTest", None) 1999 if method: 2000 method() 2001 if parsable: 2002 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason)) 2003 if self.results_formatter: 2004 self.results_formatter.handle_event( 2005 EventBuilder.event_for_skip(test, reason)) 2006 2007 def addUnexpectedSuccess(self, test, bugnumber): 2008 global sdir_has_content 2009 global parsable 2010 sdir_has_content = True 2011 super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber) 2012 method = getattr(test, "markUnexpectedSuccess", None) 2013 if method: 2014 method(bugnumber) 2015 if parsable: 2016 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 2017 if self.results_formatter: 2018 self.results_formatter.handle_event( 2019 EventBuilder.event_for_unexpected_success( 2020 test, bugnumber)) 2021 2022 2023 if parsable: 2024 v = 0 2025 elif progress_bar: 2026 v = 1 2027 else: 2028 v = verbose 2029 2030 # Invoke the test runner. 2031 if count == 1: 2032 result = unittest2.TextTestRunner(stream=sys.stderr, 2033 verbosity=v, 2034 failfast=failfast, 2035 resultclass=LLDBTestResult).run(suite) 2036 else: 2037 # We are invoking the same test suite more than once. In this case, 2038 # mark __ignore_singleton__ flag as True so the signleton pattern is 2039 # not enforced. 2040 LLDBTestResult.__ignore_singleton__ = True 2041 for i in range(count): 2042 2043 result = unittest2.TextTestRunner(stream=sys.stderr, 2044 verbosity=v, 2045 failfast=failfast, 2046 resultclass=LLDBTestResult).run(suite) 2047 2048 failed = failed or not result.wasSuccessful() 2049 2050 if sdir_has_content and not parsable: 2051 sys.stderr.write("Session logs for test failures/errors/unexpected successes" 2052 " can be found in directory '%s'\n" % sdir_name) 2053 2054 if useCategories and len(failuresPerCategory) > 0: 2055 sys.stderr.write("Failures per category:\n") 2056 for category in failuresPerCategory: 2057 sys.stderr.write("%s - %d\n" % (category,failuresPerCategory[category])) 2058 2059 os.chdir(where_to_save_session) 2060 fname = os.path.join(sdir_name, "TestFinished-%d" % os.getpid()) 2061 with open(fname, "w") as f: 2062 print("Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S"), file=f) 2063 2064 # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined. 2065 # This should not be necessary now. 2066 if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ): 2067 print("Terminating Test suite...") 2068 subprocess.Popen(["/bin/sh", "-c", "kill %s; exit 0" % (os.getpid())]) 2069 2070 # Exiting. 2071 exitTestSuite(failed) 2072 2073if __name__ == "__main__": 2074 print(__file__ + " is for use as a module only. It should not be run as a standalone script.") 2075 sys.exit(-1) 2076