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