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