1""" 2LLDB module which provides the abstract base class of lldb test case. 3 4The concrete subclass can override lldbtest.TestBase in order to inherit the 5common behavior for unitest.TestCase.setUp/tearDown implemented in this file. 6 7./dotest.py provides a test driver which sets up the environment to run the 8entire of part of the test suite . Example: 9 10# Exercises the test suite in the types directory.... 11/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types 12... 13 14Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42' 15Command invoked: python ./dotest.py -A x86_64 types 16compilers=['clang'] 17 18Configuration: arch=x86_64 compiler=clang 19---------------------------------------------------------------------- 20Collected 72 tests 21 22........................................................................ 23---------------------------------------------------------------------- 24Ran 72 tests in 135.468s 25 26OK 27$ 28""" 29 30from __future__ import absolute_import 31from __future__ import print_function 32 33# System modules 34import abc 35from distutils.version import LooseVersion 36from functools import wraps 37import gc 38import glob 39import io 40import os.path 41import re 42import shutil 43import signal 44from subprocess import * 45import sys 46import time 47import traceback 48 49# Third-party modules 50import unittest2 51from six import add_metaclass 52from six import StringIO as SixStringIO 53import six 54 55# LLDB modules 56import lldb 57from . import configuration 58from . import decorators 59from . import lldbplatformutil 60from . import lldbtest_config 61from . import lldbutil 62from . import test_categories 63from lldbsuite.support import encoded_file 64from lldbsuite.support import funcutils 65from lldbsuite.support import seven 66from lldbsuite.test.builders import get_builder 67from lldbsuite.test_event import build_exception 68 69# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables 70# LLDB_COMMAND_TRACE is set from '-t' option. 71 72# By default, traceAlways is False. 73if "LLDB_COMMAND_TRACE" in os.environ and os.environ[ 74 "LLDB_COMMAND_TRACE"] == "YES": 75 traceAlways = True 76else: 77 traceAlways = False 78 79# By default, doCleanup is True. 80if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"] == "NO": 81 doCleanup = False 82else: 83 doCleanup = True 84 85 86# 87# Some commonly used assert messages. 88# 89 90COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" 91 92CURRENT_EXECUTABLE_SET = "Current executable set successfully" 93 94PROCESS_IS_VALID = "Process is valid" 95 96PROCESS_KILLED = "Process is killed successfully" 97 98PROCESS_EXITED = "Process exited successfully" 99 100PROCESS_STOPPED = "Process status should be stopped" 101 102RUN_SUCCEEDED = "Process is launched successfully" 103 104RUN_COMPLETED = "Process exited successfully" 105 106BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" 107 108BREAKPOINT_CREATED = "Breakpoint created successfully" 109 110BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct" 111 112BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" 113 114BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit count = 1" 115 116BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit count = 2" 117 118BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit count = 3" 119 120MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable." 121 122OBJECT_PRINTED_CORRECTLY = "Object printed correctly" 123 124SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly" 125 126STEP_IN_SUCCEEDED = "Thread step-in succeeded" 127 128STEP_OUT_SUCCEEDED = "Thread step-out succeeded" 129 130STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception" 131 132STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion" 133 134STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint" 135 136STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % ( 137 STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'") 138 139STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition" 140 141STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count" 142 143STOPPED_DUE_TO_BREAKPOINT_JITTED_CONDITION = "Stopped due to breakpoint jitted condition" 144 145STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" 146 147STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" 148 149STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint" 150 151DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" 152 153VALID_BREAKPOINT = "Got a valid breakpoint" 154 155VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location" 156 157VALID_COMMAND_INTERPRETER = "Got a valid command interpreter" 158 159VALID_FILESPEC = "Got a valid filespec" 160 161VALID_MODULE = "Got a valid module" 162 163VALID_PROCESS = "Got a valid process" 164 165VALID_SYMBOL = "Got a valid symbol" 166 167VALID_TARGET = "Got a valid target" 168 169VALID_PLATFORM = "Got a valid platform" 170 171VALID_TYPE = "Got a valid type" 172 173VALID_VARIABLE = "Got a valid variable" 174 175VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" 176 177WATCHPOINT_CREATED = "Watchpoint created successfully" 178 179 180def CMD_MSG(str): 181 '''A generic "Command '%s' did not return successfully" message generator.''' 182 return "Command '%s' did not return successfully" % str 183 184 185def COMPLETION_MSG(str_before, str_after, completions): 186 '''A generic assertion failed message generator for the completion mechanism.''' 187 return ("'%s' successfully completes to '%s', but completions were:\n%s" 188 % (str_before, str_after, "\n".join(completions))) 189 190 191def EXP_MSG(str, actual, exe): 192 '''A generic "'%s' returned unexpected result" message generator if exe. 193 Otherwise, it generates "'%s' does not match expected result" message.''' 194 195 return "'%s' %s result, got '%s'" % ( 196 str, 'returned unexpected' if exe else 'does not match expected', actual.strip()) 197 198 199def SETTING_MSG(setting): 200 '''A generic "Value of setting '%s' is not correct" message generator.''' 201 return "Value of setting '%s' is not correct" % setting 202 203 204def line_number(filename, string_to_match): 205 """Helper function to return the line number of the first matched string.""" 206 with io.open(filename, mode='r', encoding="utf-8") as f: 207 for i, line in enumerate(f): 208 if line.find(string_to_match) != -1: 209 # Found our match. 210 return i + 1 211 raise Exception( 212 "Unable to find '%s' within file %s" % 213 (string_to_match, filename)) 214 215def get_line(filename, line_number): 216 """Return the text of the line at the 1-based line number.""" 217 with io.open(filename, mode='r', encoding="utf-8") as f: 218 return f.readlines()[line_number - 1] 219 220def pointer_size(): 221 """Return the pointer size of the host system.""" 222 import ctypes 223 a_pointer = ctypes.c_void_p(0xffff) 224 return 8 * ctypes.sizeof(a_pointer) 225 226 227def is_exe(fpath): 228 """Returns true if fpath is an executable.""" 229 if fpath == None: 230 return False 231 if sys.platform == 'win32': 232 if not fpath.endswith(".exe"): 233 fpath += ".exe" 234 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) 235 236 237def which(program): 238 """Returns the full path to a program; None otherwise.""" 239 fpath, fname = os.path.split(program) 240 if fpath: 241 if is_exe(program): 242 return program 243 else: 244 for path in os.environ["PATH"].split(os.pathsep): 245 exe_file = os.path.join(path, program) 246 if is_exe(exe_file): 247 return exe_file 248 return None 249 250class ValueCheck: 251 def __init__(self, name=None, value=None, type=None, summary=None, 252 children=None): 253 """ 254 :param name: The name that the SBValue should have. None if the summary 255 should not be checked. 256 :param summary: The summary that the SBValue should have. None if the 257 summary should not be checked. 258 :param value: The value that the SBValue should have. None if the value 259 should not be checked. 260 :param type: The type that the SBValue result should have. None if the 261 type should not be checked. 262 :param children: A list of ValueChecks that need to match the children 263 of this SBValue. None if children shouldn't be checked. 264 The order of checks is the order of the checks in the 265 list. The number of checks has to match the number of 266 children. 267 """ 268 self.expect_name = name 269 self.expect_value = value 270 self.expect_type = type 271 self.expect_summary = summary 272 self.children = children 273 274 def check_value(self, test_base, val, error_msg=None): 275 """ 276 Checks that the given value matches the currently set properties 277 of this ValueCheck. If a match failed, the given TestBase will 278 be used to emit an error. A custom error message can be specified 279 that will be used to describe failed check for this SBValue (but 280 not errors in the child values). 281 """ 282 283 this_error_msg = error_msg if error_msg else "" 284 this_error_msg += "\nChecking SBValue: " + str(val) 285 286 test_base.assertSuccess(val.GetError()) 287 288 if self.expect_name: 289 test_base.assertEqual(self.expect_name, val.GetName(), 290 this_error_msg) 291 if self.expect_value: 292 test_base.assertEqual(self.expect_value, val.GetValue(), 293 this_error_msg) 294 if self.expect_type: 295 test_base.assertEqual(self.expect_type, val.GetDisplayTypeName(), 296 this_error_msg) 297 if self.expect_summary: 298 test_base.assertEqual(self.expect_summary, val.GetSummary(), 299 this_error_msg) 300 if self.children is not None: 301 self.check_value_children(test_base, val, error_msg) 302 303 def check_value_children(self, test_base, val, error_msg=None): 304 """ 305 Checks that the children of a SBValue match a certain structure and 306 have certain properties. 307 308 :param test_base: The current test's TestBase object. 309 :param val: The SBValue to check. 310 """ 311 312 this_error_msg = error_msg if error_msg else "" 313 this_error_msg += "\nChecking SBValue: " + str(val) 314 315 test_base.assertEqual(len(self.children), val.GetNumChildren(), this_error_msg) 316 317 for i in range(0, val.GetNumChildren()): 318 expected_child = self.children[i] 319 actual_child = val.GetChildAtIndex(i) 320 child_error = "Checking child with index " + str(i) + ":\n" + error_msg 321 expected_child.check_value(test_base, actual_child, child_error) 322 323class recording(SixStringIO): 324 """ 325 A nice little context manager for recording the debugger interactions into 326 our session object. If trace flag is ON, it also emits the interactions 327 into the stderr. 328 """ 329 330 def __init__(self, test, trace): 331 """Create a SixStringIO instance; record the session obj and trace flag.""" 332 SixStringIO.__init__(self) 333 # The test might not have undergone the 'setUp(self)' phase yet, so that 334 # the attribute 'session' might not even exist yet. 335 self.session = getattr(test, "session", None) if test else None 336 self.trace = trace 337 338 def __enter__(self): 339 """ 340 Context management protocol on entry to the body of the with statement. 341 Just return the SixStringIO object. 342 """ 343 return self 344 345 def __exit__(self, type, value, tb): 346 """ 347 Context management protocol on exit from the body of the with statement. 348 If trace is ON, it emits the recordings into stderr. Always add the 349 recordings to our session object. And close the SixStringIO object, too. 350 """ 351 if self.trace: 352 print(self.getvalue(), file=sys.stderr) 353 if self.session: 354 print(self.getvalue(), file=self.session) 355 self.close() 356 357 358@add_metaclass(abc.ABCMeta) 359class _BaseProcess(object): 360 361 @abc.abstractproperty 362 def pid(self): 363 """Returns process PID if has been launched already.""" 364 365 @abc.abstractmethod 366 def launch(self, executable, args, extra_env): 367 """Launches new process with given executable and args.""" 368 369 @abc.abstractmethod 370 def terminate(self): 371 """Terminates previously launched process..""" 372 373 374class _LocalProcess(_BaseProcess): 375 376 def __init__(self, trace_on): 377 self._proc = None 378 self._trace_on = trace_on 379 self._delayafterterminate = 0.1 380 381 @property 382 def pid(self): 383 return self._proc.pid 384 385 def launch(self, executable, args, extra_env): 386 env=None 387 if extra_env: 388 env = dict(os.environ) 389 env.update([kv.split("=", 1) for kv in extra_env]) 390 391 self._proc = Popen( 392 [executable] + args, 393 stdout=open( 394 os.devnull) if not self._trace_on else None, 395 stdin=PIPE, 396 env=env) 397 398 def terminate(self): 399 if self._proc.poll() is None: 400 # Terminate _proc like it does the pexpect 401 signals_to_try = [ 402 sig for sig in [ 403 'SIGHUP', 404 'SIGCONT', 405 'SIGINT'] if sig in dir(signal)] 406 for sig in signals_to_try: 407 try: 408 self._proc.send_signal(getattr(signal, sig)) 409 time.sleep(self._delayafterterminate) 410 if self._proc.poll() is not None: 411 return 412 except ValueError: 413 pass # Windows says SIGINT is not a valid signal to send 414 self._proc.terminate() 415 time.sleep(self._delayafterterminate) 416 if self._proc.poll() is not None: 417 return 418 self._proc.kill() 419 time.sleep(self._delayafterterminate) 420 421 def poll(self): 422 return self._proc.poll() 423 424 def wait(self, timeout=None): 425 return self._proc.wait(timeout) 426 427 428class _RemoteProcess(_BaseProcess): 429 430 def __init__(self, install_remote): 431 self._pid = None 432 self._install_remote = install_remote 433 434 @property 435 def pid(self): 436 return self._pid 437 438 def launch(self, executable, args, extra_env): 439 if self._install_remote: 440 src_path = executable 441 dst_path = lldbutil.join_remote_paths( 442 lldb.remote_platform.GetWorkingDirectory(), os.path.basename(executable)) 443 444 dst_file_spec = lldb.SBFileSpec(dst_path, False) 445 err = lldb.remote_platform.Install( 446 lldb.SBFileSpec(src_path, True), dst_file_spec) 447 if err.Fail(): 448 raise Exception( 449 "remote_platform.Install('%s', '%s') failed: %s" % 450 (src_path, dst_path, err)) 451 else: 452 dst_path = executable 453 dst_file_spec = lldb.SBFileSpec(executable, False) 454 455 launch_info = lldb.SBLaunchInfo(args) 456 launch_info.SetExecutableFile(dst_file_spec, True) 457 launch_info.SetWorkingDirectory( 458 lldb.remote_platform.GetWorkingDirectory()) 459 460 # Redirect stdout and stderr to /dev/null 461 launch_info.AddSuppressFileAction(1, False, True) 462 launch_info.AddSuppressFileAction(2, False, True) 463 464 if extra_env: 465 launch_info.SetEnvironmentEntries(extra_env, True) 466 467 err = lldb.remote_platform.Launch(launch_info) 468 if err.Fail(): 469 raise Exception( 470 "remote_platform.Launch('%s', '%s') failed: %s" % 471 (dst_path, args, err)) 472 self._pid = launch_info.GetProcessID() 473 474 def terminate(self): 475 lldb.remote_platform.Kill(self._pid) 476 477def getsource_if_available(obj): 478 """ 479 Return the text of the source code for an object if available. Otherwise, 480 a print representation is returned. 481 """ 482 import inspect 483 try: 484 return inspect.getsource(obj) 485 except: 486 return repr(obj) 487 488 489def builder_module(): 490 return get_builder(sys.platform) 491 492 493class Base(unittest2.TestCase): 494 """ 495 Abstract base for performing lldb (see TestBase) or other generic tests (see 496 BenchBase for one example). lldbtest.Base works with the test driver to 497 accomplish things. 498 499 """ 500 501 # The concrete subclass should override this attribute. 502 mydir = None 503 504 # Keep track of the old current working directory. 505 oldcwd = None 506 507 @staticmethod 508 def compute_mydir(test_file): 509 '''Subclasses should call this function to correctly calculate the 510 required "mydir" attribute as follows: 511 512 mydir = TestBase.compute_mydir(__file__) 513 ''' 514 # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir 515 lldb_test_src = configuration.test_src_root 516 if not test_file.startswith(lldb_test_src): 517 raise Exception( 518 "Test file '%s' must reside within lldb_test_src " 519 "(which is '%s')." % (test_file, lldb_test_src)) 520 return os.path.dirname(os.path.relpath(test_file, start=lldb_test_src)) 521 522 def TraceOn(self): 523 """Returns True if we are in trace mode (tracing detailed test execution).""" 524 return traceAlways 525 526 def trace(self, *args,**kwargs): 527 with recording(self, self.TraceOn()) as sbuf: 528 print(*args, file=sbuf, **kwargs) 529 530 @classmethod 531 def setUpClass(cls): 532 """ 533 Python unittest framework class setup fixture. 534 Do current directory manipulation. 535 """ 536 # Fail fast if 'mydir' attribute is not overridden. 537 if not cls.mydir: 538 cls.mydir = Base.compute_mydir(sys.modules[cls.__module__].__file__) 539 if not cls.mydir: 540 raise Exception("Subclasses must override the 'mydir' attribute.") 541 542 # Save old working directory. 543 cls.oldcwd = os.getcwd() 544 545 full_dir = os.path.join(configuration.test_src_root, cls.mydir) 546 if traceAlways: 547 print("Change dir to:", full_dir, file=sys.stderr) 548 os.chdir(full_dir) 549 lldb.SBReproducer.SetWorkingDirectory(full_dir) 550 551 # Set platform context. 552 cls.platformContext = lldbplatformutil.createPlatformContext() 553 554 @classmethod 555 def tearDownClass(cls): 556 """ 557 Python unittest framework class teardown fixture. 558 Do class-wide cleanup. 559 """ 560 561 if doCleanup: 562 # First, let's do the platform-specific cleanup. 563 module = builder_module() 564 module.cleanup() 565 566 # Subclass might have specific cleanup function defined. 567 if getattr(cls, "classCleanup", None): 568 if traceAlways: 569 print( 570 "Call class-specific cleanup function for class:", 571 cls, 572 file=sys.stderr) 573 try: 574 cls.classCleanup() 575 except: 576 exc_type, exc_value, exc_tb = sys.exc_info() 577 traceback.print_exception(exc_type, exc_value, exc_tb) 578 579 # Restore old working directory. 580 if traceAlways: 581 print("Restore dir to:", cls.oldcwd, file=sys.stderr) 582 os.chdir(cls.oldcwd) 583 584 def enableLogChannelsForCurrentTest(self): 585 if len(lldbtest_config.channels) == 0: 586 return 587 588 # if debug channels are specified in lldbtest_config.channels, 589 # create a new set of log files for every test 590 log_basename = self.getLogBasenameForCurrentTest() 591 592 # confirm that the file is writeable 593 host_log_path = "{}-host.log".format(log_basename) 594 open(host_log_path, 'w').close() 595 self.log_files.append(host_log_path) 596 597 log_enable = "log enable -Tpn -f {} ".format(host_log_path) 598 for channel_with_categories in lldbtest_config.channels: 599 channel_then_categories = channel_with_categories.split(' ', 1) 600 channel = channel_then_categories[0] 601 if len(channel_then_categories) > 1: 602 categories = channel_then_categories[1] 603 else: 604 categories = "default" 605 606 if channel == "gdb-remote" and lldb.remote_platform is None: 607 # communicate gdb-remote categories to debugserver 608 os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories 609 610 self.ci.HandleCommand( 611 log_enable + channel_with_categories, self.res) 612 if not self.res.Succeeded(): 613 raise Exception( 614 'log enable failed (check LLDB_LOG_OPTION env variable)') 615 616 # Communicate log path name to debugserver & lldb-server 617 # For remote debugging, these variables need to be set when starting the platform 618 # instance. 619 if lldb.remote_platform is None: 620 server_log_path = "{}-server.log".format(log_basename) 621 open(server_log_path, 'w').close() 622 self.log_files.append(server_log_path) 623 os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path 624 625 # Communicate channels to lldb-server 626 os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join( 627 lldbtest_config.channels) 628 629 self.addTearDownHook(self.disableLogChannelsForCurrentTest) 630 631 def disableLogChannelsForCurrentTest(self): 632 # close all log files that we opened 633 for channel_and_categories in lldbtest_config.channels: 634 # channel format - <channel-name> [<category0> [<category1> ...]] 635 channel = channel_and_categories.split(' ', 1)[0] 636 self.ci.HandleCommand("log disable " + channel, self.res) 637 if not self.res.Succeeded(): 638 raise Exception( 639 'log disable failed (check LLDB_LOG_OPTION env variable)') 640 641 # Retrieve the server log (if any) from the remote system. It is assumed the server log 642 # is writing to the "server.log" file in the current test directory. This can be 643 # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote 644 # platform. 645 if lldb.remote_platform: 646 server_log_path = self.getLogBasenameForCurrentTest() + "-server.log" 647 if lldb.remote_platform.Get( 648 lldb.SBFileSpec("server.log"), 649 lldb.SBFileSpec(server_log_path)).Success(): 650 self.log_files.append(server_log_path) 651 652 def setPlatformWorkingDir(self): 653 if not lldb.remote_platform or not configuration.lldb_platform_working_dir: 654 return 655 656 components = self.mydir.split(os.path.sep) + [str(self.test_number), self.getBuildDirBasename()] 657 remote_test_dir = configuration.lldb_platform_working_dir 658 for c in components: 659 remote_test_dir = lldbutil.join_remote_paths(remote_test_dir, c) 660 error = lldb.remote_platform.MakeDirectory( 661 remote_test_dir, 448) # 448 = 0o700 662 if error.Fail(): 663 raise Exception("making remote directory '%s': %s" % ( 664 remote_test_dir, error)) 665 666 lldb.remote_platform.SetWorkingDirectory(remote_test_dir) 667 668 # This function removes all files from the current working directory while leaving 669 # the directories in place. The cleanup is required to reduce the disk space required 670 # by the test suite while leaving the directories untouched is neccessary because 671 # sub-directories might belong to an other test 672 def clean_working_directory(): 673 # TODO: Make it working on Windows when we need it for remote debugging support 674 # TODO: Replace the heuristic to remove the files with a logic what collects the 675 # list of files we have to remove during test runs. 676 shell_cmd = lldb.SBPlatformShellCommand( 677 "rm %s/*" % remote_test_dir) 678 lldb.remote_platform.Run(shell_cmd) 679 self.addTearDownHook(clean_working_directory) 680 681 def getSourceDir(self): 682 """Return the full path to the current test.""" 683 return os.path.join(configuration.test_src_root, self.mydir) 684 685 def getBuildDirBasename(self): 686 return self.__class__.__module__ + "." + self.testMethodName 687 688 def getBuildDir(self): 689 """Return the full path to the current test.""" 690 return os.path.join(configuration.test_build_dir, self.mydir, 691 self.getBuildDirBasename()) 692 693 def makeBuildDir(self): 694 """Create the test-specific working directory, deleting any previous 695 contents.""" 696 bdir = self.getBuildDir() 697 if os.path.isdir(bdir): 698 shutil.rmtree(bdir) 699 lldbutil.mkdir_p(bdir) 700 701 def getBuildArtifact(self, name="a.out"): 702 """Return absolute path to an artifact in the test's build directory.""" 703 return os.path.join(self.getBuildDir(), name) 704 705 def getSourcePath(self, name): 706 """Return absolute path to a file in the test's source directory.""" 707 return os.path.join(self.getSourceDir(), name) 708 709 @classmethod 710 def setUpCommands(cls): 711 commands = [ 712 # First of all, clear all settings to have clean state of global properties. 713 "settings clear -all", 714 715 # Disable Spotlight lookup. The testsuite creates 716 # different binaries with the same UUID, because they only 717 # differ in the debug info, which is not being hashed. 718 "settings set symbols.enable-external-lookup false", 719 720 # Inherit the TCC permissions from the inferior's parent. 721 "settings set target.inherit-tcc true", 722 723 # Kill rather than detach from the inferior if something goes wrong. 724 "settings set target.detach-on-error false", 725 726 # Disable fix-its by default so that incorrect expressions in tests don't 727 # pass just because Clang thinks it has a fix-it. 728 "settings set target.auto-apply-fixits false", 729 730 # Testsuite runs in parallel and the host can have also other load. 731 "settings set plugin.process.gdb-remote.packet-timeout 60", 732 733 'settings set symbols.clang-modules-cache-path "{}"'.format( 734 configuration.lldb_module_cache_dir), 735 "settings set use-color false", 736 ] 737 738 # Set any user-overridden settings. 739 for setting, value in configuration.settings: 740 commands.append('setting set %s %s'%(setting, value)) 741 742 # Make sure that a sanitizer LLDB's environment doesn't get passed on. 743 if cls.platformContext and cls.platformContext.shlib_environment_var in os.environ: 744 commands.append('settings set target.env-vars {}='.format( 745 cls.platformContext.shlib_environment_var)) 746 747 # Set environment variables for the inferior. 748 if lldbtest_config.inferior_env: 749 commands.append('settings set target.env-vars {}'.format( 750 lldbtest_config.inferior_env)) 751 return commands 752 753 def setUp(self): 754 """Fixture for unittest test case setup. 755 756 It works with the test driver to conditionally skip tests and does other 757 initializations.""" 758 #import traceback 759 # traceback.print_stack() 760 761 if "LIBCXX_PATH" in os.environ: 762 self.libcxxPath = os.environ["LIBCXX_PATH"] 763 else: 764 self.libcxxPath = None 765 766 if "LLDBVSCODE_EXEC" in os.environ: 767 self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"] 768 else: 769 self.lldbVSCodeExec = None 770 771 self.lldbOption = " ".join( 772 "-o '" + s + "'" for s in self.setUpCommands()) 773 774 # If we spawn an lldb process for test (via pexpect), do not load the 775 # init file unless told otherwise. 776 if os.environ.get("NO_LLDBINIT") != "NO": 777 self.lldbOption += " --no-lldbinit" 778 779 # Assign the test method name to self.testMethodName. 780 # 781 # For an example of the use of this attribute, look at test/types dir. 782 # There are a bunch of test cases under test/types and we don't want the 783 # module cacheing subsystem to be confused with executable name "a.out" 784 # used for all the test cases. 785 self.testMethodName = self._testMethodName 786 787 # This is for the case of directly spawning 'lldb'/'gdb' and interacting 788 # with it using pexpect. 789 self.child = None 790 self.child_prompt = "(lldb) " 791 # If the child is interacting with the embedded script interpreter, 792 # there are two exits required during tear down, first to quit the 793 # embedded script interpreter and second to quit the lldb command 794 # interpreter. 795 self.child_in_script_interpreter = False 796 797 # These are for customized teardown cleanup. 798 self.dict = None 799 self.doTearDownCleanup = False 800 # And in rare cases where there are multiple teardown cleanups. 801 self.dicts = [] 802 self.doTearDownCleanups = False 803 804 # List of spawned subproces.Popen objects 805 self.subprocesses = [] 806 807 # List of log files produced by the current test. 808 self.log_files = [] 809 810 # Create the build directory. 811 # The logs are stored in the build directory, so we have to create it 812 # before creating the first log file. 813 self.makeBuildDir() 814 815 session_file = self.getLogBasenameForCurrentTest()+".log" 816 self.log_files.append(session_file) 817 818 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered. 819 self.session = encoded_file.open(session_file, "utf-8", mode="w") 820 821 # Optimistically set __errored__, __failed__, __expected__ to False 822 # initially. If the test errored/failed, the session info 823 # (self.session) is then dumped into a session specific file for 824 # diagnosis. 825 self.__cleanup_errored__ = False 826 self.__errored__ = False 827 self.__failed__ = False 828 self.__expected__ = False 829 # We are also interested in unexpected success. 830 self.__unexpected__ = False 831 # And skipped tests. 832 self.__skipped__ = False 833 834 # See addTearDownHook(self, hook) which allows the client to add a hook 835 # function to be run during tearDown() time. 836 self.hooks = [] 837 838 # See HideStdout(self). 839 self.sys_stdout_hidden = False 840 841 if self.platformContext: 842 # set environment variable names for finding shared libraries 843 self.dylibPath = self.platformContext.shlib_environment_var 844 845 # Create the debugger instance. 846 self.dbg = lldb.SBDebugger.Create() 847 # Copy selected platform from a global instance if it exists. 848 if lldb.selected_platform is not None: 849 self.dbg.SetSelectedPlatform(lldb.selected_platform) 850 851 if not self.dbg: 852 raise Exception('Invalid debugger instance') 853 854 # Retrieve the associated command interpreter instance. 855 self.ci = self.dbg.GetCommandInterpreter() 856 if not self.ci: 857 raise Exception('Could not get the command interpreter') 858 859 # And the result object. 860 self.res = lldb.SBCommandReturnObject() 861 862 self.setPlatformWorkingDir() 863 self.enableLogChannelsForCurrentTest() 864 865 self.lib_lldb = None 866 self.framework_dir = None 867 self.darwinWithFramework = False 868 869 if sys.platform.startswith("darwin") and configuration.lldb_framework_path: 870 framework = configuration.lldb_framework_path 871 lib = os.path.join(framework, 'LLDB') 872 if os.path.exists(lib): 873 self.framework_dir = os.path.dirname(framework) 874 self.lib_lldb = lib 875 self.darwinWithFramework = self.platformIsDarwin() 876 877 def setAsync(self, value): 878 """ Sets async mode to True/False and ensures it is reset after the testcase completes.""" 879 old_async = self.dbg.GetAsync() 880 self.dbg.SetAsync(value) 881 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async)) 882 883 def cleanupSubprocesses(self): 884 # Terminate subprocesses in reverse order from how they were created. 885 for p in reversed(self.subprocesses): 886 p.terminate() 887 del p 888 del self.subprocesses[:] 889 890 def spawnSubprocess(self, executable, args=[], extra_env=None, install_remote=True): 891 """ Creates a subprocess.Popen object with the specified executable and arguments, 892 saves it in self.subprocesses, and returns the object. 893 """ 894 proc = _RemoteProcess( 895 install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn()) 896 proc.launch(executable, args, extra_env=extra_env) 897 self.subprocesses.append(proc) 898 return proc 899 900 def HideStdout(self): 901 """Hide output to stdout from the user. 902 903 During test execution, there might be cases where we don't want to show the 904 standard output to the user. For example, 905 906 self.runCmd(r'''sc print("\n\n\tHello!\n")''') 907 908 tests whether command abbreviation for 'script' works or not. There is no 909 need to show the 'Hello' output to the user as long as the 'script' command 910 succeeds and we are not in TraceOn() mode (see the '-t' option). 911 912 In this case, the test method calls self.HideStdout(self) to redirect the 913 sys.stdout to a null device, and restores the sys.stdout upon teardown. 914 915 Note that you should only call this method at most once during a test case 916 execution. Any subsequent call has no effect at all.""" 917 if self.sys_stdout_hidden: 918 return 919 920 self.sys_stdout_hidden = True 921 old_stdout = sys.stdout 922 sys.stdout = open(os.devnull, 'w') 923 924 def restore_stdout(): 925 sys.stdout = old_stdout 926 self.addTearDownHook(restore_stdout) 927 928 # ======================================================================= 929 # Methods for customized teardown cleanups as well as execution of hooks. 930 # ======================================================================= 931 932 def setTearDownCleanup(self, dictionary=None): 933 """Register a cleanup action at tearDown() time with a dictionary""" 934 self.dict = dictionary 935 self.doTearDownCleanup = True 936 937 def addTearDownCleanup(self, dictionary): 938 """Add a cleanup action at tearDown() time with a dictionary""" 939 self.dicts.append(dictionary) 940 self.doTearDownCleanups = True 941 942 def addTearDownHook(self, hook): 943 """ 944 Add a function to be run during tearDown() time. 945 946 Hooks are executed in a first come first serve manner. 947 """ 948 if six.callable(hook): 949 with recording(self, traceAlways) as sbuf: 950 print( 951 "Adding tearDown hook:", 952 getsource_if_available(hook), 953 file=sbuf) 954 self.hooks.append(hook) 955 956 return self 957 958 def deletePexpectChild(self): 959 # This is for the case of directly spawning 'lldb' and interacting with it 960 # using pexpect. 961 if self.child and self.child.isalive(): 962 import pexpect 963 with recording(self, traceAlways) as sbuf: 964 print("tearing down the child process....", file=sbuf) 965 try: 966 if self.child_in_script_interpreter: 967 self.child.sendline('quit()') 968 self.child.expect_exact(self.child_prompt) 969 self.child.sendline( 970 'settings set interpreter.prompt-on-quit false') 971 self.child.sendline('quit') 972 self.child.expect(pexpect.EOF) 973 except (ValueError, pexpect.ExceptionPexpect): 974 # child is already terminated 975 pass 976 except OSError as exception: 977 import errno 978 if exception.errno != errno.EIO: 979 # unexpected error 980 raise 981 # child is already terminated 982 finally: 983 # Give it one final blow to make sure the child is terminated. 984 self.child.close() 985 986 def tearDown(self): 987 """Fixture for unittest test case teardown.""" 988 self.deletePexpectChild() 989 990 # Check and run any hook functions. 991 for hook in reversed(self.hooks): 992 with recording(self, traceAlways) as sbuf: 993 print( 994 "Executing tearDown hook:", 995 getsource_if_available(hook), 996 file=sbuf) 997 if funcutils.requires_self(hook): 998 hook(self) 999 else: 1000 hook() # try the plain call and hope it works 1001 1002 del self.hooks 1003 1004 # Perform registered teardown cleanup. 1005 if doCleanup and self.doTearDownCleanup: 1006 self.cleanup(dictionary=self.dict) 1007 1008 # In rare cases where there are multiple teardown cleanups added. 1009 if doCleanup and self.doTearDownCleanups: 1010 if self.dicts: 1011 for dict in reversed(self.dicts): 1012 self.cleanup(dictionary=dict) 1013 1014 # Remove subprocesses created by the test. 1015 self.cleanupSubprocesses() 1016 1017 # This must be the last statement, otherwise teardown hooks or other 1018 # lines might depend on this still being active. 1019 lldb.SBDebugger.Destroy(self.dbg) 1020 del self.dbg 1021 1022 # All modules should be orphaned now so that they can be cleared from 1023 # the shared module cache. 1024 lldb.SBModule.GarbageCollectAllocatedModules() 1025 1026 # Assert that the global module cache is empty. 1027 self.assertEqual(lldb.SBModule.GetNumberAllocatedModules(), 0) 1028 1029 1030 # ========================================================= 1031 # Various callbacks to allow introspection of test progress 1032 # ========================================================= 1033 1034 def markError(self): 1035 """Callback invoked when an error (unexpected exception) errored.""" 1036 self.__errored__ = True 1037 with recording(self, False) as sbuf: 1038 # False because there's no need to write "ERROR" to the stderr twice. 1039 # Once by the Python unittest framework, and a second time by us. 1040 print("ERROR", file=sbuf) 1041 1042 def markCleanupError(self): 1043 """Callback invoked when an error occurs while a test is cleaning up.""" 1044 self.__cleanup_errored__ = True 1045 with recording(self, False) as sbuf: 1046 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice. 1047 # Once by the Python unittest framework, and a second time by us. 1048 print("CLEANUP_ERROR", file=sbuf) 1049 1050 def markFailure(self): 1051 """Callback invoked when a failure (test assertion failure) occurred.""" 1052 self.__failed__ = True 1053 with recording(self, False) as sbuf: 1054 # False because there's no need to write "FAIL" to the stderr twice. 1055 # Once by the Python unittest framework, and a second time by us. 1056 print("FAIL", file=sbuf) 1057 1058 def markExpectedFailure(self, err, bugnumber): 1059 """Callback invoked when an expected failure/error occurred.""" 1060 self.__expected__ = True 1061 with recording(self, False) as sbuf: 1062 # False because there's no need to write "expected failure" to the 1063 # stderr twice. 1064 # Once by the Python unittest framework, and a second time by us. 1065 if bugnumber is None: 1066 print("expected failure", file=sbuf) 1067 else: 1068 print( 1069 "expected failure (problem id:" + str(bugnumber) + ")", 1070 file=sbuf) 1071 1072 def markSkippedTest(self): 1073 """Callback invoked when a test is skipped.""" 1074 self.__skipped__ = True 1075 with recording(self, False) as sbuf: 1076 # False because there's no need to write "skipped test" to the 1077 # stderr twice. 1078 # Once by the Python unittest framework, and a second time by us. 1079 print("skipped test", file=sbuf) 1080 1081 def markUnexpectedSuccess(self, bugnumber): 1082 """Callback invoked when an unexpected success occurred.""" 1083 self.__unexpected__ = True 1084 with recording(self, False) as sbuf: 1085 # False because there's no need to write "unexpected success" to the 1086 # stderr twice. 1087 # Once by the Python unittest framework, and a second time by us. 1088 if bugnumber is None: 1089 print("unexpected success", file=sbuf) 1090 else: 1091 print( 1092 "unexpected success (problem id:" + str(bugnumber) + ")", 1093 file=sbuf) 1094 1095 def getRerunArgs(self): 1096 return " -f %s.%s" % (self.__class__.__name__, self._testMethodName) 1097 1098 def getLogBasenameForCurrentTest(self, prefix="Incomplete"): 1099 """ 1100 returns a partial path that can be used as the beginning of the name of multiple 1101 log files pertaining to this test 1102 """ 1103 return os.path.join(self.getBuildDir(), prefix) 1104 1105 def dumpSessionInfo(self): 1106 """ 1107 Dump the debugger interactions leading to a test error/failure. This 1108 allows for more convenient postmortem analysis. 1109 1110 See also LLDBTestResult (dotest.py) which is a singlton class derived 1111 from TextTestResult and overwrites addError, addFailure, and 1112 addExpectedFailure methods to allow us to to mark the test instance as 1113 such. 1114 """ 1115 1116 # We are here because self.tearDown() detected that this test instance 1117 # either errored or failed. The lldb.test_result singleton contains 1118 # two lists (errors and failures) which get populated by the unittest 1119 # framework. Look over there for stack trace information. 1120 # 1121 # The lists contain 2-tuples of TestCase instances and strings holding 1122 # formatted tracebacks. 1123 # 1124 # See http://docs.python.org/library/unittest.html#unittest.TestResult. 1125 1126 # output tracebacks into session 1127 pairs = [] 1128 if self.__errored__: 1129 pairs = configuration.test_result.errors 1130 prefix = 'Error' 1131 elif self.__cleanup_errored__: 1132 pairs = configuration.test_result.cleanup_errors 1133 prefix = 'CleanupError' 1134 elif self.__failed__: 1135 pairs = configuration.test_result.failures 1136 prefix = 'Failure' 1137 elif self.__expected__: 1138 pairs = configuration.test_result.expectedFailures 1139 prefix = 'ExpectedFailure' 1140 elif self.__skipped__: 1141 prefix = 'SkippedTest' 1142 elif self.__unexpected__: 1143 prefix = 'UnexpectedSuccess' 1144 else: 1145 prefix = 'Success' 1146 1147 if not self.__unexpected__ and not self.__skipped__: 1148 for test, traceback in pairs: 1149 if test is self: 1150 print(traceback, file=self.session) 1151 1152 import datetime 1153 print( 1154 "Session info generated @", 1155 datetime.datetime.now().ctime(), 1156 file=self.session) 1157 self.session.close() 1158 del self.session 1159 1160 # process the log files 1161 if prefix != 'Success' or lldbtest_config.log_success: 1162 # keep all log files, rename them to include prefix 1163 src_log_basename = self.getLogBasenameForCurrentTest() 1164 dst_log_basename = self.getLogBasenameForCurrentTest(prefix) 1165 for src in self.log_files: 1166 if os.path.isfile(src): 1167 dst = src.replace(src_log_basename, dst_log_basename) 1168 if os.name == "nt" and os.path.isfile(dst): 1169 # On Windows, renaming a -> b will throw an exception if 1170 # b exists. On non-Windows platforms it silently 1171 # replaces the destination. Ultimately this means that 1172 # atomic renames are not guaranteed to be possible on 1173 # Windows, but we need this to work anyway, so just 1174 # remove the destination first if it already exists. 1175 remove_file(dst) 1176 1177 lldbutil.mkdir_p(os.path.dirname(dst)) 1178 os.rename(src, dst) 1179 else: 1180 # success! (and we don't want log files) delete log files 1181 for log_file in self.log_files: 1182 if os.path.isfile(log_file): 1183 remove_file(log_file) 1184 1185 # ==================================================== 1186 # Config. methods supported through a plugin interface 1187 # (enables reading of the current test configuration) 1188 # ==================================================== 1189 1190 def isMIPS(self): 1191 """Returns true if the architecture is MIPS.""" 1192 arch = self.getArchitecture() 1193 if re.match("mips", arch): 1194 return True 1195 return False 1196 1197 def isPPC64le(self): 1198 """Returns true if the architecture is PPC64LE.""" 1199 arch = self.getArchitecture() 1200 if re.match("powerpc64le", arch): 1201 return True 1202 return False 1203 1204 def getCPUInfo(self): 1205 triple = self.dbg.GetSelectedPlatform().GetTriple() 1206 1207 # TODO other platforms, please implement this function 1208 if not re.match(".*-.*-linux", triple): 1209 return "" 1210 1211 # Need to do something different for non-Linux/Android targets 1212 cpuinfo_path = self.getBuildArtifact("cpuinfo") 1213 if configuration.lldb_platform_name: 1214 self.runCmd('platform get-file "/proc/cpuinfo" ' + cpuinfo_path) 1215 else: 1216 cpuinfo_path = "/proc/cpuinfo" 1217 1218 try: 1219 with open(cpuinfo_path, 'r') as f: 1220 cpuinfo = f.read() 1221 except: 1222 return "" 1223 1224 return cpuinfo 1225 1226 def isAArch64(self): 1227 """Returns true if the architecture is AArch64.""" 1228 arch = self.getArchitecture().lower() 1229 return arch in ["aarch64", "arm64", "arm64e"] 1230 1231 def isAArch64SVE(self): 1232 return self.isAArch64() and "sve" in self.getCPUInfo() 1233 1234 def isAArch64MTE(self): 1235 return self.isAArch64() and "mte" in self.getCPUInfo() 1236 1237 def isAArch64PAuth(self): 1238 return self.isAArch64() and "paca" in self.getCPUInfo() 1239 1240 def getArchitecture(self): 1241 """Returns the architecture in effect the test suite is running with.""" 1242 module = builder_module() 1243 arch = module.getArchitecture() 1244 if arch == 'amd64': 1245 arch = 'x86_64' 1246 if arch in ['armv7l', 'armv8l'] : 1247 arch = 'arm' 1248 return arch 1249 1250 def getLldbArchitecture(self): 1251 """Returns the architecture of the lldb binary.""" 1252 if not hasattr(self, 'lldbArchitecture'): 1253 1254 # spawn local process 1255 command = [ 1256 lldbtest_config.lldbExec, 1257 "-o", 1258 "file " + lldbtest_config.lldbExec, 1259 "-o", 1260 "quit" 1261 ] 1262 1263 output = check_output(command) 1264 str = output.decode("utf-8") 1265 1266 for line in str.splitlines(): 1267 m = re.search( 1268 "Current executable set to '.*' \\((.*)\\)\\.", line) 1269 if m: 1270 self.lldbArchitecture = m.group(1) 1271 break 1272 1273 return self.lldbArchitecture 1274 1275 def getCompiler(self): 1276 """Returns the compiler in effect the test suite is running with.""" 1277 module = builder_module() 1278 return module.getCompiler() 1279 1280 def getCompilerBinary(self): 1281 """Returns the compiler binary the test suite is running with.""" 1282 return self.getCompiler().split()[0] 1283 1284 def getCompilerVersion(self): 1285 """ Returns a string that represents the compiler version. 1286 Supports: llvm, clang. 1287 """ 1288 compiler = self.getCompilerBinary() 1289 version_output = check_output([compiler, "--version"], errors="replace") 1290 m = re.search('version ([0-9.]+)', version_output) 1291 if m: 1292 return m.group(1) 1293 return 'unknown' 1294 1295 def getDwarfVersion(self): 1296 """ Returns the dwarf version generated by clang or '0'. """ 1297 if configuration.dwarf_version: 1298 return str(configuration.dwarf_version) 1299 if 'clang' in self.getCompiler(): 1300 try: 1301 triple = builder_module().getTriple(self.getArchitecture()) 1302 target = ['-target', triple] if triple else [] 1303 driver_output = check_output( 1304 [self.getCompiler()] + target + '-g -c -x c - -o - -###'.split(), 1305 stderr=STDOUT) 1306 driver_output = driver_output.decode("utf-8") 1307 for line in driver_output.split(os.linesep): 1308 m = re.search('dwarf-version=([0-9])', line) 1309 if m: 1310 return m.group(1) 1311 except CalledProcessError: 1312 pass 1313 return '0' 1314 1315 def platformIsDarwin(self): 1316 """Returns true if the OS triple for the selected platform is any valid apple OS""" 1317 return lldbplatformutil.platformIsDarwin() 1318 1319 def hasDarwinFramework(self): 1320 return self.darwinWithFramework 1321 1322 def getPlatform(self): 1323 """Returns the target platform the test suite is running on.""" 1324 return lldbplatformutil.getPlatform() 1325 1326 def isIntelCompiler(self): 1327 """ Returns true if using an Intel (ICC) compiler, false otherwise. """ 1328 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]]) 1329 1330 def expectedCompilerVersion(self, compiler_version): 1331 """Returns True iff compiler_version[1] matches the current compiler version. 1332 Use compiler_version[0] to specify the operator used to determine if a match has occurred. 1333 Any operator other than the following defaults to an equality test: 1334 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' 1335 1336 If the current compiler version cannot be determined, we assume it is close to the top 1337 of trunk, so any less-than or equal-to comparisons will return False, and any 1338 greater-than or not-equal-to comparisons will return True. 1339 """ 1340 if compiler_version is None: 1341 return True 1342 operator = str(compiler_version[0]) 1343 version = compiler_version[1] 1344 1345 if version is None: 1346 return True 1347 1348 test_compiler_version = self.getCompilerVersion() 1349 if test_compiler_version == 'unknown': 1350 # Assume the compiler version is at or near the top of trunk. 1351 return operator in ['>', '>=', '!', '!=', 'not'] 1352 1353 if operator == '>': 1354 return LooseVersion(test_compiler_version) > LooseVersion(version) 1355 if operator == '>=' or operator == '=>': 1356 return LooseVersion(test_compiler_version) >= LooseVersion(version) 1357 if operator == '<': 1358 return LooseVersion(test_compiler_version) < LooseVersion(version) 1359 if operator == '<=' or operator == '=<': 1360 return LooseVersion(test_compiler_version) <= LooseVersion(version) 1361 if operator == '!=' or operator == '!' or operator == 'not': 1362 return str(version) not in str(test_compiler_version) 1363 return str(version) in str(test_compiler_version) 1364 1365 def expectedCompiler(self, compilers): 1366 """Returns True iff any element of compilers is a sub-string of the current compiler.""" 1367 if (compilers is None): 1368 return True 1369 1370 for compiler in compilers: 1371 if compiler in self.getCompiler(): 1372 return True 1373 1374 return False 1375 1376 def expectedArch(self, archs): 1377 """Returns True iff any element of archs is a sub-string of the current architecture.""" 1378 if (archs is None): 1379 return True 1380 1381 for arch in archs: 1382 if arch in self.getArchitecture(): 1383 return True 1384 1385 return False 1386 1387 def getRunOptions(self): 1388 """Command line option for -A and -C to run this test again, called from 1389 self.dumpSessionInfo().""" 1390 arch = self.getArchitecture() 1391 comp = self.getCompiler() 1392 option_str = "" 1393 if arch: 1394 option_str = "-A " + arch 1395 if comp: 1396 option_str += " -C " + comp 1397 return option_str 1398 1399 def getDebugInfo(self): 1400 method = getattr(self, self.testMethodName) 1401 return getattr(method, "debug_info", None) 1402 1403 def build( 1404 self, 1405 debug_info=None, 1406 architecture=None, 1407 compiler=None, 1408 dictionary=None): 1409 """Platform specific way to build binaries.""" 1410 if not architecture and configuration.arch: 1411 architecture = configuration.arch 1412 1413 if debug_info is None: 1414 debug_info = self.getDebugInfo() 1415 1416 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1417 1418 testdir = self.mydir 1419 testname = self.getBuildDirBasename() 1420 1421 module = builder_module() 1422 command = builder_module().getBuildCommand(debug_info, architecture, 1423 compiler, dictionary, testdir, testname) 1424 if command is None: 1425 raise Exception("Don't know how to build binary") 1426 1427 self.runBuildCommand(command) 1428 1429 def runBuildCommand(self, command): 1430 self.trace(seven.join_for_shell(command)) 1431 try: 1432 output = check_output(command, stderr=STDOUT, errors="replace") 1433 except CalledProcessError as cpe: 1434 raise build_exception.BuildError(cpe) 1435 self.trace(output) 1436 1437 1438 # ================================================== 1439 # Build methods supported through a plugin interface 1440 # ================================================== 1441 1442 def getstdlibFlag(self): 1443 """ Returns the proper -stdlib flag, or empty if not required.""" 1444 if self.platformIsDarwin() or self.getPlatform() == "freebsd" or self.getPlatform() == "openbsd": 1445 stdlibflag = "-stdlib=libc++" 1446 else: # this includes NetBSD 1447 stdlibflag = "" 1448 return stdlibflag 1449 1450 def getstdFlag(self): 1451 """ Returns the proper stdflag. """ 1452 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1453 stdflag = "-std=c++0x" 1454 else: 1455 stdflag = "-std=c++11" 1456 return stdflag 1457 1458 def buildDriver(self, sources, exe_name): 1459 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so 1460 or LLDB.framework). 1461 """ 1462 stdflag = self.getstdFlag() 1463 stdlibflag = self.getstdlibFlag() 1464 1465 lib_dir = configuration.lldb_libs_dir 1466 if self.hasDarwinFramework(): 1467 d = {'CXX_SOURCES': sources, 1468 'EXE': exe_name, 1469 'CFLAGS_EXTRAS': "%s %s" % (stdflag, stdlibflag), 1470 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, 1471 'LD_EXTRAS': "%s -Wl,-rpath,%s" % (self.lib_lldb, self.framework_dir), 1472 } 1473 elif sys.platform.startswith('win'): 1474 d = { 1475 'CXX_SOURCES': sources, 1476 'EXE': exe_name, 1477 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, 1478 stdlibflag, 1479 os.path.join( 1480 os.environ["LLDB_SRC"], 1481 "include")), 1482 'LD_EXTRAS': "-L%s -lliblldb" % lib_dir} 1483 else: 1484 d = { 1485 'CXX_SOURCES': sources, 1486 'EXE': exe_name, 1487 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, 1488 stdlibflag, 1489 os.path.join( 1490 os.environ["LLDB_SRC"], 1491 "include")), 1492 'LD_EXTRAS': "-L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)} 1493 if self.TraceOn(): 1494 print( 1495 "Building LLDB Driver (%s) from sources %s" % 1496 (exe_name, sources)) 1497 1498 self.build(dictionary=d) 1499 1500 def buildLibrary(self, sources, lib_name): 1501 """Platform specific way to build a default library. """ 1502 1503 stdflag = self.getstdFlag() 1504 1505 lib_dir = configuration.lldb_libs_dir 1506 if self.hasDarwinFramework(): 1507 d = {'DYLIB_CXX_SOURCES': sources, 1508 'DYLIB_NAME': lib_name, 1509 'CFLAGS_EXTRAS': "%s -stdlib=libc++" % stdflag, 1510 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, 1511 'LD_EXTRAS': "%s -Wl,-rpath,%s -dynamiclib" % (self.lib_lldb, self.framework_dir), 1512 } 1513 elif self.getPlatform() == 'windows': 1514 d = { 1515 'DYLIB_CXX_SOURCES': sources, 1516 'DYLIB_NAME': lib_name, 1517 'CFLAGS_EXTRAS': "%s -I%s " % (stdflag, 1518 os.path.join( 1519 os.environ["LLDB_SRC"], 1520 "include")), 1521 'LD_EXTRAS': "-shared -l%s\liblldb.lib" % lib_dir} 1522 else: 1523 d = { 1524 'DYLIB_CXX_SOURCES': sources, 1525 'DYLIB_NAME': lib_name, 1526 'CFLAGS_EXTRAS': "%s -I%s -fPIC" % (stdflag, 1527 os.path.join( 1528 os.environ["LLDB_SRC"], 1529 "include")), 1530 'LD_EXTRAS': "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)} 1531 if self.TraceOn(): 1532 print( 1533 "Building LLDB Library (%s) from sources %s" % 1534 (lib_name, sources)) 1535 1536 self.build(dictionary=d) 1537 1538 def buildProgram(self, sources, exe_name): 1539 """ Platform specific way to build an executable from C/C++ sources. """ 1540 d = {'CXX_SOURCES': sources, 1541 'EXE': exe_name} 1542 self.build(dictionary=d) 1543 1544 def signBinary(self, binary_path): 1545 if sys.platform.startswith("darwin"): 1546 codesign_cmd = "codesign --force --sign \"%s\" %s" % ( 1547 lldbtest_config.codesign_identity, binary_path) 1548 call(codesign_cmd, shell=True) 1549 1550 def findBuiltClang(self): 1551 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler).""" 1552 paths_to_try = [ 1553 "llvm-build/Release+Asserts/x86_64/bin/clang", 1554 "llvm-build/Debug+Asserts/x86_64/bin/clang", 1555 "llvm-build/Release/x86_64/bin/clang", 1556 "llvm-build/Debug/x86_64/bin/clang", 1557 ] 1558 lldb_root_path = os.path.join( 1559 os.path.dirname(__file__), "..", "..", "..", "..") 1560 for p in paths_to_try: 1561 path = os.path.join(lldb_root_path, p) 1562 if os.path.exists(path): 1563 return path 1564 1565 # Tries to find clang at the same folder as the lldb 1566 lldb_dir = os.path.dirname(lldbtest_config.lldbExec) 1567 path = shutil.which("clang", path=lldb_dir) 1568 if path is not None: 1569 return path 1570 1571 return os.environ["CC"] 1572 1573 1574 def yaml2obj(self, yaml_path, obj_path, max_size=None): 1575 """ 1576 Create an object file at the given path from a yaml file. 1577 1578 Throws subprocess.CalledProcessError if the object could not be created. 1579 """ 1580 yaml2obj_bin = configuration.get_yaml2obj_path() 1581 if not yaml2obj_bin: 1582 self.assertTrue(False, "No valid yaml2obj executable specified") 1583 command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path] 1584 if max_size is not None: 1585 command += ["--max-size=%d" % max_size] 1586 self.runBuildCommand(command) 1587 1588 def cleanup(self, dictionary=None): 1589 """Platform specific way to do cleanup after build.""" 1590 module = builder_module() 1591 if not module.cleanup(dictionary): 1592 raise Exception( 1593 "Don't know how to do cleanup with dictionary: " + 1594 dictionary) 1595 1596 def invoke(self, obj, name, trace=False): 1597 """Use reflection to call a method dynamically with no argument.""" 1598 trace = (True if traceAlways else trace) 1599 1600 method = getattr(obj, name) 1601 import inspect 1602 self.assertTrue(inspect.ismethod(method), 1603 name + "is a method name of object: " + str(obj)) 1604 result = method() 1605 with recording(self, trace) as sbuf: 1606 print(str(method) + ":", result, file=sbuf) 1607 return result 1608 1609 def getLLDBLibraryEnvVal(self): 1610 """ Returns the path that the OS-specific library search environment variable 1611 (self.dylibPath) should be set to in order for a program to find the LLDB 1612 library. If an environment variable named self.dylibPath is already set, 1613 the new path is appended to it and returned. 1614 """ 1615 existing_library_path = os.environ[ 1616 self.dylibPath] if self.dylibPath in os.environ else None 1617 if existing_library_path: 1618 return "%s:%s" % (existing_library_path, configuration.lldb_libs_dir) 1619 if sys.platform.startswith("darwin") and configuration.lldb_framework_path: 1620 return configuration.lldb_framework_path 1621 return configuration.lldb_libs_dir 1622 1623 def getLibcPlusPlusLibs(self): 1624 if self.getPlatform() in ('freebsd', 'linux', 'netbsd', 'openbsd'): 1625 return ['libc++.so.1'] 1626 else: 1627 return ['libc++.1.dylib', 'libc++abi.'] 1628 1629 def run_platform_command(self, cmd): 1630 platform = self.dbg.GetSelectedPlatform() 1631 shell_command = lldb.SBPlatformShellCommand(cmd) 1632 err = platform.Run(shell_command) 1633 return (err, shell_command.GetStatus(), shell_command.GetOutput()) 1634 1635# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded. 1636# We change the test methods to create a new test method for each test for each debug info we are 1637# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding 1638# the new test method we remove the old method at the same time. This functionality can be 1639# supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test 1640# level by using the decorator @no_debug_info_test. 1641 1642 1643class LLDBTestCaseFactory(type): 1644 1645 def __new__(cls, name, bases, attrs): 1646 original_testcase = super( 1647 LLDBTestCaseFactory, cls).__new__( 1648 cls, name, bases, attrs) 1649 if original_testcase.NO_DEBUG_INFO_TESTCASE: 1650 return original_testcase 1651 1652 newattrs = {} 1653 for attrname, attrvalue in attrs.items(): 1654 if attrname.startswith("test") and not getattr( 1655 attrvalue, "__no_debug_info_test__", False): 1656 1657 # If any debug info categories were explicitly tagged, assume that list to be 1658 # authoritative. If none were specified, try with all debug 1659 # info formats. 1660 all_dbginfo_categories = set(test_categories.debug_info_categories) 1661 categories = set( 1662 getattr( 1663 attrvalue, 1664 "categories", 1665 [])) & all_dbginfo_categories 1666 if not categories: 1667 categories = all_dbginfo_categories 1668 1669 for cat in categories: 1670 @decorators.add_test_categories([cat]) 1671 @wraps(attrvalue) 1672 def test_method(self, attrvalue=attrvalue): 1673 return attrvalue(self) 1674 1675 method_name = attrname + "_" + cat 1676 test_method.__name__ = method_name 1677 test_method.debug_info = cat 1678 newattrs[method_name] = test_method 1679 1680 else: 1681 newattrs[attrname] = attrvalue 1682 return super( 1683 LLDBTestCaseFactory, 1684 cls).__new__( 1685 cls, 1686 name, 1687 bases, 1688 newattrs) 1689 1690# Setup the metaclass for this class to change the list of the test 1691# methods when a new class is loaded 1692 1693 1694@add_metaclass(LLDBTestCaseFactory) 1695class TestBase(Base): 1696 """ 1697 This abstract base class is meant to be subclassed. It provides default 1698 implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(), 1699 among other things. 1700 1701 Important things for test class writers: 1702 1703 - The setUp method sets up things to facilitate subsequent interactions 1704 with the debugger as part of the test. These include: 1705 - populate the test method name 1706 - create/get a debugger set with synchronous mode (self.dbg) 1707 - get the command interpreter from with the debugger (self.ci) 1708 - create a result object for use with the command interpreter 1709 (self.res) 1710 - plus other stuffs 1711 1712 - The tearDown method tries to perform some necessary cleanup on behalf 1713 of the test to return the debugger to a good state for the next test. 1714 These include: 1715 - execute any tearDown hooks registered by the test method with 1716 TestBase.addTearDownHook(); examples can be found in 1717 settings/TestSettings.py 1718 - kill the inferior process associated with each target, if any, 1719 and, then delete the target from the debugger's target list 1720 - perform build cleanup before running the next test method in the 1721 same test class; examples of registering for this service can be 1722 found in types/TestIntegerTypes.py with the call: 1723 - self.setTearDownCleanup(dictionary=d) 1724 1725 - Similarly setUpClass and tearDownClass perform classwise setup and 1726 teardown fixtures. The tearDownClass method invokes a default build 1727 cleanup for the entire test class; also, subclasses can implement the 1728 classmethod classCleanup(cls) to perform special class cleanup action. 1729 1730 - The instance methods runCmd and expect are used heavily by existing 1731 test cases to send a command to the command interpreter and to perform 1732 string/pattern matching on the output of such command execution. The 1733 expect method also provides a mode to peform string/pattern matching 1734 without running a command. 1735 1736 - The build method is used to build the binaries used during a 1737 particular test scenario. A plugin should be provided for the 1738 sys.platform running the test suite. The Mac OS X implementation is 1739 located in builders/darwin.py. 1740 """ 1741 1742 # Subclasses can set this to true (if they don't depend on debug info) to avoid running the 1743 # test multiple times with various debug info types. 1744 NO_DEBUG_INFO_TESTCASE = False 1745 1746 # Maximum allowed attempts when launching the inferior process. 1747 # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. 1748 maxLaunchCount = 1 1749 1750 # Time to wait before the next launching attempt in second(s). 1751 # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. 1752 timeWaitNextLaunch = 1.0 1753 1754 def generateSource(self, source): 1755 template = source + '.template' 1756 temp = os.path.join(self.getSourceDir(), template) 1757 with open(temp, 'r') as f: 1758 content = f.read() 1759 1760 public_api_dir = os.path.join( 1761 os.environ["LLDB_SRC"], "include", "lldb", "API") 1762 1763 # Look under the include/lldb/API directory and add #include statements 1764 # for all the SB API headers. 1765 public_headers = os.listdir(public_api_dir) 1766 # For different platforms, the include statement can vary. 1767 if self.hasDarwinFramework(): 1768 include_stmt = "'#include <%s>' % os.path.join('LLDB', header)" 1769 else: 1770 include_stmt = "'#include <%s>' % os.path.join(r'" + public_api_dir + "', header)" 1771 list = [eval(include_stmt) for header in public_headers if ( 1772 header.startswith("SB") and header.endswith(".h"))] 1773 includes = '\n'.join(list) 1774 new_content = content.replace('%include_SB_APIs%', includes) 1775 new_content = new_content.replace('%SOURCE_DIR%', self.getSourceDir()) 1776 src = os.path.join(self.getBuildDir(), source) 1777 with open(src, 'w') as f: 1778 f.write(new_content) 1779 1780 self.addTearDownHook(lambda: os.remove(src)) 1781 1782 def setUp(self): 1783 # Works with the test driver to conditionally skip tests via 1784 # decorators. 1785 Base.setUp(self) 1786 1787 for s in self.setUpCommands(): 1788 self.runCmd(s) 1789 1790 if "LLDB_MAX_LAUNCH_COUNT" in os.environ: 1791 self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) 1792 1793 if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: 1794 self.timeWaitNextLaunch = float( 1795 os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) 1796 1797 # We want our debugger to be synchronous. 1798 self.dbg.SetAsync(False) 1799 1800 # Retrieve the associated command interpreter instance. 1801 self.ci = self.dbg.GetCommandInterpreter() 1802 if not self.ci: 1803 raise Exception('Could not get the command interpreter') 1804 1805 # And the result object. 1806 self.res = lldb.SBCommandReturnObject() 1807 1808 def registerSharedLibrariesWithTarget(self, target, shlibs): 1809 '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing 1810 1811 Any modules in the target that have their remote install file specification set will 1812 get uploaded to the remote host. This function registers the local copies of the 1813 shared libraries with the target and sets their remote install locations so they will 1814 be uploaded when the target is run. 1815 ''' 1816 if not shlibs or not self.platformContext: 1817 return None 1818 1819 shlib_environment_var = self.platformContext.shlib_environment_var 1820 shlib_prefix = self.platformContext.shlib_prefix 1821 shlib_extension = '.' + self.platformContext.shlib_extension 1822 1823 dirs = [] 1824 # Add any shared libraries to our target if remote so they get 1825 # uploaded into the working directory on the remote side 1826 for name in shlibs: 1827 # The path can be a full path to a shared library, or a make file name like "Foo" for 1828 # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a 1829 # basename like "libFoo.so". So figure out which one it is and resolve the local copy 1830 # of the shared library accordingly 1831 if os.path.isfile(name): 1832 local_shlib_path = name # name is the full path to the local shared library 1833 else: 1834 # Check relative names 1835 local_shlib_path = os.path.join( 1836 self.getBuildDir(), shlib_prefix + name + shlib_extension) 1837 if not os.path.exists(local_shlib_path): 1838 local_shlib_path = os.path.join( 1839 self.getBuildDir(), name + shlib_extension) 1840 if not os.path.exists(local_shlib_path): 1841 local_shlib_path = os.path.join(self.getBuildDir(), name) 1842 1843 # Make sure we found the local shared library in the above code 1844 self.assertTrue(os.path.exists(local_shlib_path)) 1845 1846 1847 # Add the shared library to our target 1848 shlib_module = target.AddModule(local_shlib_path, None, None, None) 1849 if lldb.remote_platform: 1850 # We must set the remote install location if we want the shared library 1851 # to get uploaded to the remote target 1852 remote_shlib_path = lldbutil.append_to_process_working_directory(self, 1853 os.path.basename(local_shlib_path)) 1854 shlib_module.SetRemoteInstallFileSpec( 1855 lldb.SBFileSpec(remote_shlib_path, False)) 1856 dir_to_add = self.get_process_working_directory() 1857 else: 1858 dir_to_add = os.path.dirname(local_shlib_path) 1859 1860 if dir_to_add not in dirs: 1861 dirs.append(dir_to_add) 1862 1863 env_value = self.platformContext.shlib_path_separator.join(dirs) 1864 return ['%s=%s' % (shlib_environment_var, env_value)] 1865 1866 def registerSanitizerLibrariesWithTarget(self, target): 1867 runtimes = [] 1868 for m in target.module_iter(): 1869 libspec = m.GetFileSpec() 1870 if "clang_rt" in libspec.GetFilename(): 1871 runtimes.append(os.path.join(libspec.GetDirectory(), 1872 libspec.GetFilename())) 1873 return self.registerSharedLibrariesWithTarget(target, runtimes) 1874 1875 # utility methods that tests can use to access the current objects 1876 def target(self): 1877 if not self.dbg: 1878 raise Exception('Invalid debugger instance') 1879 return self.dbg.GetSelectedTarget() 1880 1881 def process(self): 1882 if not self.dbg: 1883 raise Exception('Invalid debugger instance') 1884 return self.dbg.GetSelectedTarget().GetProcess() 1885 1886 def thread(self): 1887 if not self.dbg: 1888 raise Exception('Invalid debugger instance') 1889 return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread() 1890 1891 def frame(self): 1892 if not self.dbg: 1893 raise Exception('Invalid debugger instance') 1894 return self.dbg.GetSelectedTarget().GetProcess( 1895 ).GetSelectedThread().GetSelectedFrame() 1896 1897 def get_process_working_directory(self): 1898 '''Get the working directory that should be used when launching processes for local or remote processes.''' 1899 if lldb.remote_platform: 1900 # Remote tests set the platform working directory up in 1901 # TestBase.setUp() 1902 return lldb.remote_platform.GetWorkingDirectory() 1903 else: 1904 # local tests change directory into each test subdirectory 1905 return self.getBuildDir() 1906 1907 def tearDown(self): 1908 # Ensure all the references to SB objects have gone away so that we can 1909 # be sure that all test-specific resources have been freed before we 1910 # attempt to delete the targets. 1911 gc.collect() 1912 1913 # Delete the target(s) from the debugger as a general cleanup step. 1914 # This includes terminating the process for each target, if any. 1915 # We'd like to reuse the debugger for our next test without incurring 1916 # the initialization overhead. 1917 targets = [] 1918 for target in self.dbg: 1919 if target: 1920 targets.append(target) 1921 process = target.GetProcess() 1922 if process: 1923 rc = self.invoke(process, "Kill") 1924 assert rc.Success() 1925 for target in targets: 1926 self.dbg.DeleteTarget(target) 1927 1928 # Assert that all targets are deleted. 1929 self.assertEqual(self.dbg.GetNumTargets(), 0) 1930 1931 # Do this last, to make sure it's in reverse order from how we setup. 1932 Base.tearDown(self) 1933 1934 def switch_to_thread_with_stop_reason(self, stop_reason): 1935 """ 1936 Run the 'thread list' command, and select the thread with stop reason as 1937 'stop_reason'. If no such thread exists, no select action is done. 1938 """ 1939 from .lldbutil import stop_reason_to_str 1940 self.runCmd('thread list') 1941 output = self.res.GetOutput() 1942 thread_line_pattern = re.compile( 1943 "^[ *] thread #([0-9]+):.*stop reason = %s" % 1944 stop_reason_to_str(stop_reason)) 1945 for line in output.splitlines(): 1946 matched = thread_line_pattern.match(line) 1947 if matched: 1948 self.runCmd('thread select %s' % matched.group(1)) 1949 1950 def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): 1951 """ 1952 Ask the command interpreter to handle the command and then check its 1953 return status. 1954 """ 1955 # Fail fast if 'cmd' is not meaningful. 1956 if cmd is None: 1957 raise Exception("Bad 'cmd' parameter encountered") 1958 1959 trace = (True if traceAlways else trace) 1960 1961 if cmd.startswith("target create "): 1962 cmd = cmd.replace("target create ", "file ") 1963 1964 running = (cmd.startswith("run") or cmd.startswith("process launch")) 1965 1966 for i in range(self.maxLaunchCount if running else 1): 1967 self.ci.HandleCommand(cmd, self.res, inHistory) 1968 1969 with recording(self, trace) as sbuf: 1970 print("runCmd:", cmd, file=sbuf) 1971 if not check: 1972 print("check of return status not required", file=sbuf) 1973 if self.res.Succeeded(): 1974 print("output:", self.res.GetOutput(), file=sbuf) 1975 else: 1976 print("runCmd failed!", file=sbuf) 1977 print(self.res.GetError(), file=sbuf) 1978 1979 if self.res.Succeeded(): 1980 break 1981 elif running: 1982 # For process launch, wait some time before possible next try. 1983 time.sleep(self.timeWaitNextLaunch) 1984 with recording(self, trace) as sbuf: 1985 print("Command '" + cmd + "' failed!", file=sbuf) 1986 1987 if check: 1988 output = "" 1989 if self.res.GetOutput(): 1990 output += "\nCommand output:\n" + self.res.GetOutput() 1991 if self.res.GetError(): 1992 output += "\nError output:\n" + self.res.GetError() 1993 if msg: 1994 msg += output 1995 if cmd: 1996 cmd += output 1997 self.assertTrue(self.res.Succeeded(), 1998 msg if (msg) else CMD_MSG(cmd)) 1999 2000 def match( 2001 self, 2002 str, 2003 patterns, 2004 msg=None, 2005 trace=False, 2006 error=False, 2007 matching=True, 2008 exe=True): 2009 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern 2010 2011 Otherwise, all the arguments have the same meanings as for the expect function""" 2012 2013 trace = (True if traceAlways else trace) 2014 2015 if exe: 2016 # First run the command. If we are expecting error, set check=False. 2017 # Pass the assert message along since it provides more semantic 2018 # info. 2019 self.runCmd( 2020 str, 2021 msg=msg, 2022 trace=( 2023 True if trace else False), 2024 check=not error) 2025 2026 # Then compare the output against expected strings. 2027 output = self.res.GetError() if error else self.res.GetOutput() 2028 2029 # If error is True, the API client expects the command to fail! 2030 if error: 2031 self.assertFalse(self.res.Succeeded(), 2032 "Command '" + str + "' is expected to fail!") 2033 else: 2034 # No execution required, just compare str against the golden input. 2035 output = str 2036 with recording(self, trace) as sbuf: 2037 print("looking at:", output, file=sbuf) 2038 2039 # The heading says either "Expecting" or "Not expecting". 2040 heading = "Expecting" if matching else "Not expecting" 2041 2042 for pattern in patterns: 2043 # Match Objects always have a boolean value of True. 2044 match_object = re.search(pattern, output) 2045 matched = bool(match_object) 2046 with recording(self, trace) as sbuf: 2047 print("%s pattern: %s" % (heading, pattern), file=sbuf) 2048 print("Matched" if matched else "Not matched", file=sbuf) 2049 if matched: 2050 break 2051 2052 self.assertTrue(matched if matching else not matched, 2053 msg if msg else EXP_MSG(str, output, exe)) 2054 2055 return match_object 2056 2057 def check_completion_with_desc(self, str_input, match_desc_pairs, enforce_order=False): 2058 """ 2059 Checks that when the given input is completed at the given list of 2060 completions and descriptions is returned. 2061 :param str_input: The input that should be completed. The completion happens at the end of the string. 2062 :param match_desc_pairs: A list of pairs that indicate what completions have to be in the list of 2063 completions returned by LLDB. The first element of the pair is the completion 2064 string that LLDB should generate and the second element the description. 2065 :param enforce_order: True iff the order in which the completions are returned by LLDB 2066 should match the order of the match_desc_pairs pairs. 2067 """ 2068 interp = self.dbg.GetCommandInterpreter() 2069 match_strings = lldb.SBStringList() 2070 description_strings = lldb.SBStringList() 2071 num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings) 2072 self.assertEqual(len(description_strings), len(match_strings)) 2073 2074 # The index of the last matched description in description_strings or 2075 # -1 if no description has been matched yet. 2076 last_found_index = -1 2077 out_of_order_errors = "" 2078 missing_pairs = [] 2079 for pair in match_desc_pairs: 2080 found_pair = False 2081 for i in range(num_matches + 1): 2082 match_candidate = match_strings.GetStringAtIndex(i) 2083 description_candidate = description_strings.GetStringAtIndex(i) 2084 if match_candidate == pair[0] and description_candidate == pair[1]: 2085 found_pair = True 2086 if enforce_order and last_found_index > i: 2087 new_err = ("Found completion " + pair[0] + " at index " + 2088 str(i) + " in returned completion list but " + 2089 "should have been after completion " + 2090 match_strings.GetStringAtIndex(last_found_index) + 2091 " (index:" + str(last_found_index) + ")\n") 2092 out_of_order_errors += new_err 2093 last_found_index = i 2094 break 2095 if not found_pair: 2096 missing_pairs.append(pair) 2097 2098 error_msg = "" 2099 got_failure = False 2100 if len(missing_pairs): 2101 got_failure = True 2102 error_msg += "Missing pairs:\n" 2103 for pair in missing_pairs: 2104 error_msg += " [" + pair[0] + ":" + pair[1] + "]\n" 2105 if len(out_of_order_errors): 2106 got_failure = True 2107 error_msg += out_of_order_errors 2108 if got_failure: 2109 error_msg += "Got the following " + str(num_matches) + " completions back:\n" 2110 for i in range(num_matches + 1): 2111 match_candidate = match_strings.GetStringAtIndex(i) 2112 description_candidate = description_strings.GetStringAtIndex(i) 2113 error_msg += "[" + match_candidate + ":" + description_candidate + "] index " + str(i) + "\n" 2114 self.assertFalse(got_failure, error_msg) 2115 2116 def complete_exactly(self, str_input, patterns): 2117 self.complete_from_to(str_input, patterns, True) 2118 2119 def complete_from_to(self, str_input, patterns, turn_off_re_match=False): 2120 """Test that the completion mechanism completes str_input to patterns, 2121 where patterns could be a pattern-string or a list of pattern-strings""" 2122 # Patterns should not be None in order to proceed. 2123 self.assertFalse(patterns is None) 2124 # And should be either a string or list of strings. Check for list type 2125 # below, if not, make a list out of the singleton string. If patterns 2126 # is not a string or not a list of strings, there'll be runtime errors 2127 # later on. 2128 if not isinstance(patterns, list): 2129 patterns = [patterns] 2130 2131 interp = self.dbg.GetCommandInterpreter() 2132 match_strings = lldb.SBStringList() 2133 num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) 2134 common_match = match_strings.GetStringAtIndex(0) 2135 if num_matches == 0: 2136 compare_string = str_input 2137 else: 2138 if common_match != None and len(common_match) > 0: 2139 compare_string = str_input + common_match 2140 else: 2141 compare_string = "" 2142 for idx in range(1, num_matches+1): 2143 compare_string += match_strings.GetStringAtIndex(idx) + "\n" 2144 2145 for p in patterns: 2146 if turn_off_re_match: 2147 self.expect( 2148 compare_string, msg=COMPLETION_MSG( 2149 str_input, p, match_strings), exe=False, substrs=[p]) 2150 else: 2151 self.expect( 2152 compare_string, msg=COMPLETION_MSG( 2153 str_input, p, match_strings), exe=False, patterns=[p]) 2154 2155 def completions_match(self, command, completions): 2156 """Checks that the completions for the given command are equal to the 2157 given list of completions""" 2158 interp = self.dbg.GetCommandInterpreter() 2159 match_strings = lldb.SBStringList() 2160 interp.HandleCompletion(command, len(command), 0, -1, match_strings) 2161 # match_strings is a 1-indexed list, so we have to slice... 2162 self.assertItemsEqual(completions, list(match_strings)[1:], 2163 "List of returned completion is wrong") 2164 2165 def completions_contain(self, command, completions): 2166 """Checks that the completions for the given command contain the given 2167 list of completions.""" 2168 interp = self.dbg.GetCommandInterpreter() 2169 match_strings = lldb.SBStringList() 2170 interp.HandleCompletion(command, len(command), 0, -1, match_strings) 2171 for completion in completions: 2172 # match_strings is a 1-indexed list, so we have to slice... 2173 self.assertIn(completion, list(match_strings)[1:], 2174 "Couldn't find expected completion") 2175 2176 def filecheck( 2177 self, 2178 command, 2179 check_file, 2180 filecheck_options = '', 2181 expect_cmd_failure = False): 2182 # Run the command. 2183 self.runCmd( 2184 command, 2185 check=(not expect_cmd_failure), 2186 msg="FileCheck'ing result of `{0}`".format(command)) 2187 2188 self.assertTrue((not expect_cmd_failure) == self.res.Succeeded()) 2189 2190 # Get the error text if there was an error, and the regular text if not. 2191 output = self.res.GetOutput() if self.res.Succeeded() \ 2192 else self.res.GetError() 2193 2194 # Assemble the absolute path to the check file. As a convenience for 2195 # LLDB inline tests, assume that the check file is a relative path to 2196 # a file within the inline test directory. 2197 if check_file.endswith('.pyc'): 2198 check_file = check_file[:-1] 2199 check_file_abs = os.path.abspath(check_file) 2200 2201 # Run FileCheck. 2202 filecheck_bin = configuration.get_filecheck_path() 2203 if not filecheck_bin: 2204 self.assertTrue(False, "No valid FileCheck executable specified") 2205 filecheck_args = [filecheck_bin, check_file_abs] 2206 if filecheck_options: 2207 filecheck_args.append(filecheck_options) 2208 subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True) 2209 cmd_stdout, cmd_stderr = subproc.communicate(input=output) 2210 cmd_status = subproc.returncode 2211 2212 filecheck_cmd = " ".join(filecheck_args) 2213 filecheck_trace = """ 2214--- FileCheck trace (code={0}) --- 2215{1} 2216 2217FileCheck input: 2218{2} 2219 2220FileCheck output: 2221{3} 2222{4} 2223""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr) 2224 2225 trace = cmd_status != 0 or traceAlways 2226 with recording(self, trace) as sbuf: 2227 print(filecheck_trace, file=sbuf) 2228 2229 self.assertTrue(cmd_status == 0) 2230 2231 def expect( 2232 self, 2233 str, 2234 msg=None, 2235 patterns=None, 2236 startstr=None, 2237 endstr=None, 2238 substrs=None, 2239 trace=False, 2240 error=False, 2241 ordered=True, 2242 matching=True, 2243 exe=True, 2244 inHistory=False): 2245 """ 2246 Similar to runCmd; with additional expect style output matching ability. 2247 2248 Ask the command interpreter to handle the command and then check its 2249 return status. The 'msg' parameter specifies an informational assert 2250 message. We expect the output from running the command to start with 2251 'startstr', matches the substrings contained in 'substrs', and regexp 2252 matches the patterns contained in 'patterns'. 2253 2254 When matching is true and ordered is true, which are both the default, 2255 the strings in the substrs array have to appear in the command output 2256 in the order in which they appear in the array. 2257 2258 If the keyword argument error is set to True, it signifies that the API 2259 client is expecting the command to fail. In this case, the error stream 2260 from running the command is retrieved and compared against the golden 2261 input, instead. 2262 2263 If the keyword argument matching is set to False, it signifies that the API 2264 client is expecting the output of the command not to match the golden 2265 input. 2266 2267 Finally, the required argument 'str' represents the lldb command to be 2268 sent to the command interpreter. In case the keyword argument 'exe' is 2269 set to False, the 'str' is treated as a string to be matched/not-matched 2270 against the golden input. 2271 """ 2272 # Catch cases where `expect` has been miscalled. Specifically, prevent 2273 # this easy to make mistake: 2274 # self.expect("lldb command", "some substr") 2275 # The `msg` parameter is used only when a failed match occurs. A failed 2276 # match can only occur when one of `patterns`, `startstr`, `endstr`, or 2277 # `substrs` has been given. Thus, if a `msg` is given, it's an error to 2278 # not also provide one of the matcher parameters. 2279 if msg and not (patterns or startstr or endstr or substrs or error): 2280 assert False, "expect() missing a matcher argument" 2281 2282 # Check `patterns` and `substrs` are not accidentally given as strings. 2283 assert not isinstance(patterns, six.string_types), \ 2284 "patterns must be a collection of strings" 2285 assert not isinstance(substrs, six.string_types), \ 2286 "substrs must be a collection of strings" 2287 2288 trace = (True if traceAlways else trace) 2289 2290 if exe: 2291 # First run the command. If we are expecting error, set check=False. 2292 # Pass the assert message along since it provides more semantic 2293 # info. 2294 self.runCmd( 2295 str, 2296 msg=msg, 2297 trace=( 2298 True if trace else False), 2299 check=not error, 2300 inHistory=inHistory) 2301 2302 # Then compare the output against expected strings. 2303 output = self.res.GetError() if error else self.res.GetOutput() 2304 2305 # If error is True, the API client expects the command to fail! 2306 if error: 2307 self.assertFalse(self.res.Succeeded(), 2308 "Command '" + str + "' is expected to fail!") 2309 else: 2310 # No execution required, just compare str against the golden input. 2311 if isinstance(str, lldb.SBCommandReturnObject): 2312 output = str.GetOutput() 2313 else: 2314 output = str 2315 with recording(self, trace) as sbuf: 2316 print("looking at:", output, file=sbuf) 2317 2318 expecting_str = "Expecting" if matching else "Not expecting" 2319 def found_str(matched): 2320 return "was found" if matched else "was not found" 2321 2322 # To be used as assert fail message and/or trace content 2323 log_lines = [ 2324 "{}:".format("Ran command" if exe else "Checking string"), 2325 "\"{}\"".format(str), 2326 # Space out command and output 2327 "", 2328 ] 2329 if exe: 2330 # Newline before output to make large strings more readable 2331 log_lines.append("Got output:\n{}".format(output)) 2332 2333 # Assume that we start matched if we want a match 2334 # Meaning if you have no conditions, matching or 2335 # not matching will always pass 2336 matched = matching 2337 2338 # We will stop checking on first failure 2339 if startstr: 2340 matched = output.startswith(startstr) 2341 log_lines.append("{} start string: \"{}\" ({})".format( 2342 expecting_str, startstr, found_str(matched))) 2343 2344 if endstr and matched == matching: 2345 matched = output.endswith(endstr) 2346 log_lines.append("{} end string: \"{}\" ({})".format( 2347 expecting_str, endstr, found_str(matched))) 2348 2349 if substrs and matched == matching: 2350 start = 0 2351 for substr in substrs: 2352 index = output[start:].find(substr) 2353 start = start + index if ordered and matching else 0 2354 matched = index != -1 2355 log_lines.append("{} sub string: \"{}\" ({})".format( 2356 expecting_str, substr, found_str(matched))) 2357 2358 if matched != matching: 2359 break 2360 2361 if patterns and matched == matching: 2362 for pattern in patterns: 2363 matched = re.search(pattern, output) 2364 2365 pattern_line = "{} regex pattern: \"{}\" ({}".format( 2366 expecting_str, pattern, found_str(matched)) 2367 if matched: 2368 pattern_line += ", matched \"{}\"".format( 2369 matched.group(0)) 2370 pattern_line += ")" 2371 log_lines.append(pattern_line) 2372 2373 # Convert to bool because match objects 2374 # are True-ish but != True itself 2375 matched = bool(matched) 2376 if matched != matching: 2377 break 2378 2379 # If a check failed, add any extra assert message 2380 if msg is not None and matched != matching: 2381 log_lines.append(msg) 2382 2383 log_msg = "\n".join(log_lines) 2384 with recording(self, trace) as sbuf: 2385 print(log_msg, file=sbuf) 2386 if matched != matching: 2387 self.fail(log_msg) 2388 2389 def expect_expr( 2390 self, 2391 expr, 2392 result_summary=None, 2393 result_value=None, 2394 result_type=None, 2395 result_children=None 2396 ): 2397 """ 2398 Evaluates the given expression and verifies the result. 2399 :param expr: The expression as a string. 2400 :param result_summary: The summary that the expression should have. None if the summary should not be checked. 2401 :param result_value: The value that the expression should have. None if the value should not be checked. 2402 :param result_type: The type that the expression result should have. None if the type should not be checked. 2403 :param result_children: The expected children of the expression result 2404 as a list of ValueChecks. None if the children shouldn't be checked. 2405 """ 2406 self.assertTrue(expr.strip() == expr, "Expression contains trailing/leading whitespace: '" + expr + "'") 2407 2408 frame = self.frame() 2409 options = lldb.SBExpressionOptions() 2410 2411 # Disable fix-its that tests don't pass by accident. 2412 options.SetAutoApplyFixIts(False) 2413 2414 # Set the usual default options for normal expressions. 2415 options.SetIgnoreBreakpoints(True) 2416 2417 if self.frame().IsValid(): 2418 options.SetLanguage(frame.GuessLanguage()) 2419 eval_result = self.frame().EvaluateExpression(expr, options) 2420 else: 2421 target = self.target() 2422 # If there is no selected target, run the expression in the dummy 2423 # target. 2424 if not target.IsValid(): 2425 target = self.dbg.GetDummyTarget() 2426 eval_result = target.EvaluateExpression(expr, options) 2427 2428 value_check = ValueCheck(type=result_type, value=result_value, 2429 summary=result_summary, children=result_children) 2430 value_check.check_value(self, eval_result, str(eval_result)) 2431 return eval_result 2432 2433 def expect_var_path( 2434 self, 2435 var_path, 2436 summary=None, 2437 value=None, 2438 type=None, 2439 children=None 2440 ): 2441 """ 2442 Evaluates the given variable path and verifies the result. 2443 See also 'frame variable' and SBFrame.GetValueForVariablePath. 2444 :param var_path: The variable path as a string. 2445 :param summary: The summary that the variable should have. None if the summary should not be checked. 2446 :param value: The value that the variable should have. None if the value should not be checked. 2447 :param type: The type that the variable result should have. None if the type should not be checked. 2448 :param children: The expected children of the variable as a list of ValueChecks. 2449 None if the children shouldn't be checked. 2450 """ 2451 self.assertTrue(var_path.strip() == var_path, 2452 "Expression contains trailing/leading whitespace: '" + var_path + "'") 2453 2454 frame = self.frame() 2455 eval_result = frame.GetValueForVariablePath(var_path) 2456 2457 value_check = ValueCheck(type=type, value=value, 2458 summary=summary, children=children) 2459 value_check.check_value(self, eval_result, str(eval_result)) 2460 return eval_result 2461 2462 """Assert that an lldb.SBError is in the "success" state.""" 2463 def assertSuccess(self, obj, msg=None): 2464 if not obj.Success(): 2465 error = obj.GetCString() 2466 self.fail(self._formatMessage(msg, 2467 "'{}' is not success".format(error))) 2468 2469 """Assert two states are equal""" 2470 def assertState(self, first, second, msg=None): 2471 if first != second: 2472 error = "{} ({}) != {} ({})".format( 2473 lldbutil.state_type_to_str(first), first, 2474 lldbutil.state_type_to_str(second), second) 2475 self.fail(self._formatMessage(msg, error)) 2476 2477 def createTestTarget(self, file_path=None, msg=None, 2478 load_dependent_modules=True): 2479 """ 2480 Creates a target from the file found at the given file path. 2481 Asserts that the resulting target is valid. 2482 :param file_path: The file path that should be used to create the target. 2483 The default argument opens the current default test 2484 executable in the current test directory. 2485 :param msg: A custom error message. 2486 """ 2487 if file_path is None: 2488 file_path = self.getBuildArtifact("a.out") 2489 error = lldb.SBError() 2490 triple = "" 2491 platform = "" 2492 target = self.dbg.CreateTarget(file_path, triple, platform, 2493 load_dependent_modules, error) 2494 if error.Fail(): 2495 err = "Couldn't create target for path '{}': {}".format(file_path, 2496 str(error)) 2497 self.fail(self._formatMessage(msg, err)) 2498 2499 self.assertTrue(target.IsValid(), "Got invalid target without error") 2500 return target 2501 2502 # ================================================= 2503 # Misc. helper methods for debugging test execution 2504 # ================================================= 2505 2506 def DebugSBValue(self, val): 2507 """Debug print a SBValue object, if traceAlways is True.""" 2508 from .lldbutil import value_type_to_str 2509 2510 if not traceAlways: 2511 return 2512 2513 err = sys.stderr 2514 err.write(val.GetName() + ":\n") 2515 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 2516 err.write('\t' + "ByteSize -> " + 2517 str(val.GetByteSize()) + '\n') 2518 err.write('\t' + "NumChildren -> " + 2519 str(val.GetNumChildren()) + '\n') 2520 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') 2521 err.write('\t' + "ValueAsUnsigned -> " + 2522 str(val.GetValueAsUnsigned()) + '\n') 2523 err.write( 2524 '\t' + 2525 "ValueType -> " + 2526 value_type_to_str( 2527 val.GetValueType()) + 2528 '\n') 2529 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') 2530 err.write('\t' + "IsPointerType -> " + 2531 str(val.TypeIsPointerType()) + '\n') 2532 err.write('\t' + "Location -> " + val.GetLocation() + '\n') 2533 2534 def DebugSBType(self, type): 2535 """Debug print a SBType object, if traceAlways is True.""" 2536 if not traceAlways: 2537 return 2538 2539 err = sys.stderr 2540 err.write(type.GetName() + ":\n") 2541 err.write('\t' + "ByteSize -> " + 2542 str(type.GetByteSize()) + '\n') 2543 err.write('\t' + "IsAggregateType -> " + 2544 str(type.IsAggregateType()) + '\n') 2545 err.write('\t' + "IsPointerType -> " + 2546 str(type.IsPointerType()) + '\n') 2547 err.write('\t' + "IsReferenceType -> " + 2548 str(type.IsReferenceType()) + '\n') 2549 2550 def DebugPExpect(self, child): 2551 """Debug the spwaned pexpect object.""" 2552 if not traceAlways: 2553 return 2554 2555 print(child) 2556 2557 @classmethod 2558 def RemoveTempFile(cls, file): 2559 if os.path.exists(file): 2560 remove_file(file) 2561 2562# On Windows, the first attempt to delete a recently-touched file can fail 2563# because of a race with antimalware scanners. This function will detect a 2564# failure and retry. 2565 2566 2567def remove_file(file, num_retries=1, sleep_duration=0.5): 2568 for i in range(num_retries + 1): 2569 try: 2570 os.remove(file) 2571 return True 2572 except: 2573 time.sleep(sleep_duration) 2574 continue 2575 return False 2576