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