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