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