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