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