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