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, extra_env): 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, extra_env): 383 env=None 384 if extra_env: 385 env = dict(os.environ) 386 env.update([kv.split("=", 1) for kv in extra_env]) 387 388 self._proc = Popen( 389 [executable] + args, 390 stdout=open( 391 os.devnull) if not self._trace_on else None, 392 stdin=PIPE, 393 preexec_fn=lldbplatformutil.enable_attach, 394 env=env) 395 396 def terminate(self): 397 if self._proc.poll() is None: 398 # Terminate _proc like it does the pexpect 399 signals_to_try = [ 400 sig for sig in [ 401 'SIGHUP', 402 'SIGCONT', 403 'SIGINT'] if sig in dir(signal)] 404 for sig in signals_to_try: 405 try: 406 self._proc.send_signal(getattr(signal, sig)) 407 time.sleep(self._delayafterterminate) 408 if self._proc.poll() is not None: 409 return 410 except ValueError: 411 pass # Windows says SIGINT is not a valid signal to send 412 self._proc.terminate() 413 time.sleep(self._delayafterterminate) 414 if self._proc.poll() is not None: 415 return 416 self._proc.kill() 417 time.sleep(self._delayafterterminate) 418 419 def poll(self): 420 return self._proc.poll() 421 422 423class _RemoteProcess(_BaseProcess): 424 425 def __init__(self, install_remote): 426 self._pid = None 427 self._install_remote = install_remote 428 429 @property 430 def pid(self): 431 return self._pid 432 433 def launch(self, executable, args, extra_env): 434 if self._install_remote: 435 src_path = executable 436 dst_path = lldbutil.join_remote_paths( 437 lldb.remote_platform.GetWorkingDirectory(), os.path.basename(executable)) 438 439 dst_file_spec = lldb.SBFileSpec(dst_path, False) 440 err = lldb.remote_platform.Install( 441 lldb.SBFileSpec(src_path, True), dst_file_spec) 442 if err.Fail(): 443 raise Exception( 444 "remote_platform.Install('%s', '%s') failed: %s" % 445 (src_path, dst_path, err)) 446 else: 447 dst_path = executable 448 dst_file_spec = lldb.SBFileSpec(executable, False) 449 450 launch_info = lldb.SBLaunchInfo(args) 451 launch_info.SetExecutableFile(dst_file_spec, True) 452 launch_info.SetWorkingDirectory( 453 lldb.remote_platform.GetWorkingDirectory()) 454 455 # Redirect stdout and stderr to /dev/null 456 launch_info.AddSuppressFileAction(1, False, True) 457 launch_info.AddSuppressFileAction(2, False, True) 458 459 if extra_env: 460 launch_info.SetEnvironmentEntries(extra_env, True) 461 462 err = lldb.remote_platform.Launch(launch_info) 463 if err.Fail(): 464 raise Exception( 465 "remote_platform.Launch('%s', '%s') failed: %s" % 466 (dst_path, args, err)) 467 self._pid = launch_info.GetProcessID() 468 469 def terminate(self): 470 lldb.remote_platform.Kill(self._pid) 471 472# From 2.7's subprocess.check_output() convenience function. 473# Return a tuple (stdoutdata, stderrdata). 474 475 476def system(commands, **kwargs): 477 r"""Run an os command with arguments and return its output as a byte string. 478 479 If the exit code was non-zero it raises a CalledProcessError. The 480 CalledProcessError object will have the return code in the returncode 481 attribute and output in the output attribute. 482 483 The arguments are the same as for the Popen constructor. Example: 484 485 >>> check_output(["ls", "-l", "/dev/null"]) 486 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' 487 488 The stdout argument is not allowed as it is used internally. 489 To capture standard error in the result, use stderr=STDOUT. 490 491 >>> check_output(["/bin/sh", "-c", 492 ... "ls -l non_existent_file ; exit 0"], 493 ... stderr=STDOUT) 494 'ls: non_existent_file: No such file or directory\n' 495 """ 496 497 # Assign the sender object to variable 'test' and remove it from kwargs. 498 test = kwargs.pop('sender', None) 499 500 # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo'] 501 commandList = [' '.join(x) for x in commands] 502 output = "" 503 error = "" 504 for shellCommand in commandList: 505 if 'stdout' in kwargs: 506 raise ValueError( 507 'stdout argument not allowed, it will be overridden.') 508 if 'shell' in kwargs and kwargs['shell'] == False: 509 raise ValueError('shell=False not allowed') 510 process = Popen( 511 shellCommand, 512 stdout=PIPE, 513 stderr=STDOUT, 514 shell=True, 515 **kwargs) 516 pid = process.pid 517 this_output, this_error = process.communicate() 518 retcode = process.poll() 519 520 if retcode: 521 cmd = kwargs.get("args") 522 if cmd is None: 523 cmd = shellCommand 524 cpe = CalledProcessError(retcode, cmd) 525 # Ensure caller can access the stdout/stderr. 526 cpe.lldb_extensions = { 527 "combined_output": this_output, 528 "command": shellCommand 529 } 530 raise cpe 531 output = output + this_output.decode("utf-8", errors='ignore') 532 return output 533 534 535def getsource_if_available(obj): 536 """ 537 Return the text of the source code for an object if available. Otherwise, 538 a print representation is returned. 539 """ 540 import inspect 541 try: 542 return inspect.getsource(obj) 543 except: 544 return repr(obj) 545 546 547def builder_module(): 548 return get_builder(sys.platform) 549 550 551class Base(unittest2.TestCase): 552 """ 553 Abstract base for performing lldb (see TestBase) or other generic tests (see 554 BenchBase for one example). lldbtest.Base works with the test driver to 555 accomplish things. 556 557 """ 558 559 # The concrete subclass should override this attribute. 560 mydir = None 561 562 # Keep track of the old current working directory. 563 oldcwd = None 564 565 @staticmethod 566 def compute_mydir(test_file): 567 '''Subclasses should call this function to correctly calculate the 568 required "mydir" attribute as follows: 569 570 mydir = TestBase.compute_mydir(__file__) 571 ''' 572 # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir 573 lldb_test_src = configuration.test_src_root 574 if not test_file.startswith(lldb_test_src): 575 raise Exception( 576 "Test file '%s' must reside within lldb_test_src " 577 "(which is '%s')." % (test_file, lldb_test_src)) 578 return os.path.dirname(os.path.relpath(test_file, start=lldb_test_src)) 579 580 def TraceOn(self): 581 """Returns True if we are in trace mode (tracing detailed test execution).""" 582 return traceAlways 583 584 def trace(self, *args,**kwargs): 585 with recording(self, self.TraceOn()) as sbuf: 586 print(*args, file=sbuf, **kwargs) 587 588 @classmethod 589 def setUpClass(cls): 590 """ 591 Python unittest framework class setup fixture. 592 Do current directory manipulation. 593 """ 594 # Fail fast if 'mydir' attribute is not overridden. 595 if not cls.mydir or len(cls.mydir) == 0: 596 raise Exception("Subclasses must override the 'mydir' attribute.") 597 598 # Save old working directory. 599 cls.oldcwd = os.getcwd() 600 601 full_dir = os.path.join(configuration.test_src_root, cls.mydir) 602 if traceAlways: 603 print("Change dir to:", full_dir, file=sys.stderr) 604 os.chdir(full_dir) 605 lldb.SBReproducer.SetWorkingDirectory(full_dir) 606 607 # Set platform context. 608 cls.platformContext = lldbplatformutil.createPlatformContext() 609 610 @classmethod 611 def tearDownClass(cls): 612 """ 613 Python unittest framework class teardown fixture. 614 Do class-wide cleanup. 615 """ 616 617 if doCleanup: 618 # First, let's do the platform-specific cleanup. 619 module = builder_module() 620 module.cleanup() 621 622 # Subclass might have specific cleanup function defined. 623 if getattr(cls, "classCleanup", None): 624 if traceAlways: 625 print( 626 "Call class-specific cleanup function for class:", 627 cls, 628 file=sys.stderr) 629 try: 630 cls.classCleanup() 631 except: 632 exc_type, exc_value, exc_tb = sys.exc_info() 633 traceback.print_exception(exc_type, exc_value, exc_tb) 634 635 # Restore old working directory. 636 if traceAlways: 637 print("Restore dir to:", cls.oldcwd, file=sys.stderr) 638 os.chdir(cls.oldcwd) 639 640 def enableLogChannelsForCurrentTest(self): 641 if len(lldbtest_config.channels) == 0: 642 return 643 644 # if debug channels are specified in lldbtest_config.channels, 645 # create a new set of log files for every test 646 log_basename = self.getLogBasenameForCurrentTest() 647 648 # confirm that the file is writeable 649 host_log_path = "{}-host.log".format(log_basename) 650 open(host_log_path, 'w').close() 651 self.log_files.append(host_log_path) 652 653 log_enable = "log enable -Tpn -f {} ".format(host_log_path) 654 for channel_with_categories in lldbtest_config.channels: 655 channel_then_categories = channel_with_categories.split(' ', 1) 656 channel = channel_then_categories[0] 657 if len(channel_then_categories) > 1: 658 categories = channel_then_categories[1] 659 else: 660 categories = "default" 661 662 if channel == "gdb-remote" and lldb.remote_platform is None: 663 # communicate gdb-remote categories to debugserver 664 os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories 665 666 self.ci.HandleCommand( 667 log_enable + channel_with_categories, self.res) 668 if not self.res.Succeeded(): 669 raise Exception( 670 'log enable failed (check LLDB_LOG_OPTION env variable)') 671 672 # Communicate log path name to debugserver & lldb-server 673 # For remote debugging, these variables need to be set when starting the platform 674 # instance. 675 if lldb.remote_platform is None: 676 server_log_path = "{}-server.log".format(log_basename) 677 open(server_log_path, 'w').close() 678 self.log_files.append(server_log_path) 679 os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path 680 681 # Communicate channels to lldb-server 682 os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join( 683 lldbtest_config.channels) 684 685 self.addTearDownHook(self.disableLogChannelsForCurrentTest) 686 687 def disableLogChannelsForCurrentTest(self): 688 # close all log files that we opened 689 for channel_and_categories in lldbtest_config.channels: 690 # channel format - <channel-name> [<category0> [<category1> ...]] 691 channel = channel_and_categories.split(' ', 1)[0] 692 self.ci.HandleCommand("log disable " + channel, self.res) 693 if not self.res.Succeeded(): 694 raise Exception( 695 'log disable failed (check LLDB_LOG_OPTION env variable)') 696 697 # Retrieve the server log (if any) from the remote system. It is assumed the server log 698 # is writing to the "server.log" file in the current test directory. This can be 699 # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote 700 # platform. 701 if lldb.remote_platform: 702 server_log_path = self.getLogBasenameForCurrentTest() + "-server.log" 703 if lldb.remote_platform.Get( 704 lldb.SBFileSpec("server.log"), 705 lldb.SBFileSpec(server_log_path)).Success(): 706 self.log_files.append(server_log_path) 707 708 def setPlatformWorkingDir(self): 709 if not lldb.remote_platform or not configuration.lldb_platform_working_dir: 710 return 711 712 components = self.mydir.split(os.path.sep) + [str(self.test_number), self.getBuildDirBasename()] 713 remote_test_dir = configuration.lldb_platform_working_dir 714 for c in components: 715 remote_test_dir = lldbutil.join_remote_paths(remote_test_dir, c) 716 error = lldb.remote_platform.MakeDirectory( 717 remote_test_dir, 448) # 448 = 0o700 718 if error.Fail(): 719 raise Exception("making remote directory '%s': %s" % ( 720 remote_test_dir, error)) 721 722 lldb.remote_platform.SetWorkingDirectory(remote_test_dir) 723 724 # This function removes all files from the current working directory while leaving 725 # the directories in place. The cleanup is required to reduce the disk space required 726 # by the test suite while leaving the directories untouched is neccessary because 727 # sub-directories might belong to an other test 728 def clean_working_directory(): 729 # TODO: Make it working on Windows when we need it for remote debugging support 730 # TODO: Replace the heuristic to remove the files with a logic what collects the 731 # list of files we have to remove during test runs. 732 shell_cmd = lldb.SBPlatformShellCommand( 733 "rm %s/*" % remote_test_dir) 734 lldb.remote_platform.Run(shell_cmd) 735 self.addTearDownHook(clean_working_directory) 736 737 def getSourceDir(self): 738 """Return the full path to the current test.""" 739 return os.path.join(configuration.test_src_root, self.mydir) 740 741 def getBuildDirBasename(self): 742 return self.__class__.__module__ + "." + self.testMethodName 743 744 def getBuildDir(self): 745 """Return the full path to the current test.""" 746 return os.path.join(configuration.test_build_dir, self.mydir, 747 self.getBuildDirBasename()) 748 749 def makeBuildDir(self): 750 """Create the test-specific working directory, deleting any previous 751 contents.""" 752 bdir = self.getBuildDir() 753 if os.path.isdir(bdir): 754 shutil.rmtree(bdir) 755 lldbutil.mkdir_p(bdir) 756 757 def getBuildArtifact(self, name="a.out"): 758 """Return absolute path to an artifact in the test's build directory.""" 759 return os.path.join(self.getBuildDir(), name) 760 761 def getSourcePath(self, name): 762 """Return absolute path to a file in the test's source directory.""" 763 return os.path.join(self.getSourceDir(), name) 764 765 @classmethod 766 def setUpCommands(cls): 767 commands = [ 768 # First of all, clear all settings to have clean state of global properties. 769 "settings clear -all", 770 771 # Disable Spotlight lookup. The testsuite creates 772 # different binaries with the same UUID, because they only 773 # differ in the debug info, which is not being hashed. 774 "settings set symbols.enable-external-lookup false", 775 776 # Inherit the TCC permissions from the inferior's parent. 777 "settings set target.inherit-tcc true", 778 779 # Kill rather than detach from the inferior if something goes wrong. 780 "settings set target.detach-on-error false", 781 782 # Disable fix-its by default so that incorrect expressions in tests don't 783 # pass just because Clang thinks it has a fix-it. 784 "settings set target.auto-apply-fixits false", 785 786 # Testsuite runs in parallel and the host can have also other load. 787 "settings set plugin.process.gdb-remote.packet-timeout 60", 788 789 'settings set symbols.clang-modules-cache-path "{}"'.format( 790 configuration.lldb_module_cache_dir), 791 "settings set use-color false", 792 ] 793 794 # Set any user-overridden settings. 795 for setting, value in configuration.settings: 796 commands.append('setting set %s %s'%(setting, value)) 797 798 # Make sure that a sanitizer LLDB's environment doesn't get passed on. 799 if cls.platformContext and cls.platformContext.shlib_environment_var in os.environ: 800 commands.append('settings set target.env-vars {}='.format( 801 cls.platformContext.shlib_environment_var)) 802 803 # Set environment variables for the inferior. 804 if lldbtest_config.inferior_env: 805 commands.append('settings set target.env-vars {}'.format( 806 lldbtest_config.inferior_env)) 807 return commands 808 809 def setUp(self): 810 """Fixture for unittest test case setup. 811 812 It works with the test driver to conditionally skip tests and does other 813 initializations.""" 814 #import traceback 815 # traceback.print_stack() 816 817 if "LIBCXX_PATH" in os.environ: 818 self.libcxxPath = os.environ["LIBCXX_PATH"] 819 else: 820 self.libcxxPath = None 821 822 if "LLDBVSCODE_EXEC" in os.environ: 823 self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"] 824 else: 825 self.lldbVSCodeExec = None 826 827 self.lldbOption = " ".join( 828 "-o '" + s + "'" for s in self.setUpCommands()) 829 830 # If we spawn an lldb process for test (via pexpect), do not load the 831 # init file unless told otherwise. 832 if os.environ.get("NO_LLDBINIT") != "NO": 833 self.lldbOption += " --no-lldbinit" 834 835 # Assign the test method name to self.testMethodName. 836 # 837 # For an example of the use of this attribute, look at test/types dir. 838 # There are a bunch of test cases under test/types and we don't want the 839 # module cacheing subsystem to be confused with executable name "a.out" 840 # used for all the test cases. 841 self.testMethodName = self._testMethodName 842 843 # This is for the case of directly spawning 'lldb'/'gdb' and interacting 844 # with it using pexpect. 845 self.child = None 846 self.child_prompt = "(lldb) " 847 # If the child is interacting with the embedded script interpreter, 848 # there are two exits required during tear down, first to quit the 849 # embedded script interpreter and second to quit the lldb command 850 # interpreter. 851 self.child_in_script_interpreter = False 852 853 # These are for customized teardown cleanup. 854 self.dict = None 855 self.doTearDownCleanup = False 856 # And in rare cases where there are multiple teardown cleanups. 857 self.dicts = [] 858 self.doTearDownCleanups = False 859 860 # List of spawned subproces.Popen objects 861 self.subprocesses = [] 862 863 # List of log files produced by the current test. 864 self.log_files = [] 865 866 # Create the build directory. 867 # The logs are stored in the build directory, so we have to create it 868 # before creating the first log file. 869 self.makeBuildDir() 870 871 session_file = self.getLogBasenameForCurrentTest()+".log" 872 self.log_files.append(session_file) 873 874 # Python 3 doesn't support unbuffered I/O in text mode. Open buffered. 875 self.session = encoded_file.open(session_file, "utf-8", mode="w") 876 877 # Optimistically set __errored__, __failed__, __expected__ to False 878 # initially. If the test errored/failed, the session info 879 # (self.session) is then dumped into a session specific file for 880 # diagnosis. 881 self.__cleanup_errored__ = False 882 self.__errored__ = False 883 self.__failed__ = False 884 self.__expected__ = False 885 # We are also interested in unexpected success. 886 self.__unexpected__ = False 887 # And skipped tests. 888 self.__skipped__ = False 889 890 # See addTearDownHook(self, hook) which allows the client to add a hook 891 # function to be run during tearDown() time. 892 self.hooks = [] 893 894 # See HideStdout(self). 895 self.sys_stdout_hidden = False 896 897 if self.platformContext: 898 # set environment variable names for finding shared libraries 899 self.dylibPath = self.platformContext.shlib_environment_var 900 901 # Create the debugger instance. 902 self.dbg = lldb.SBDebugger.Create() 903 # Copy selected platform from a global instance if it exists. 904 if lldb.selected_platform is not None: 905 self.dbg.SetSelectedPlatform(lldb.selected_platform) 906 907 if not self.dbg: 908 raise Exception('Invalid debugger instance') 909 910 # Retrieve the associated command interpreter instance. 911 self.ci = self.dbg.GetCommandInterpreter() 912 if not self.ci: 913 raise Exception('Could not get the command interpreter') 914 915 # And the result object. 916 self.res = lldb.SBCommandReturnObject() 917 918 self.setPlatformWorkingDir() 919 self.enableLogChannelsForCurrentTest() 920 921 self.lib_lldb = None 922 self.framework_dir = None 923 self.darwinWithFramework = False 924 925 if sys.platform.startswith("darwin") and configuration.lldb_framework_path: 926 framework = configuration.lldb_framework_path 927 lib = os.path.join(framework, 'LLDB') 928 if os.path.exists(lib): 929 self.framework_dir = os.path.dirname(framework) 930 self.lib_lldb = lib 931 self.darwinWithFramework = self.platformIsDarwin() 932 933 def setAsync(self, value): 934 """ Sets async mode to True/False and ensures it is reset after the testcase completes.""" 935 old_async = self.dbg.GetAsync() 936 self.dbg.SetAsync(value) 937 self.addTearDownHook(lambda: self.dbg.SetAsync(old_async)) 938 939 def cleanupSubprocesses(self): 940 # Terminate subprocesses in reverse order from how they were created. 941 for p in reversed(self.subprocesses): 942 p.terminate() 943 del p 944 del self.subprocesses[:] 945 946 def spawnSubprocess(self, executable, args=[], extra_env=None, install_remote=True): 947 """ Creates a subprocess.Popen object with the specified executable and arguments, 948 saves it in self.subprocesses, and returns the object. 949 """ 950 proc = _RemoteProcess( 951 install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn()) 952 proc.launch(executable, args, extra_env=extra_env) 953 self.subprocesses.append(proc) 954 return proc 955 956 def HideStdout(self): 957 """Hide output to stdout from the user. 958 959 During test execution, there might be cases where we don't want to show the 960 standard output to the user. For example, 961 962 self.runCmd(r'''sc print("\n\n\tHello!\n")''') 963 964 tests whether command abbreviation for 'script' works or not. There is no 965 need to show the 'Hello' output to the user as long as the 'script' command 966 succeeds and we are not in TraceOn() mode (see the '-t' option). 967 968 In this case, the test method calls self.HideStdout(self) to redirect the 969 sys.stdout to a null device, and restores the sys.stdout upon teardown. 970 971 Note that you should only call this method at most once during a test case 972 execution. Any subsequent call has no effect at all.""" 973 if self.sys_stdout_hidden: 974 return 975 976 self.sys_stdout_hidden = True 977 old_stdout = sys.stdout 978 sys.stdout = open(os.devnull, 'w') 979 980 def restore_stdout(): 981 sys.stdout = old_stdout 982 self.addTearDownHook(restore_stdout) 983 984 # ======================================================================= 985 # Methods for customized teardown cleanups as well as execution of hooks. 986 # ======================================================================= 987 988 def setTearDownCleanup(self, dictionary=None): 989 """Register a cleanup action at tearDown() time with a dictionary""" 990 self.dict = dictionary 991 self.doTearDownCleanup = True 992 993 def addTearDownCleanup(self, dictionary): 994 """Add a cleanup action at tearDown() time with a dictionary""" 995 self.dicts.append(dictionary) 996 self.doTearDownCleanups = True 997 998 def addTearDownHook(self, hook): 999 """ 1000 Add a function to be run during tearDown() time. 1001 1002 Hooks are executed in a first come first serve manner. 1003 """ 1004 if six.callable(hook): 1005 with recording(self, traceAlways) as sbuf: 1006 print( 1007 "Adding tearDown hook:", 1008 getsource_if_available(hook), 1009 file=sbuf) 1010 self.hooks.append(hook) 1011 1012 return self 1013 1014 def deletePexpectChild(self): 1015 # This is for the case of directly spawning 'lldb' and interacting with it 1016 # using pexpect. 1017 if self.child and self.child.isalive(): 1018 import pexpect 1019 with recording(self, traceAlways) as sbuf: 1020 print("tearing down the child process....", file=sbuf) 1021 try: 1022 if self.child_in_script_interpreter: 1023 self.child.sendline('quit()') 1024 self.child.expect_exact(self.child_prompt) 1025 self.child.sendline( 1026 'settings set interpreter.prompt-on-quit false') 1027 self.child.sendline('quit') 1028 self.child.expect(pexpect.EOF) 1029 except (ValueError, pexpect.ExceptionPexpect): 1030 # child is already terminated 1031 pass 1032 except OSError as exception: 1033 import errno 1034 if exception.errno != errno.EIO: 1035 # unexpected error 1036 raise 1037 # child is already terminated 1038 finally: 1039 # Give it one final blow to make sure the child is terminated. 1040 self.child.close() 1041 1042 def tearDown(self): 1043 """Fixture for unittest test case teardown.""" 1044 self.deletePexpectChild() 1045 1046 # Check and run any hook functions. 1047 for hook in reversed(self.hooks): 1048 with recording(self, traceAlways) as sbuf: 1049 print( 1050 "Executing tearDown hook:", 1051 getsource_if_available(hook), 1052 file=sbuf) 1053 if funcutils.requires_self(hook): 1054 hook(self) 1055 else: 1056 hook() # try the plain call and hope it works 1057 1058 del self.hooks 1059 1060 # Perform registered teardown cleanup. 1061 if doCleanup and self.doTearDownCleanup: 1062 self.cleanup(dictionary=self.dict) 1063 1064 # In rare cases where there are multiple teardown cleanups added. 1065 if doCleanup and self.doTearDownCleanups: 1066 if self.dicts: 1067 for dict in reversed(self.dicts): 1068 self.cleanup(dictionary=dict) 1069 1070 # Remove subprocesses created by the test. 1071 self.cleanupSubprocesses() 1072 1073 # This must be the last statement, otherwise teardown hooks or other 1074 # lines might depend on this still being active. 1075 lldb.SBDebugger.Destroy(self.dbg) 1076 del self.dbg 1077 1078 # All modules should be orphaned now so that they can be cleared from 1079 # the shared module cache. 1080 lldb.SBModule.GarbageCollectAllocatedModules() 1081 1082 # Assert that the global module cache is empty. 1083 self.assertEqual(lldb.SBModule.GetNumberAllocatedModules(), 0) 1084 1085 1086 # ========================================================= 1087 # Various callbacks to allow introspection of test progress 1088 # ========================================================= 1089 1090 def markError(self): 1091 """Callback invoked when an error (unexpected exception) errored.""" 1092 self.__errored__ = True 1093 with recording(self, False) as sbuf: 1094 # False because there's no need to write "ERROR" to the stderr twice. 1095 # Once by the Python unittest framework, and a second time by us. 1096 print("ERROR", file=sbuf) 1097 1098 def markCleanupError(self): 1099 """Callback invoked when an error occurs while a test is cleaning up.""" 1100 self.__cleanup_errored__ = True 1101 with recording(self, False) as sbuf: 1102 # False because there's no need to write "CLEANUP_ERROR" to the stderr twice. 1103 # Once by the Python unittest framework, and a second time by us. 1104 print("CLEANUP_ERROR", file=sbuf) 1105 1106 def markFailure(self): 1107 """Callback invoked when a failure (test assertion failure) occurred.""" 1108 self.__failed__ = True 1109 with recording(self, False) as sbuf: 1110 # False because there's no need to write "FAIL" to the stderr twice. 1111 # Once by the Python unittest framework, and a second time by us. 1112 print("FAIL", file=sbuf) 1113 1114 def markExpectedFailure(self, err, bugnumber): 1115 """Callback invoked when an expected failure/error occurred.""" 1116 self.__expected__ = True 1117 with recording(self, False) as sbuf: 1118 # False because there's no need to write "expected failure" to the 1119 # stderr twice. 1120 # Once by the Python unittest framework, and a second time by us. 1121 if bugnumber is None: 1122 print("expected failure", file=sbuf) 1123 else: 1124 print( 1125 "expected failure (problem id:" + str(bugnumber) + ")", 1126 file=sbuf) 1127 1128 def markSkippedTest(self): 1129 """Callback invoked when a test is skipped.""" 1130 self.__skipped__ = True 1131 with recording(self, False) as sbuf: 1132 # False because there's no need to write "skipped test" to the 1133 # stderr twice. 1134 # Once by the Python unittest framework, and a second time by us. 1135 print("skipped test", file=sbuf) 1136 1137 def markUnexpectedSuccess(self, bugnumber): 1138 """Callback invoked when an unexpected success occurred.""" 1139 self.__unexpected__ = True 1140 with recording(self, False) as sbuf: 1141 # False because there's no need to write "unexpected success" to the 1142 # stderr twice. 1143 # Once by the Python unittest framework, and a second time by us. 1144 if bugnumber is None: 1145 print("unexpected success", file=sbuf) 1146 else: 1147 print( 1148 "unexpected success (problem id:" + str(bugnumber) + ")", 1149 file=sbuf) 1150 1151 def getRerunArgs(self): 1152 return " -f %s.%s" % (self.__class__.__name__, self._testMethodName) 1153 1154 def getLogBasenameForCurrentTest(self, prefix="Incomplete"): 1155 """ 1156 returns a partial path that can be used as the beginning of the name of multiple 1157 log files pertaining to this test 1158 """ 1159 return os.path.join(self.getBuildDir(), prefix) 1160 1161 def dumpSessionInfo(self): 1162 """ 1163 Dump the debugger interactions leading to a test error/failure. This 1164 allows for more convenient postmortem analysis. 1165 1166 See also LLDBTestResult (dotest.py) which is a singlton class derived 1167 from TextTestResult and overwrites addError, addFailure, and 1168 addExpectedFailure methods to allow us to to mark the test instance as 1169 such. 1170 """ 1171 1172 # We are here because self.tearDown() detected that this test instance 1173 # either errored or failed. The lldb.test_result singleton contains 1174 # two lists (errors and failures) which get populated by the unittest 1175 # framework. Look over there for stack trace information. 1176 # 1177 # The lists contain 2-tuples of TestCase instances and strings holding 1178 # formatted tracebacks. 1179 # 1180 # See http://docs.python.org/library/unittest.html#unittest.TestResult. 1181 1182 # output tracebacks into session 1183 pairs = [] 1184 if self.__errored__: 1185 pairs = configuration.test_result.errors 1186 prefix = 'Error' 1187 elif self.__cleanup_errored__: 1188 pairs = configuration.test_result.cleanup_errors 1189 prefix = 'CleanupError' 1190 elif self.__failed__: 1191 pairs = configuration.test_result.failures 1192 prefix = 'Failure' 1193 elif self.__expected__: 1194 pairs = configuration.test_result.expectedFailures 1195 prefix = 'ExpectedFailure' 1196 elif self.__skipped__: 1197 prefix = 'SkippedTest' 1198 elif self.__unexpected__: 1199 prefix = 'UnexpectedSuccess' 1200 else: 1201 prefix = 'Success' 1202 1203 if not self.__unexpected__ and not self.__skipped__: 1204 for test, traceback in pairs: 1205 if test is self: 1206 print(traceback, file=self.session) 1207 1208 import datetime 1209 print( 1210 "Session info generated @", 1211 datetime.datetime.now().ctime(), 1212 file=self.session) 1213 self.session.close() 1214 del self.session 1215 1216 # process the log files 1217 if prefix != 'Success' or lldbtest_config.log_success: 1218 # keep all log files, rename them to include prefix 1219 src_log_basename = self.getLogBasenameForCurrentTest() 1220 dst_log_basename = self.getLogBasenameForCurrentTest(prefix) 1221 for src in self.log_files: 1222 if os.path.isfile(src): 1223 dst = src.replace(src_log_basename, dst_log_basename) 1224 if os.name == "nt" and os.path.isfile(dst): 1225 # On Windows, renaming a -> b will throw an exception if 1226 # b exists. On non-Windows platforms it silently 1227 # replaces the destination. Ultimately this means that 1228 # atomic renames are not guaranteed to be possible on 1229 # Windows, but we need this to work anyway, so just 1230 # remove the destination first if it already exists. 1231 remove_file(dst) 1232 1233 lldbutil.mkdir_p(os.path.dirname(dst)) 1234 os.rename(src, dst) 1235 else: 1236 # success! (and we don't want log files) delete log files 1237 for log_file in self.log_files: 1238 if os.path.isfile(log_file): 1239 remove_file(log_file) 1240 1241 # ==================================================== 1242 # Config. methods supported through a plugin interface 1243 # (enables reading of the current test configuration) 1244 # ==================================================== 1245 1246 def isMIPS(self): 1247 """Returns true if the architecture is MIPS.""" 1248 arch = self.getArchitecture() 1249 if re.match("mips", arch): 1250 return True 1251 return False 1252 1253 def isPPC64le(self): 1254 """Returns true if the architecture is PPC64LE.""" 1255 arch = self.getArchitecture() 1256 if re.match("powerpc64le", arch): 1257 return True 1258 return False 1259 1260 def getCPUInfo(self): 1261 triple = self.dbg.GetSelectedPlatform().GetTriple() 1262 1263 # TODO other platforms, please implement this function 1264 if not re.match(".*-.*-linux", triple): 1265 return "" 1266 1267 # Need to do something different for non-Linux/Android targets 1268 cpuinfo_path = self.getBuildArtifact("cpuinfo") 1269 if configuration.lldb_platform_name: 1270 self.runCmd('platform get-file "/proc/cpuinfo" ' + cpuinfo_path) 1271 else: 1272 cpuinfo_path = "/proc/cpuinfo" 1273 1274 try: 1275 with open(cpuinfo_path, 'r') as f: 1276 cpuinfo = f.read() 1277 except: 1278 return "" 1279 1280 return cpuinfo 1281 1282 def isAArch64(self): 1283 """Returns true if the architecture is AArch64.""" 1284 arch = self.getArchitecture().lower() 1285 return arch in ["aarch64", "arm64", "arm64e"] 1286 1287 def isAArch64SVE(self): 1288 return self.isAArch64() and "sve" in self.getCPUInfo() 1289 1290 def isAArch64MTE(self): 1291 return self.isAArch64() and "mte" in self.getCPUInfo() 1292 1293 def isAArch64PAuth(self): 1294 return self.isAArch64() and "paca" in self.getCPUInfo() 1295 1296 def getArchitecture(self): 1297 """Returns the architecture in effect the test suite is running with.""" 1298 module = builder_module() 1299 arch = module.getArchitecture() 1300 if arch == 'amd64': 1301 arch = 'x86_64' 1302 if arch in ['armv7l', 'armv8l'] : 1303 arch = 'arm' 1304 return arch 1305 1306 def getLldbArchitecture(self): 1307 """Returns the architecture of the lldb binary.""" 1308 if not hasattr(self, 'lldbArchitecture'): 1309 1310 # spawn local process 1311 command = [ 1312 lldbtest_config.lldbExec, 1313 "-o", 1314 "file " + lldbtest_config.lldbExec, 1315 "-o", 1316 "quit" 1317 ] 1318 1319 output = check_output(command) 1320 str = output.decode("utf-8") 1321 1322 for line in str.splitlines(): 1323 m = re.search( 1324 "Current executable set to '.*' \\((.*)\\)\\.", line) 1325 if m: 1326 self.lldbArchitecture = m.group(1) 1327 break 1328 1329 return self.lldbArchitecture 1330 1331 def getCompiler(self): 1332 """Returns the compiler in effect the test suite is running with.""" 1333 module = builder_module() 1334 return module.getCompiler() 1335 1336 def getCompilerBinary(self): 1337 """Returns the compiler binary the test suite is running with.""" 1338 return self.getCompiler().split()[0] 1339 1340 def getCompilerVersion(self): 1341 """ Returns a string that represents the compiler version. 1342 Supports: llvm, clang. 1343 """ 1344 compiler = self.getCompilerBinary() 1345 version_output = system([[compiler, "--version"]]) 1346 for line in version_output.split(os.linesep): 1347 m = re.search('version ([0-9.]+)', line) 1348 if m: 1349 return m.group(1) 1350 return 'unknown' 1351 1352 def getDwarfVersion(self): 1353 """ Returns the dwarf version generated by clang or '0'. """ 1354 if configuration.dwarf_version: 1355 return str(configuration.dwarf_version) 1356 if 'clang' in self.getCompiler(): 1357 try: 1358 driver_output = check_output( 1359 [self.getCompiler()] + '-g -c -x c - -o - -###'.split(), 1360 stderr=STDOUT) 1361 driver_output = driver_output.decode("utf-8") 1362 for line in driver_output.split(os.linesep): 1363 m = re.search('dwarf-version=([0-9])', line) 1364 if m: 1365 return m.group(1) 1366 except: pass 1367 return '0' 1368 1369 def platformIsDarwin(self): 1370 """Returns true if the OS triple for the selected platform is any valid apple OS""" 1371 return lldbplatformutil.platformIsDarwin() 1372 1373 def hasDarwinFramework(self): 1374 return self.darwinWithFramework 1375 1376 def getPlatform(self): 1377 """Returns the target platform the test suite is running on.""" 1378 return lldbplatformutil.getPlatform() 1379 1380 def isIntelCompiler(self): 1381 """ Returns true if using an Intel (ICC) compiler, false otherwise. """ 1382 return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]]) 1383 1384 def expectedCompilerVersion(self, compiler_version): 1385 """Returns True iff compiler_version[1] matches the current compiler version. 1386 Use compiler_version[0] to specify the operator used to determine if a match has occurred. 1387 Any operator other than the following defaults to an equality test: 1388 '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' 1389 1390 If the current compiler version cannot be determined, we assume it is close to the top 1391 of trunk, so any less-than or equal-to comparisons will return False, and any 1392 greater-than or not-equal-to comparisons will return True. 1393 """ 1394 if compiler_version is None: 1395 return True 1396 operator = str(compiler_version[0]) 1397 version = compiler_version[1] 1398 1399 if version is None: 1400 return True 1401 1402 test_compiler_version = self.getCompilerVersion() 1403 if test_compiler_version == 'unknown': 1404 # Assume the compiler version is at or near the top of trunk. 1405 return operator in ['>', '>=', '!', '!=', 'not'] 1406 1407 if operator == '>': 1408 return LooseVersion(test_compiler_version) > LooseVersion(version) 1409 if operator == '>=' or operator == '=>': 1410 return LooseVersion(test_compiler_version) >= LooseVersion(version) 1411 if operator == '<': 1412 return LooseVersion(test_compiler_version) < LooseVersion(version) 1413 if operator == '<=' or operator == '=<': 1414 return LooseVersion(test_compiler_version) <= LooseVersion(version) 1415 if operator == '!=' or operator == '!' or operator == 'not': 1416 return str(version) not in str(test_compiler_version) 1417 return str(version) in str(test_compiler_version) 1418 1419 def expectedCompiler(self, compilers): 1420 """Returns True iff any element of compilers is a sub-string of the current compiler.""" 1421 if (compilers is None): 1422 return True 1423 1424 for compiler in compilers: 1425 if compiler in self.getCompiler(): 1426 return True 1427 1428 return False 1429 1430 def expectedArch(self, archs): 1431 """Returns True iff any element of archs is a sub-string of the current architecture.""" 1432 if (archs is None): 1433 return True 1434 1435 for arch in archs: 1436 if arch in self.getArchitecture(): 1437 return True 1438 1439 return False 1440 1441 def getRunOptions(self): 1442 """Command line option for -A and -C to run this test again, called from 1443 self.dumpSessionInfo().""" 1444 arch = self.getArchitecture() 1445 comp = self.getCompiler() 1446 option_str = "" 1447 if arch: 1448 option_str = "-A " + arch 1449 if comp: 1450 option_str += " -C " + comp 1451 return option_str 1452 1453 def getDebugInfo(self): 1454 method = getattr(self, self.testMethodName) 1455 return getattr(method, "debug_info", None) 1456 1457 # ================================================== 1458 # Build methods supported through a plugin interface 1459 # ================================================== 1460 1461 def getstdlibFlag(self): 1462 """ Returns the proper -stdlib flag, or empty if not required.""" 1463 if self.platformIsDarwin() or self.getPlatform() == "freebsd" or self.getPlatform() == "openbsd": 1464 stdlibflag = "-stdlib=libc++" 1465 else: # this includes NetBSD 1466 stdlibflag = "" 1467 return stdlibflag 1468 1469 def getstdFlag(self): 1470 """ Returns the proper stdflag. """ 1471 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1472 stdflag = "-std=c++0x" 1473 else: 1474 stdflag = "-std=c++11" 1475 return stdflag 1476 1477 def buildDriver(self, sources, exe_name): 1478 """ Platform-specific way to build a program that links with LLDB (via the liblldb.so 1479 or LLDB.framework). 1480 """ 1481 stdflag = self.getstdFlag() 1482 stdlibflag = self.getstdlibFlag() 1483 1484 lib_dir = configuration.lldb_libs_dir 1485 if self.hasDarwinFramework(): 1486 d = {'CXX_SOURCES': sources, 1487 'EXE': exe_name, 1488 'CFLAGS_EXTRAS': "%s %s" % (stdflag, stdlibflag), 1489 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, 1490 'LD_EXTRAS': "%s -Wl,-rpath,%s" % (self.lib_lldb, self.framework_dir), 1491 } 1492 elif sys.platform.startswith('win'): 1493 d = { 1494 'CXX_SOURCES': sources, 1495 'EXE': exe_name, 1496 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, 1497 stdlibflag, 1498 os.path.join( 1499 os.environ["LLDB_SRC"], 1500 "include")), 1501 'LD_EXTRAS': "-L%s -lliblldb" % lib_dir} 1502 else: 1503 d = { 1504 'CXX_SOURCES': sources, 1505 'EXE': exe_name, 1506 'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, 1507 stdlibflag, 1508 os.path.join( 1509 os.environ["LLDB_SRC"], 1510 "include")), 1511 'LD_EXTRAS': "-L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)} 1512 if self.TraceOn(): 1513 print( 1514 "Building LLDB Driver (%s) from sources %s" % 1515 (exe_name, sources)) 1516 1517 self.buildDefault(dictionary=d) 1518 1519 def buildLibrary(self, sources, lib_name): 1520 """Platform specific way to build a default library. """ 1521 1522 stdflag = self.getstdFlag() 1523 1524 lib_dir = configuration.lldb_libs_dir 1525 if self.hasDarwinFramework(): 1526 d = {'DYLIB_CXX_SOURCES': sources, 1527 'DYLIB_NAME': lib_name, 1528 'CFLAGS_EXTRAS': "%s -stdlib=libc++" % stdflag, 1529 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, 1530 'LD_EXTRAS': "%s -Wl,-rpath,%s -dynamiclib" % (self.lib_lldb, self.framework_dir), 1531 } 1532 elif self.getPlatform() == 'windows': 1533 d = { 1534 'DYLIB_CXX_SOURCES': sources, 1535 'DYLIB_NAME': lib_name, 1536 'CFLAGS_EXTRAS': "%s -I%s " % (stdflag, 1537 os.path.join( 1538 os.environ["LLDB_SRC"], 1539 "include")), 1540 'LD_EXTRAS': "-shared -l%s\liblldb.lib" % lib_dir} 1541 else: 1542 d = { 1543 'DYLIB_CXX_SOURCES': sources, 1544 'DYLIB_NAME': lib_name, 1545 'CFLAGS_EXTRAS': "%s -I%s -fPIC" % (stdflag, 1546 os.path.join( 1547 os.environ["LLDB_SRC"], 1548 "include")), 1549 'LD_EXTRAS': "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir)} 1550 if self.TraceOn(): 1551 print( 1552 "Building LLDB Library (%s) from sources %s" % 1553 (lib_name, sources)) 1554 1555 self.buildDefault(dictionary=d) 1556 1557 def buildProgram(self, sources, exe_name): 1558 """ Platform specific way to build an executable from C/C++ sources. """ 1559 d = {'CXX_SOURCES': sources, 1560 'EXE': exe_name} 1561 self.buildDefault(dictionary=d) 1562 1563 def buildDefault( 1564 self, 1565 architecture=None, 1566 compiler=None, 1567 dictionary=None): 1568 """Platform specific way to build the default binaries.""" 1569 testdir = self.mydir 1570 testname = self.getBuildDirBasename() 1571 1572 if not architecture and configuration.arch: 1573 architecture = configuration.arch 1574 1575 if self.getDebugInfo(): 1576 raise Exception("buildDefault tests must set NO_DEBUG_INFO_TESTCASE") 1577 module = builder_module() 1578 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1579 if not module.buildDefault(self, architecture, compiler, 1580 dictionary, testdir, testname): 1581 raise Exception("Don't know how to build default binary") 1582 1583 def buildDsym( 1584 self, 1585 architecture=None, 1586 compiler=None, 1587 dictionary=None): 1588 """Platform specific way to build binaries with dsym info.""" 1589 testdir = self.mydir 1590 testname = self.getBuildDirBasename() 1591 if self.getDebugInfo() != "dsym": 1592 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1593 1594 module = builder_module() 1595 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1596 if not module.buildDsym(self, architecture, compiler, 1597 dictionary, testdir, testname): 1598 raise Exception("Don't know how to build binary with dsym") 1599 1600 def buildDwarf( 1601 self, 1602 architecture=None, 1603 compiler=None, 1604 dictionary=None): 1605 """Platform specific way to build binaries with dwarf maps.""" 1606 testdir = self.mydir 1607 testname = self.getBuildDirBasename() 1608 if self.getDebugInfo() != "dwarf": 1609 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1610 1611 module = builder_module() 1612 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1613 if not module.buildDwarf(self, architecture, compiler, 1614 dictionary, testdir, testname): 1615 raise Exception("Don't know how to build binary with dwarf") 1616 1617 def buildDwo( 1618 self, 1619 architecture=None, 1620 compiler=None, 1621 dictionary=None): 1622 """Platform specific way to build binaries with dwarf maps.""" 1623 testdir = self.mydir 1624 testname = self.getBuildDirBasename() 1625 if self.getDebugInfo() != "dwo": 1626 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1627 1628 module = builder_module() 1629 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1630 if not module.buildDwo(self, architecture, compiler, 1631 dictionary, testdir, testname): 1632 raise Exception("Don't know how to build binary with dwo") 1633 1634 def buildGModules( 1635 self, 1636 architecture=None, 1637 compiler=None, 1638 dictionary=None): 1639 """Platform specific way to build binaries with gmodules info.""" 1640 testdir = self.mydir 1641 testname = self.getBuildDirBasename() 1642 if self.getDebugInfo() != "gmodules": 1643 raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") 1644 1645 module = builder_module() 1646 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 1647 if not module.buildGModules(self, architecture, compiler, 1648 dictionary, testdir, testname): 1649 raise Exception("Don't know how to build binary with gmodules") 1650 1651 def signBinary(self, binary_path): 1652 if sys.platform.startswith("darwin"): 1653 codesign_cmd = "codesign --force --sign \"%s\" %s" % ( 1654 lldbtest_config.codesign_identity, binary_path) 1655 call(codesign_cmd, shell=True) 1656 1657 def findBuiltClang(self): 1658 """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler).""" 1659 paths_to_try = [ 1660 "llvm-build/Release+Asserts/x86_64/bin/clang", 1661 "llvm-build/Debug+Asserts/x86_64/bin/clang", 1662 "llvm-build/Release/x86_64/bin/clang", 1663 "llvm-build/Debug/x86_64/bin/clang", 1664 ] 1665 lldb_root_path = os.path.join( 1666 os.path.dirname(__file__), "..", "..", "..", "..") 1667 for p in paths_to_try: 1668 path = os.path.join(lldb_root_path, p) 1669 if os.path.exists(path): 1670 return path 1671 1672 # Tries to find clang at the same folder as the lldb 1673 lldb_dir = os.path.dirname(lldbtest_config.lldbExec) 1674 path = distutils.spawn.find_executable("clang", lldb_dir) 1675 if path is not None: 1676 return path 1677 1678 return os.environ["CC"] 1679 1680 1681 def yaml2obj(self, yaml_path, obj_path): 1682 """ 1683 Create an object file at the given path from a yaml file. 1684 1685 Throws subprocess.CalledProcessError if the object could not be created. 1686 """ 1687 yaml2obj_bin = configuration.get_yaml2obj_path() 1688 if not yaml2obj_bin: 1689 self.assertTrue(False, "No valid yaml2obj executable specified") 1690 command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path] 1691 system([command]) 1692 1693 def getBuildFlags( 1694 self, 1695 use_cpp11=True, 1696 use_libcxx=False, 1697 use_libstdcxx=False): 1698 """ Returns a dictionary (which can be provided to build* functions above) which 1699 contains OS-specific build flags. 1700 """ 1701 cflags = "" 1702 ldflags = "" 1703 1704 # On Mac OS X, unless specifically requested to use libstdc++, use 1705 # libc++ 1706 if not use_libstdcxx and self.platformIsDarwin(): 1707 use_libcxx = True 1708 1709 if use_libcxx and self.libcxxPath: 1710 cflags += "-stdlib=libc++ " 1711 if self.libcxxPath: 1712 libcxxInclude = os.path.join(self.libcxxPath, "include") 1713 libcxxLib = os.path.join(self.libcxxPath, "lib") 1714 if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib): 1715 cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % ( 1716 libcxxInclude, libcxxLib, libcxxLib) 1717 1718 if use_cpp11: 1719 cflags += "-std=" 1720 if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): 1721 cflags += "c++0x" 1722 else: 1723 cflags += "c++11" 1724 if self.platformIsDarwin() or self.getPlatform() == "freebsd": 1725 cflags += " -stdlib=libc++" 1726 elif self.getPlatform() == "openbsd": 1727 cflags += " -stdlib=libc++" 1728 elif self.getPlatform() == "netbsd": 1729 # NetBSD defaults to libc++ 1730 pass 1731 elif "clang" in self.getCompiler(): 1732 cflags += " -stdlib=libstdc++" 1733 1734 return {'CFLAGS_EXTRAS': cflags, 1735 'LD_EXTRAS': ldflags, 1736 } 1737 1738 def cleanup(self, dictionary=None): 1739 """Platform specific way to do cleanup after build.""" 1740 module = builder_module() 1741 if not module.cleanup(self, dictionary): 1742 raise Exception( 1743 "Don't know how to do cleanup with dictionary: " + 1744 dictionary) 1745 1746 def invoke(self, obj, name, trace=False): 1747 """Use reflection to call a method dynamically with no argument.""" 1748 trace = (True if traceAlways else trace) 1749 1750 method = getattr(obj, name) 1751 import inspect 1752 self.assertTrue(inspect.ismethod(method), 1753 name + "is a method name of object: " + str(obj)) 1754 result = method() 1755 with recording(self, trace) as sbuf: 1756 print(str(method) + ":", result, file=sbuf) 1757 return result 1758 1759 def getLLDBLibraryEnvVal(self): 1760 """ Returns the path that the OS-specific library search environment variable 1761 (self.dylibPath) should be set to in order for a program to find the LLDB 1762 library. If an environment variable named self.dylibPath is already set, 1763 the new path is appended to it and returned. 1764 """ 1765 existing_library_path = os.environ[ 1766 self.dylibPath] if self.dylibPath in os.environ else None 1767 if existing_library_path: 1768 return "%s:%s" % (existing_library_path, configuration.lldb_libs_dir) 1769 if sys.platform.startswith("darwin") and configuration.lldb_framework_path: 1770 return configuration.lldb_framework_path 1771 return configuration.lldb_libs_dir 1772 1773 def getLibcPlusPlusLibs(self): 1774 if self.getPlatform() in ('freebsd', 'linux', 'netbsd', 'openbsd'): 1775 return ['libc++.so.1'] 1776 else: 1777 return ['libc++.1.dylib', 'libc++abi.'] 1778 1779 def run_platform_command(self, cmd): 1780 platform = self.dbg.GetSelectedPlatform() 1781 shell_command = lldb.SBPlatformShellCommand(cmd) 1782 err = platform.Run(shell_command) 1783 return (err, shell_command.GetStatus(), shell_command.GetOutput()) 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 # Assert that all targets are deleted. 2084 self.assertEqual(self.dbg.GetNumTargets(), 0) 2085 2086 # Do this last, to make sure it's in reverse order from how we setup. 2087 Base.tearDown(self) 2088 2089 def switch_to_thread_with_stop_reason(self, stop_reason): 2090 """ 2091 Run the 'thread list' command, and select the thread with stop reason as 2092 'stop_reason'. If no such thread exists, no select action is done. 2093 """ 2094 from .lldbutil import stop_reason_to_str 2095 self.runCmd('thread list') 2096 output = self.res.GetOutput() 2097 thread_line_pattern = re.compile( 2098 "^[ *] thread #([0-9]+):.*stop reason = %s" % 2099 stop_reason_to_str(stop_reason)) 2100 for line in output.splitlines(): 2101 matched = thread_line_pattern.match(line) 2102 if matched: 2103 self.runCmd('thread select %s' % matched.group(1)) 2104 2105 def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): 2106 """ 2107 Ask the command interpreter to handle the command and then check its 2108 return status. 2109 """ 2110 # Fail fast if 'cmd' is not meaningful. 2111 if cmd is None: 2112 raise Exception("Bad 'cmd' parameter encountered") 2113 2114 trace = (True if traceAlways else trace) 2115 2116 if cmd.startswith("target create "): 2117 cmd = cmd.replace("target create ", "file ") 2118 2119 running = (cmd.startswith("run") or cmd.startswith("process launch")) 2120 2121 for i in range(self.maxLaunchCount if running else 1): 2122 self.ci.HandleCommand(cmd, self.res, inHistory) 2123 2124 with recording(self, trace) as sbuf: 2125 print("runCmd:", cmd, file=sbuf) 2126 if not check: 2127 print("check of return status not required", file=sbuf) 2128 if self.res.Succeeded(): 2129 print("output:", self.res.GetOutput(), file=sbuf) 2130 else: 2131 print("runCmd failed!", file=sbuf) 2132 print(self.res.GetError(), file=sbuf) 2133 2134 if self.res.Succeeded(): 2135 break 2136 elif running: 2137 # For process launch, wait some time before possible next try. 2138 time.sleep(self.timeWaitNextLaunch) 2139 with recording(self, trace) as sbuf: 2140 print("Command '" + cmd + "' failed!", file=sbuf) 2141 2142 if check: 2143 output = "" 2144 if self.res.GetOutput(): 2145 output += "\nCommand output:\n" + self.res.GetOutput() 2146 if self.res.GetError(): 2147 output += "\nError output:\n" + self.res.GetError() 2148 if msg: 2149 msg += output 2150 if cmd: 2151 cmd += output 2152 self.assertTrue(self.res.Succeeded(), 2153 msg if (msg) else CMD_MSG(cmd)) 2154 2155 def match( 2156 self, 2157 str, 2158 patterns, 2159 msg=None, 2160 trace=False, 2161 error=False, 2162 matching=True, 2163 exe=True): 2164 """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern 2165 2166 Otherwise, all the arguments have the same meanings as for the expect function""" 2167 2168 trace = (True if traceAlways else trace) 2169 2170 if exe: 2171 # First run the command. If we are expecting error, set check=False. 2172 # Pass the assert message along since it provides more semantic 2173 # info. 2174 self.runCmd( 2175 str, 2176 msg=msg, 2177 trace=( 2178 True if trace else False), 2179 check=not error) 2180 2181 # Then compare the output against expected strings. 2182 output = self.res.GetError() if error else self.res.GetOutput() 2183 2184 # If error is True, the API client expects the command to fail! 2185 if error: 2186 self.assertFalse(self.res.Succeeded(), 2187 "Command '" + str + "' is expected to fail!") 2188 else: 2189 # No execution required, just compare str against the golden input. 2190 output = str 2191 with recording(self, trace) as sbuf: 2192 print("looking at:", output, file=sbuf) 2193 2194 # The heading says either "Expecting" or "Not expecting". 2195 heading = "Expecting" if matching else "Not expecting" 2196 2197 for pattern in patterns: 2198 # Match Objects always have a boolean value of True. 2199 match_object = re.search(pattern, output) 2200 matched = bool(match_object) 2201 with recording(self, trace) as sbuf: 2202 print("%s pattern: %s" % (heading, pattern), file=sbuf) 2203 print("Matched" if matched else "Not matched", file=sbuf) 2204 if matched: 2205 break 2206 2207 self.assertTrue(matched if matching else not matched, 2208 msg if msg else EXP_MSG(str, output, exe)) 2209 2210 return match_object 2211 2212 def check_completion_with_desc(self, str_input, match_desc_pairs, enforce_order=False): 2213 """ 2214 Checks that when the given input is completed at the given list of 2215 completions and descriptions is returned. 2216 :param str_input: The input that should be completed. The completion happens at the end of the string. 2217 :param match_desc_pairs: A list of pairs that indicate what completions have to be in the list of 2218 completions returned by LLDB. The first element of the pair is the completion 2219 string that LLDB should generate and the second element the description. 2220 :param enforce_order: True iff the order in which the completions are returned by LLDB 2221 should match the order of the match_desc_pairs pairs. 2222 """ 2223 interp = self.dbg.GetCommandInterpreter() 2224 match_strings = lldb.SBStringList() 2225 description_strings = lldb.SBStringList() 2226 num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings) 2227 self.assertEqual(len(description_strings), len(match_strings)) 2228 2229 # The index of the last matched description in description_strings or 2230 # -1 if no description has been matched yet. 2231 last_found_index = -1 2232 out_of_order_errors = "" 2233 missing_pairs = [] 2234 for pair in match_desc_pairs: 2235 found_pair = False 2236 for i in range(num_matches + 1): 2237 match_candidate = match_strings.GetStringAtIndex(i) 2238 description_candidate = description_strings.GetStringAtIndex(i) 2239 if match_candidate == pair[0] and description_candidate == pair[1]: 2240 found_pair = True 2241 if enforce_order and last_found_index > i: 2242 new_err = ("Found completion " + pair[0] + " at index " + 2243 str(i) + " in returned completion list but " + 2244 "should have been after completion " + 2245 match_strings.GetStringAtIndex(last_found_index) + 2246 " (index:" + str(last_found_index) + ")\n") 2247 out_of_order_errors += new_err 2248 last_found_index = i 2249 break 2250 if not found_pair: 2251 missing_pairs.append(pair) 2252 2253 error_msg = "" 2254 got_failure = False 2255 if len(missing_pairs): 2256 got_failure = True 2257 error_msg += "Missing pairs:\n" 2258 for pair in missing_pairs: 2259 error_msg += " [" + pair[0] + ":" + pair[1] + "]\n" 2260 if len(out_of_order_errors): 2261 got_failure = True 2262 error_msg += out_of_order_errors 2263 if got_failure: 2264 error_msg += "Got the following " + str(num_matches) + " completions back:\n" 2265 for i in range(num_matches + 1): 2266 match_candidate = match_strings.GetStringAtIndex(i) 2267 description_candidate = description_strings.GetStringAtIndex(i) 2268 error_msg += "[" + match_candidate + ":" + description_candidate + "] index " + str(i) + "\n" 2269 self.assertFalse(got_failure, error_msg) 2270 2271 def complete_exactly(self, str_input, patterns): 2272 self.complete_from_to(str_input, patterns, True) 2273 2274 def complete_from_to(self, str_input, patterns, turn_off_re_match=False): 2275 """Test that the completion mechanism completes str_input to patterns, 2276 where patterns could be a pattern-string or a list of pattern-strings""" 2277 # Patterns should not be None in order to proceed. 2278 self.assertFalse(patterns is None) 2279 # And should be either a string or list of strings. Check for list type 2280 # below, if not, make a list out of the singleton string. If patterns 2281 # is not a string or not a list of strings, there'll be runtime errors 2282 # later on. 2283 if not isinstance(patterns, list): 2284 patterns = [patterns] 2285 2286 interp = self.dbg.GetCommandInterpreter() 2287 match_strings = lldb.SBStringList() 2288 num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) 2289 common_match = match_strings.GetStringAtIndex(0) 2290 if num_matches == 0: 2291 compare_string = str_input 2292 else: 2293 if common_match != None and len(common_match) > 0: 2294 compare_string = str_input + common_match 2295 else: 2296 compare_string = "" 2297 for idx in range(1, num_matches+1): 2298 compare_string += match_strings.GetStringAtIndex(idx) + "\n" 2299 2300 for p in patterns: 2301 if turn_off_re_match: 2302 self.expect( 2303 compare_string, msg=COMPLETION_MSG( 2304 str_input, p, match_strings), exe=False, substrs=[p]) 2305 else: 2306 self.expect( 2307 compare_string, msg=COMPLETION_MSG( 2308 str_input, p, match_strings), exe=False, patterns=[p]) 2309 2310 def completions_match(self, command, completions): 2311 """Checks that the completions for the given command are equal to the 2312 given list of completions""" 2313 interp = self.dbg.GetCommandInterpreter() 2314 match_strings = lldb.SBStringList() 2315 interp.HandleCompletion(command, len(command), 0, -1, match_strings) 2316 # match_strings is a 1-indexed list, so we have to slice... 2317 self.assertItemsEqual(completions, list(match_strings)[1:], 2318 "List of returned completion is wrong") 2319 2320 def completions_contain(self, command, completions): 2321 """Checks that the completions for the given command contain the given 2322 list of completions.""" 2323 interp = self.dbg.GetCommandInterpreter() 2324 match_strings = lldb.SBStringList() 2325 interp.HandleCompletion(command, len(command), 0, -1, match_strings) 2326 for completion in completions: 2327 # match_strings is a 1-indexed list, so we have to slice... 2328 self.assertIn(completion, list(match_strings)[1:], 2329 "Couldn't find expected completion") 2330 2331 def filecheck( 2332 self, 2333 command, 2334 check_file, 2335 filecheck_options = '', 2336 expect_cmd_failure = False): 2337 # Run the command. 2338 self.runCmd( 2339 command, 2340 check=(not expect_cmd_failure), 2341 msg="FileCheck'ing result of `{0}`".format(command)) 2342 2343 self.assertTrue((not expect_cmd_failure) == self.res.Succeeded()) 2344 2345 # Get the error text if there was an error, and the regular text if not. 2346 output = self.res.GetOutput() if self.res.Succeeded() \ 2347 else self.res.GetError() 2348 2349 # Assemble the absolute path to the check file. As a convenience for 2350 # LLDB inline tests, assume that the check file is a relative path to 2351 # a file within the inline test directory. 2352 if check_file.endswith('.pyc'): 2353 check_file = check_file[:-1] 2354 check_file_abs = os.path.abspath(check_file) 2355 2356 # Run FileCheck. 2357 filecheck_bin = configuration.get_filecheck_path() 2358 if not filecheck_bin: 2359 self.assertTrue(False, "No valid FileCheck executable specified") 2360 filecheck_args = [filecheck_bin, check_file_abs] 2361 if filecheck_options: 2362 filecheck_args.append(filecheck_options) 2363 subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True) 2364 cmd_stdout, cmd_stderr = subproc.communicate(input=output) 2365 cmd_status = subproc.returncode 2366 2367 filecheck_cmd = " ".join(filecheck_args) 2368 filecheck_trace = """ 2369--- FileCheck trace (code={0}) --- 2370{1} 2371 2372FileCheck input: 2373{2} 2374 2375FileCheck output: 2376{3} 2377{4} 2378""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr) 2379 2380 trace = cmd_status != 0 or traceAlways 2381 with recording(self, trace) as sbuf: 2382 print(filecheck_trace, file=sbuf) 2383 2384 self.assertTrue(cmd_status == 0) 2385 2386 def expect( 2387 self, 2388 str, 2389 msg=None, 2390 patterns=None, 2391 startstr=None, 2392 endstr=None, 2393 substrs=None, 2394 trace=False, 2395 error=False, 2396 ordered=True, 2397 matching=True, 2398 exe=True, 2399 inHistory=False): 2400 """ 2401 Similar to runCmd; with additional expect style output matching ability. 2402 2403 Ask the command interpreter to handle the command and then check its 2404 return status. The 'msg' parameter specifies an informational assert 2405 message. We expect the output from running the command to start with 2406 'startstr', matches the substrings contained in 'substrs', and regexp 2407 matches the patterns contained in 'patterns'. 2408 2409 When matching is true and ordered is true, which are both the default, 2410 the strings in the substrs array have to appear in the command output 2411 in the order in which they appear in the array. 2412 2413 If the keyword argument error is set to True, it signifies that the API 2414 client is expecting the command to fail. In this case, the error stream 2415 from running the command is retrieved and compared against the golden 2416 input, instead. 2417 2418 If the keyword argument matching is set to False, it signifies that the API 2419 client is expecting the output of the command not to match the golden 2420 input. 2421 2422 Finally, the required argument 'str' represents the lldb command to be 2423 sent to the command interpreter. In case the keyword argument 'exe' is 2424 set to False, the 'str' is treated as a string to be matched/not-matched 2425 against the golden input. 2426 """ 2427 # Catch cases where `expect` has been miscalled. Specifically, prevent 2428 # this easy to make mistake: 2429 # self.expect("lldb command", "some substr") 2430 # The `msg` parameter is used only when a failed match occurs. A failed 2431 # match can only occur when one of `patterns`, `startstr`, `endstr`, or 2432 # `substrs` has been given. Thus, if a `msg` is given, it's an error to 2433 # not also provide one of the matcher parameters. 2434 if msg and not (patterns or startstr or endstr or substrs or error): 2435 assert False, "expect() missing a matcher argument" 2436 2437 # Check `patterns` and `substrs` are not accidentally given as strings. 2438 assert not isinstance(patterns, six.string_types), \ 2439 "patterns must be a collection of strings" 2440 assert not isinstance(substrs, six.string_types), \ 2441 "substrs must be a collection of strings" 2442 2443 trace = (True if traceAlways else trace) 2444 2445 if exe: 2446 # First run the command. If we are expecting error, set check=False. 2447 # Pass the assert message along since it provides more semantic 2448 # info. 2449 self.runCmd( 2450 str, 2451 msg=msg, 2452 trace=( 2453 True if trace else False), 2454 check=not error, 2455 inHistory=inHistory) 2456 2457 # Then compare the output against expected strings. 2458 output = self.res.GetError() if error else self.res.GetOutput() 2459 2460 # If error is True, the API client expects the command to fail! 2461 if error: 2462 self.assertFalse(self.res.Succeeded(), 2463 "Command '" + str + "' is expected to fail!") 2464 else: 2465 # No execution required, just compare str against the golden input. 2466 if isinstance(str, lldb.SBCommandReturnObject): 2467 output = str.GetOutput() 2468 else: 2469 output = str 2470 with recording(self, trace) as sbuf: 2471 print("looking at:", output, file=sbuf) 2472 2473 expecting_str = "Expecting" if matching else "Not expecting" 2474 def found_str(matched): 2475 return "was found" if matched else "was not found" 2476 2477 # To be used as assert fail message and/or trace content 2478 log_lines = [ 2479 "{}:".format("Ran command" if exe else "Checking string"), 2480 "\"{}\"".format(str), 2481 # Space out command and output 2482 "", 2483 ] 2484 if exe: 2485 # Newline before output to make large strings more readable 2486 log_lines.append("Got output:\n{}".format(output)) 2487 2488 # Assume that we start matched if we want a match 2489 # Meaning if you have no conditions, matching or 2490 # not matching will always pass 2491 matched = matching 2492 2493 # We will stop checking on first failure 2494 if startstr: 2495 matched = output.startswith(startstr) 2496 log_lines.append("{} start string: \"{}\" ({})".format( 2497 expecting_str, startstr, found_str(matched))) 2498 2499 if endstr and matched == matching: 2500 matched = output.endswith(endstr) 2501 log_lines.append("{} end string: \"{}\" ({})".format( 2502 expecting_str, endstr, found_str(matched))) 2503 2504 if substrs and matched == matching: 2505 start = 0 2506 for substr in substrs: 2507 index = output[start:].find(substr) 2508 start = start + index if ordered and matching else 0 2509 matched = index != -1 2510 log_lines.append("{} sub string: \"{}\" ({})".format( 2511 expecting_str, substr, found_str(matched))) 2512 2513 if matched != matching: 2514 break 2515 2516 if patterns and matched == matching: 2517 for pattern in patterns: 2518 matched = re.search(pattern, output) 2519 2520 pattern_line = "{} regex pattern: \"{}\" ({}".format( 2521 expecting_str, pattern, found_str(matched)) 2522 if matched: 2523 pattern_line += ", matched \"{}\"".format( 2524 matched.group(0)) 2525 pattern_line += ")" 2526 log_lines.append(pattern_line) 2527 2528 # Convert to bool because match objects 2529 # are True-ish but != True itself 2530 matched = bool(matched) 2531 if matched != matching: 2532 break 2533 2534 # If a check failed, add any extra assert message 2535 if msg is not None and matched != matching: 2536 log_lines.append(msg) 2537 2538 log_msg = "\n".join(log_lines) 2539 with recording(self, trace) as sbuf: 2540 print(log_msg, file=sbuf) 2541 if matched != matching: 2542 self.fail(log_msg) 2543 2544 def expect_expr( 2545 self, 2546 expr, 2547 result_summary=None, 2548 result_value=None, 2549 result_type=None, 2550 result_children=None 2551 ): 2552 """ 2553 Evaluates the given expression and verifies the result. 2554 :param expr: The expression as a string. 2555 :param result_summary: The summary that the expression should have. None if the summary should not be checked. 2556 :param result_value: The value that the expression should have. None if the value should not be checked. 2557 :param result_type: The type that the expression result should have. None if the type should not be checked. 2558 :param result_children: The expected children of the expression result 2559 as a list of ValueChecks. None if the children shouldn't be checked. 2560 """ 2561 self.assertTrue(expr.strip() == expr, "Expression contains trailing/leading whitespace: '" + expr + "'") 2562 2563 frame = self.frame() 2564 options = lldb.SBExpressionOptions() 2565 2566 # Disable fix-its that tests don't pass by accident. 2567 options.SetAutoApplyFixIts(False) 2568 2569 # Set the usual default options for normal expressions. 2570 options.SetIgnoreBreakpoints(True) 2571 2572 if self.frame().IsValid(): 2573 options.SetLanguage(frame.GuessLanguage()) 2574 eval_result = self.frame().EvaluateExpression(expr, options) 2575 else: 2576 target = self.target() 2577 # If there is no selected target, run the expression in the dummy 2578 # target. 2579 if not target.IsValid(): 2580 target = self.dbg.GetDummyTarget() 2581 eval_result = target.EvaluateExpression(expr, options) 2582 2583 value_check = ValueCheck(type=result_type, value=result_value, 2584 summary=result_summary, children=result_children) 2585 value_check.check_value(self, eval_result, str(eval_result)) 2586 return eval_result 2587 2588 def expect_var_path( 2589 self, 2590 var_path, 2591 summary=None, 2592 value=None, 2593 type=None, 2594 children=None 2595 ): 2596 """ 2597 Evaluates the given variable path and verifies the result. 2598 See also 'frame variable' and SBFrame.GetValueForVariablePath. 2599 :param var_path: The variable path as a string. 2600 :param summary: The summary that the variable should have. None if the summary should not be checked. 2601 :param value: The value that the variable should have. None if the value should not be checked. 2602 :param type: The type that the variable result should have. None if the type should not be checked. 2603 :param children: The expected children of the variable as a list of ValueChecks. 2604 None if the children shouldn't be checked. 2605 """ 2606 self.assertTrue(var_path.strip() == var_path, 2607 "Expression contains trailing/leading whitespace: '" + var_path + "'") 2608 2609 frame = self.frame() 2610 eval_result = frame.GetValueForVariablePath(var_path) 2611 2612 value_check = ValueCheck(type=type, value=value, 2613 summary=summary, children=children) 2614 value_check.check_value(self, eval_result, str(eval_result)) 2615 return eval_result 2616 2617 def build( 2618 self, 2619 architecture=None, 2620 compiler=None, 2621 dictionary=None): 2622 """Platform specific way to build the default binaries.""" 2623 module = builder_module() 2624 2625 if not architecture and configuration.arch: 2626 architecture = configuration.arch 2627 2628 dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) 2629 if self.getDebugInfo() is None: 2630 return self.buildDefault(architecture, compiler, dictionary) 2631 elif self.getDebugInfo() == "dsym": 2632 return self.buildDsym(architecture, compiler, dictionary) 2633 elif self.getDebugInfo() == "dwarf": 2634 return self.buildDwarf(architecture, compiler, dictionary) 2635 elif self.getDebugInfo() == "dwo": 2636 return self.buildDwo(architecture, compiler, dictionary) 2637 elif self.getDebugInfo() == "gmodules": 2638 return self.buildGModules(architecture, compiler, dictionary) 2639 else: 2640 self.fail("Can't build for debug info: %s" % self.getDebugInfo()) 2641 2642 """Assert that an lldb.SBError is in the "success" state.""" 2643 def assertSuccess(self, obj, msg=None): 2644 if not obj.Success(): 2645 error = obj.GetCString() 2646 self.fail(self._formatMessage(msg, 2647 "'{}' is not success".format(error))) 2648 2649 def createTestTarget(self, file_path=None, msg=None): 2650 """ 2651 Creates a target from the file found at the given file path. 2652 Asserts that the resulting target is valid. 2653 :param file_path: The file path that should be used to create the target. 2654 The default argument opens the current default test 2655 executable in the current test directory. 2656 :param msg: A custom error message. 2657 """ 2658 if file_path is None: 2659 file_path = self.getBuildArtifact("a.out") 2660 error = lldb.SBError() 2661 triple = "" 2662 platform = "" 2663 load_dependent_modules = True 2664 target = self.dbg.CreateTarget(file_path, triple, platform, 2665 load_dependent_modules, error) 2666 if error.Fail(): 2667 err = "Couldn't create target for path '{}': {}".format(file_path, 2668 str(error)) 2669 self.fail(self._formatMessage(msg, err)) 2670 2671 self.assertTrue(target.IsValid(), "Got invalid target without error") 2672 return target 2673 2674 # ================================================= 2675 # Misc. helper methods for debugging test execution 2676 # ================================================= 2677 2678 def DebugSBValue(self, val): 2679 """Debug print a SBValue object, if traceAlways is True.""" 2680 from .lldbutil import value_type_to_str 2681 2682 if not traceAlways: 2683 return 2684 2685 err = sys.stderr 2686 err.write(val.GetName() + ":\n") 2687 err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') 2688 err.write('\t' + "ByteSize -> " + 2689 str(val.GetByteSize()) + '\n') 2690 err.write('\t' + "NumChildren -> " + 2691 str(val.GetNumChildren()) + '\n') 2692 err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') 2693 err.write('\t' + "ValueAsUnsigned -> " + 2694 str(val.GetValueAsUnsigned()) + '\n') 2695 err.write( 2696 '\t' + 2697 "ValueType -> " + 2698 value_type_to_str( 2699 val.GetValueType()) + 2700 '\n') 2701 err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') 2702 err.write('\t' + "IsPointerType -> " + 2703 str(val.TypeIsPointerType()) + '\n') 2704 err.write('\t' + "Location -> " + val.GetLocation() + '\n') 2705 2706 def DebugSBType(self, type): 2707 """Debug print a SBType object, if traceAlways is True.""" 2708 if not traceAlways: 2709 return 2710 2711 err = sys.stderr 2712 err.write(type.GetName() + ":\n") 2713 err.write('\t' + "ByteSize -> " + 2714 str(type.GetByteSize()) + '\n') 2715 err.write('\t' + "IsPointerType -> " + 2716 str(type.IsPointerType()) + '\n') 2717 err.write('\t' + "IsReferenceType -> " + 2718 str(type.IsReferenceType()) + '\n') 2719 2720 def DebugPExpect(self, child): 2721 """Debug the spwaned pexpect object.""" 2722 if not traceAlways: 2723 return 2724 2725 print(child) 2726 2727 @classmethod 2728 def RemoveTempFile(cls, file): 2729 if os.path.exists(file): 2730 remove_file(file) 2731 2732# On Windows, the first attempt to delete a recently-touched file can fail 2733# because of a race with antimalware scanners. This function will detect a 2734# failure and retry. 2735 2736 2737def remove_file(file, num_retries=1, sleep_duration=0.5): 2738 for i in range(num_retries + 1): 2739 try: 2740 os.remove(file) 2741 return True 2742 except: 2743 time.sleep(sleep_duration) 2744 continue 2745 return False 2746