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