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