diff options
Diffstat (limited to 'packages/Python/lldbsuite/test/lldbtest.py')
| -rw-r--r-- | packages/Python/lldbsuite/test/lldbtest.py | 2482 | 
1 files changed, 0 insertions, 2482 deletions
diff --git a/packages/Python/lldbsuite/test/lldbtest.py b/packages/Python/lldbsuite/test/lldbtest.py deleted file mode 100644 index 161e8c61349d1..0000000000000 --- a/packages/Python/lldbsuite/test/lldbtest.py +++ /dev/null @@ -1,2482 +0,0 @@ -""" -LLDB module which provides the abstract base class of lldb test case. - -The concrete subclass can override lldbtest.TesBase in order to inherit the -common behavior for unitest.TestCase.setUp/tearDown implemented in this file. - -The subclass should override the attribute mydir in order for the python runtime -to locate the individual test cases when running as part of a large test suite -or when running each test case as a separate python invocation. - -./dotest.py provides a test driver which sets up the environment to run the -entire of part of the test suite .  Example: - -# Exercises the test suite in the types directory.... -/Volumes/data/lldb/svn/ToT/test $ ./dotest.py -A x86_64 types -... - -Session logs for test failures/errors/unexpected successes will go into directory '2012-05-16-13_35_42' -Command invoked: python ./dotest.py -A x86_64 types -compilers=['clang'] - -Configuration: arch=x86_64 compiler=clang ----------------------------------------------------------------------- -Collected 72 tests - -........................................................................ ----------------------------------------------------------------------- -Ran 72 tests in 135.468s - -OK -$ -""" - -from __future__ import absolute_import -from __future__ import print_function - -# System modules -import abc -import collections -from functools import wraps -import gc -import glob -import inspect -import io -import os.path -import re -import shutil -import signal -from subprocess import * -import sys -import time -import traceback -import types -import distutils.spawn - -# Third-party modules -import unittest2 -from six import add_metaclass -from six import StringIO as SixStringIO -import six - -# LLDB modules -import use_lldb_suite -import lldb -from . import configuration -from . import decorators -from . import lldbplatformutil -from . import lldbtest_config -from . import lldbutil -from . import test_categories -from lldbsuite.support import encoded_file -from lldbsuite.support import funcutils - -# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables -# LLDB_COMMAND_TRACE is set from '-t' option. - -# By default, traceAlways is False. -if "LLDB_COMMAND_TRACE" in os.environ and os.environ[ -        "LLDB_COMMAND_TRACE"] == "YES": -    traceAlways = True -else: -    traceAlways = False - -# By default, doCleanup is True. -if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"] == "NO": -    doCleanup = False -else: -    doCleanup = True - - -# -# Some commonly used assert messages. -# - -COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected" - -CURRENT_EXECUTABLE_SET = "Current executable set successfully" - -PROCESS_IS_VALID = "Process is valid" - -PROCESS_KILLED = "Process is killed successfully" - -PROCESS_EXITED = "Process exited successfully" - -PROCESS_STOPPED = "Process status should be stopped" - -RUN_SUCCEEDED = "Process is launched successfully" - -RUN_COMPLETED = "Process exited successfully" - -BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly" - -BREAKPOINT_CREATED = "Breakpoint created successfully" - -BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct" - -BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully" - -BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1" - -BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2" - -BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3" - -MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable." - -OBJECT_PRINTED_CORRECTLY = "Object printed correctly" - -SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly" - -STEP_OUT_SUCCEEDED = "Thread step-out succeeded" - -STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception" - -STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion" - -STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint" - -STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % ( -    STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'") - -STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition" - -STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count" - -STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal" - -STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in" - -STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint" - -DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly" - -VALID_BREAKPOINT = "Got a valid breakpoint" - -VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location" - -VALID_COMMAND_INTERPRETER = "Got a valid command interpreter" - -VALID_FILESPEC = "Got a valid filespec" - -VALID_MODULE = "Got a valid module" - -VALID_PROCESS = "Got a valid process" - -VALID_SYMBOL = "Got a valid symbol" - -VALID_TARGET = "Got a valid target" - -VALID_PLATFORM = "Got a valid platform" - -VALID_TYPE = "Got a valid type" - -VALID_VARIABLE = "Got a valid variable" - -VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" - -WATCHPOINT_CREATED = "Watchpoint created successfully" - - -def CMD_MSG(str): -    '''A generic "Command '%s' returns successfully" message generator.''' -    return "Command '%s' returns successfully" % str - - -def COMPLETION_MSG(str_before, str_after, completions): -    '''A generic message generator for the completion mechanism.''' -    return ("'%s' successfully completes to '%s', but completions were:\n%s" -           % (str_before, str_after, "\n".join(completions))) - - -def EXP_MSG(str, actual, exe): -    '''A generic "'%s' returns expected result" message generator if exe. -    Otherwise, it generates "'%s' matches expected result" message.''' - -    return "'%s' %s expected result, got '%s'" % ( -        str, 'returns' if exe else 'matches', actual.strip()) - - -def SETTING_MSG(setting): -    '''A generic "Value of setting '%s' is correct" message generator.''' -    return "Value of setting '%s' is correct" % setting - - -def EnvArray(): -    """Returns an env variable array from the os.environ map object.""" -    return list(map(lambda k, -                    v: k + "=" + v, -                    list(os.environ.keys()), -                    list(os.environ.values()))) - - -def line_number(filename, string_to_match): -    """Helper function to return the line number of the first matched string.""" -    with io.open(filename, mode='r', encoding="utf-8") as f: -        for i, line in enumerate(f): -            if line.find(string_to_match) != -1: -                # Found our match. -                return i + 1 -    raise Exception( -        "Unable to find '%s' within file %s" % -        (string_to_match, filename)) - -def get_line(filename, line_number): -    """Return the text of the line at the 1-based line number.""" -    with io.open(filename, mode='r', encoding="utf-8") as f: -        return f.readlines()[line_number - 1] - -def pointer_size(): -    """Return the pointer size of the host system.""" -    import ctypes -    a_pointer = ctypes.c_void_p(0xffff) -    return 8 * ctypes.sizeof(a_pointer) - - -def is_exe(fpath): -    """Returns true if fpath is an executable.""" -    return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - - -def which(program): -    """Returns the full path to a program; None otherwise.""" -    fpath, fname = os.path.split(program) -    if fpath: -        if is_exe(program): -            return program -    else: -        for path in os.environ["PATH"].split(os.pathsep): -            exe_file = os.path.join(path, program) -            if is_exe(exe_file): -                return exe_file -    return None - - -class recording(SixStringIO): -    """ -    A nice little context manager for recording the debugger interactions into -    our session object.  If trace flag is ON, it also emits the interactions -    into the stderr. -    """ - -    def __init__(self, test, trace): -        """Create a SixStringIO instance; record the session obj and trace flag.""" -        SixStringIO.__init__(self) -        # The test might not have undergone the 'setUp(self)' phase yet, so that -        # the attribute 'session' might not even exist yet. -        self.session = getattr(test, "session", None) if test else None -        self.trace = trace - -    def __enter__(self): -        """ -        Context management protocol on entry to the body of the with statement. -        Just return the SixStringIO object. -        """ -        return self - -    def __exit__(self, type, value, tb): -        """ -        Context management protocol on exit from the body of the with statement. -        If trace is ON, it emits the recordings into stderr.  Always add the -        recordings to our session object.  And close the SixStringIO object, too. -        """ -        if self.trace: -            print(self.getvalue(), file=sys.stderr) -        if self.session: -            print(self.getvalue(), file=self.session) -        self.close() - - -@add_metaclass(abc.ABCMeta) -class _BaseProcess(object): - -    @abc.abstractproperty -    def pid(self): -        """Returns process PID if has been launched already.""" - -    @abc.abstractmethod -    def launch(self, executable, args): -        """Launches new process with given executable and args.""" - -    @abc.abstractmethod -    def terminate(self): -        """Terminates previously launched process..""" - - -class _LocalProcess(_BaseProcess): - -    def __init__(self, trace_on): -        self._proc = None -        self._trace_on = trace_on -        self._delayafterterminate = 0.1 - -    @property -    def pid(self): -        return self._proc.pid - -    def launch(self, executable, args): -        self._proc = Popen( -            [executable] + args, -            stdout=open( -                os.devnull) if not self._trace_on else None, -            stdin=PIPE) - -    def terminate(self): -        if self._proc.poll() is None: -            # Terminate _proc like it does the pexpect -            signals_to_try = [ -                sig for sig in [ -                    'SIGHUP', -                    'SIGCONT', -                    'SIGINT'] if sig in dir(signal)] -            for sig in signals_to_try: -                try: -                    self._proc.send_signal(getattr(signal, sig)) -                    time.sleep(self._delayafterterminate) -                    if self._proc.poll() is not None: -                        return -                except ValueError: -                    pass  # Windows says SIGINT is not a valid signal to send -            self._proc.terminate() -            time.sleep(self._delayafterterminate) -            if self._proc.poll() is not None: -                return -            self._proc.kill() -            time.sleep(self._delayafterterminate) - -    def poll(self): -        return self._proc.poll() - - -class _RemoteProcess(_BaseProcess): - -    def __init__(self, install_remote): -        self._pid = None -        self._install_remote = install_remote - -    @property -    def pid(self): -        return self._pid - -    def launch(self, executable, args): -        if self._install_remote: -            src_path = executable -            dst_path = lldbutil.join_remote_paths( -                    lldb.remote_platform.GetWorkingDirectory(), os.path.basename(executable)) - -            dst_file_spec = lldb.SBFileSpec(dst_path, False) -            err = lldb.remote_platform.Install( -                lldb.SBFileSpec(src_path, True), dst_file_spec) -            if err.Fail(): -                raise Exception( -                    "remote_platform.Install('%s', '%s') failed: %s" % -                    (src_path, dst_path, err)) -        else: -            dst_path = executable -            dst_file_spec = lldb.SBFileSpec(executable, False) - -        launch_info = lldb.SBLaunchInfo(args) -        launch_info.SetExecutableFile(dst_file_spec, True) -        launch_info.SetWorkingDirectory( -            lldb.remote_platform.GetWorkingDirectory()) - -        # Redirect stdout and stderr to /dev/null -        launch_info.AddSuppressFileAction(1, False, True) -        launch_info.AddSuppressFileAction(2, False, True) - -        err = lldb.remote_platform.Launch(launch_info) -        if err.Fail(): -            raise Exception( -                "remote_platform.Launch('%s', '%s') failed: %s" % -                (dst_path, args, err)) -        self._pid = launch_info.GetProcessID() - -    def terminate(self): -        lldb.remote_platform.Kill(self._pid) - -# From 2.7's subprocess.check_output() convenience function. -# Return a tuple (stdoutdata, stderrdata). - - -def system(commands, **kwargs): -    r"""Run an os command with arguments and return its output as a byte string. - -    If the exit code was non-zero it raises a CalledProcessError.  The -    CalledProcessError object will have the return code in the returncode -    attribute and output in the output attribute. - -    The arguments are the same as for the Popen constructor.  Example: - -    >>> check_output(["ls", "-l", "/dev/null"]) -    'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n' - -    The stdout argument is not allowed as it is used internally. -    To capture standard error in the result, use stderr=STDOUT. - -    >>> check_output(["/bin/sh", "-c", -    ...               "ls -l non_existent_file ; exit 0"], -    ...              stderr=STDOUT) -    'ls: non_existent_file: No such file or directory\n' -    """ - -    # Assign the sender object to variable 'test' and remove it from kwargs. -    test = kwargs.pop('sender', None) - -    # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo'] -    commandList = [' '.join(x) for x in commands] -    output = "" -    error = "" -    for shellCommand in commandList: -        if 'stdout' in kwargs: -            raise ValueError( -                'stdout argument not allowed, it will be overridden.') -        if 'shell' in kwargs and kwargs['shell'] == False: -            raise ValueError('shell=False not allowed') -        process = Popen( -            shellCommand, -            stdout=PIPE, -            stderr=PIPE, -            shell=True, -            universal_newlines=True, -            **kwargs) -        pid = process.pid -        this_output, this_error = process.communicate() -        retcode = process.poll() - -        # Enable trace on failure return while tracking down FreeBSD buildbot -        # issues -        trace = traceAlways -        if not trace and retcode and sys.platform.startswith("freebsd"): -            trace = True - -        with recording(test, trace) as sbuf: -            print(file=sbuf) -            print("os command:", shellCommand, file=sbuf) -            print("with pid:", pid, file=sbuf) -            print("stdout:", this_output, file=sbuf) -            print("stderr:", this_error, file=sbuf) -            print("retcode:", retcode, file=sbuf) -            print(file=sbuf) - -        if retcode: -            cmd = kwargs.get("args") -            if cmd is None: -                cmd = shellCommand -            cpe = CalledProcessError(retcode, cmd) -            # Ensure caller can access the stdout/stderr. -            cpe.lldb_extensions = { -                "stdout_content": this_output, -                "stderr_content": this_error, -                "command": shellCommand -            } -            raise cpe -        output = output + this_output -        error = error + this_error -    return (output, error) - - -def getsource_if_available(obj): -    """ -    Return the text of the source code for an object if available.  Otherwise, -    a print representation is returned. -    """ -    import inspect -    try: -        return inspect.getsource(obj) -    except: -        return repr(obj) - - -def builder_module(): -    if sys.platform.startswith("freebsd"): -        return __import__("builder_freebsd") -    if sys.platform.startswith("openbsd"): -        return __import__("builder_openbsd") -    if sys.platform.startswith("netbsd"): -        return __import__("builder_netbsd") -    if sys.platform.startswith("linux"): -        # sys.platform with Python-3.x returns 'linux', but with -        # Python-2.x it returns 'linux2'. -        return __import__("builder_linux") -    return __import__("builder_" + sys.platform) - - -class Base(unittest2.TestCase): -    """ -    Abstract base for performing lldb (see TestBase) or other generic tests (see -    BenchBase for one example).  lldbtest.Base works with the test driver to -    accomplish things. - -    """ - -    # The concrete subclass should override this attribute. -    mydir = None - -    # Keep track of the old current working directory. -    oldcwd = None - -    @staticmethod -    def compute_mydir(test_file): -        '''Subclasses should call this function to correctly calculate the -           required "mydir" attribute as follows: - -            mydir = TestBase.compute_mydir(__file__) -        ''' -        # /abs/path/to/packages/group/subdir/mytest.py -> group/subdir -        rel_prefix = test_file[len(os.environ["LLDB_TEST"]) + 1:] -        return os.path.dirname(rel_prefix) - -    def TraceOn(self): -        """Returns True if we are in trace mode (tracing detailed test execution).""" -        return traceAlways - -    @classmethod -    def setUpClass(cls): -        """ -        Python unittest framework class setup fixture. -        Do current directory manipulation. -        """ -        # Fail fast if 'mydir' attribute is not overridden. -        if not cls.mydir or len(cls.mydir) == 0: -            raise Exception("Subclasses must override the 'mydir' attribute.") - -        # Save old working directory. -        cls.oldcwd = os.getcwd() - -        # Change current working directory if ${LLDB_TEST} is defined. -        # See also dotest.py which sets up ${LLDB_TEST}. -        if ("LLDB_TEST" in os.environ): -            full_dir = os.path.join(os.environ["LLDB_TEST"], -                                    cls.mydir) -            if traceAlways: -                print("Change dir to:", full_dir, file=sys.stderr) -            os.chdir(full_dir) - -        # Set platform context. -        cls.platformContext = lldbplatformutil.createPlatformContext() - -    @classmethod -    def tearDownClass(cls): -        """ -        Python unittest framework class teardown fixture. -        Do class-wide cleanup. -        """ - -        if doCleanup: -            # First, let's do the platform-specific cleanup. -            module = builder_module() -            module.cleanup() - -            # Subclass might have specific cleanup function defined. -            if getattr(cls, "classCleanup", None): -                if traceAlways: -                    print( -                        "Call class-specific cleanup function for class:", -                        cls, -                        file=sys.stderr) -                try: -                    cls.classCleanup() -                except: -                    exc_type, exc_value, exc_tb = sys.exc_info() -                    traceback.print_exception(exc_type, exc_value, exc_tb) - -        # Restore old working directory. -        if traceAlways: -            print("Restore dir to:", cls.oldcwd, file=sys.stderr) -        os.chdir(cls.oldcwd) - -    @classmethod -    def skipLongRunningTest(cls): -        """ -        By default, we skip long running test case. -        This can be overridden by passing '-l' to the test driver (dotest.py). -        """ -        if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ[ -                "LLDB_SKIP_LONG_RUNNING_TEST"]: -            return False -        else: -            return True - -    def enableLogChannelsForCurrentTest(self): -        if len(lldbtest_config.channels) == 0: -            return - -        # if debug channels are specified in lldbtest_config.channels, -        # create a new set of log files for every test -        log_basename = self.getLogBasenameForCurrentTest() - -        # confirm that the file is writeable -        host_log_path = "{}-host.log".format(log_basename) -        open(host_log_path, 'w').close() - -        log_enable = "log enable -Tpn -f {} ".format(host_log_path) -        for channel_with_categories in lldbtest_config.channels: -            channel_then_categories = channel_with_categories.split(' ', 1) -            channel = channel_then_categories[0] -            if len(channel_then_categories) > 1: -                categories = channel_then_categories[1] -            else: -                categories = "default" - -            if channel == "gdb-remote" and lldb.remote_platform is None: -                # communicate gdb-remote categories to debugserver -                os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories - -            self.ci.HandleCommand( -                log_enable + channel_with_categories, self.res) -            if not self.res.Succeeded(): -                raise Exception( -                    'log enable failed (check LLDB_LOG_OPTION env variable)') - -        # Communicate log path name to debugserver & lldb-server -        # For remote debugging, these variables need to be set when starting the platform -        # instance. -        if lldb.remote_platform is None: -            server_log_path = "{}-server.log".format(log_basename) -            open(server_log_path, 'w').close() -            os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path - -            # Communicate channels to lldb-server -            os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join( -                lldbtest_config.channels) - -        self.addTearDownHook(self.disableLogChannelsForCurrentTest) - -    def disableLogChannelsForCurrentTest(self): -        # close all log files that we opened -        for channel_and_categories in lldbtest_config.channels: -            # channel format - <channel-name> [<category0> [<category1> ...]] -            channel = channel_and_categories.split(' ', 1)[0] -            self.ci.HandleCommand("log disable " + channel, self.res) -            if not self.res.Succeeded(): -                raise Exception( -                    'log disable failed (check LLDB_LOG_OPTION env variable)') - -        # Retrieve the server log (if any) from the remote system. It is assumed the server log -        # is writing to the "server.log" file in the current test directory. This can be -        # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote -        # platform. If the remote logging is not enabled, then just let the Get() command silently -        # fail. -        if lldb.remote_platform: -            lldb.remote_platform.Get( -                lldb.SBFileSpec("server.log"), lldb.SBFileSpec( -                    self.getLogBasenameForCurrentTest() + "-server.log")) - -    def setPlatformWorkingDir(self): -        if not lldb.remote_platform or not configuration.lldb_platform_working_dir: -            return - -        components = self.mydir.split(os.path.sep) + [str(self.test_number), self.getBuildDirBasename()] -        remote_test_dir = configuration.lldb_platform_working_dir -        for c in components: -            remote_test_dir = lldbutil.join_remote_paths(remote_test_dir, c) -            error = lldb.remote_platform.MakeDirectory( -                remote_test_dir, 448)  # 448 = 0o700 -            if error.Fail(): -                raise Exception("making remote directory '%s': %s" % ( -                    remote_test_dir, error)) - -        lldb.remote_platform.SetWorkingDirectory(remote_test_dir) - -        # This function removes all files from the current working directory while leaving -        # the directories in place. The cleaup is required to reduce the disk space required -        # by the test suite while leaving the directories untouched is neccessary because -        # sub-directories might belong to an other test -        def clean_working_directory(): -            # TODO: Make it working on Windows when we need it for remote debugging support -            # TODO: Replace the heuristic to remove the files with a logic what collects the -            # list of files we have to remove during test runs. -            shell_cmd = lldb.SBPlatformShellCommand( -                "rm %s/*" % remote_test_dir) -            lldb.remote_platform.Run(shell_cmd) -        self.addTearDownHook(clean_working_directory) - -    def getSourceDir(self): -        """Return the full path to the current test.""" -        return os.path.join(os.environ["LLDB_TEST"], self.mydir) - -    def getBuildDirBasename(self): -        return self.__class__.__module__ + "." + self.testMethodName - -    def getBuildDir(self): -        """Return the full path to the current test.""" -        return os.path.join(os.environ["LLDB_BUILD"], self.mydir, -                            self.getBuildDirBasename()) - - -    def makeBuildDir(self): -        """Create the test-specific working directory, deleting any previous -        contents.""" -        # See also dotest.py which sets up ${LLDB_BUILD}. -        bdir = self.getBuildDir() -        if os.path.isdir(bdir): -            shutil.rmtree(bdir) -        lldbutil.mkdir_p(bdir) - -    def getBuildArtifact(self, name="a.out"): -        """Return absolute path to an artifact in the test's build directory.""" -        return os.path.join(self.getBuildDir(), name) - -    def getSourcePath(self, name): -        """Return absolute path to a file in the test's source directory.""" -        return os.path.join(self.getSourceDir(), name) - -    def setUp(self): -        """Fixture for unittest test case setup. - -        It works with the test driver to conditionally skip tests and does other -        initializations.""" -        #import traceback -        # traceback.print_stack() - -        if "LIBCXX_PATH" in os.environ: -            self.libcxxPath = os.environ["LIBCXX_PATH"] -        else: -            self.libcxxPath = None - -        if "LLDBMI_EXEC" in os.environ: -            self.lldbMiExec = os.environ["LLDBMI_EXEC"] -        else: -            self.lldbMiExec = None - -        if "LLDBVSCODE_EXEC" in os.environ: -            self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"] -        else: -            self.lldbVSCodeExec = None - -        # If we spawn an lldb process for test (via pexpect), do not load the -        # init file unless told otherwise. -        if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]: -            self.lldbOption = "" -        else: -            self.lldbOption = "--no-lldbinit" - -        # Assign the test method name to self.testMethodName. -        # -        # For an example of the use of this attribute, look at test/types dir. -        # There are a bunch of test cases under test/types and we don't want the -        # module cacheing subsystem to be confused with executable name "a.out" -        # used for all the test cases. -        self.testMethodName = self._testMethodName - -        # This is for the case of directly spawning 'lldb'/'gdb' and interacting -        # with it using pexpect. -        self.child = None -        self.child_prompt = "(lldb) " -        # If the child is interacting with the embedded script interpreter, -        # there are two exits required during tear down, first to quit the -        # embedded script interpreter and second to quit the lldb command -        # interpreter. -        self.child_in_script_interpreter = False - -        # These are for customized teardown cleanup. -        self.dict = None -        self.doTearDownCleanup = False -        # And in rare cases where there are multiple teardown cleanups. -        self.dicts = [] -        self.doTearDownCleanups = False - -        # List of spawned subproces.Popen objects -        self.subprocesses = [] - -        # List of forked process PIDs -        self.forkedProcessPids = [] - -        # Create a string buffer to record the session info, to be dumped into a -        # test case specific file if test failure is encountered. -        self.log_basename = self.getLogBasenameForCurrentTest() - -        session_file = "{}.log".format(self.log_basename) -        # Python 3 doesn't support unbuffered I/O in text mode.  Open buffered. -        self.session = encoded_file.open(session_file, "utf-8", mode="w") - -        # Optimistically set __errored__, __failed__, __expected__ to False -        # initially.  If the test errored/failed, the session info -        # (self.session) is then dumped into a session specific file for -        # diagnosis. -        self.__cleanup_errored__ = False -        self.__errored__ = False -        self.__failed__ = False -        self.__expected__ = False -        # We are also interested in unexpected success. -        self.__unexpected__ = False -        # And skipped tests. -        self.__skipped__ = False - -        # See addTearDownHook(self, hook) which allows the client to add a hook -        # function to be run during tearDown() time. -        self.hooks = [] - -        # See HideStdout(self). -        self.sys_stdout_hidden = False - -        if self.platformContext: -            # set environment variable names for finding shared libraries -            self.dylibPath = self.platformContext.shlib_environment_var - -        # Create the debugger instance if necessary. -        try: -            self.dbg = lldb.DBG -        except AttributeError: -            self.dbg = lldb.SBDebugger.Create() - -        if not self.dbg: -            raise Exception('Invalid debugger instance') - -        # Retrieve the associated command interpreter instance. -        self.ci = self.dbg.GetCommandInterpreter() -        if not self.ci: -            raise Exception('Could not get the command interpreter') - -        # And the result object. -        self.res = lldb.SBCommandReturnObject() - -        self.setPlatformWorkingDir() -        self.enableLogChannelsForCurrentTest() - -        lib_dir = os.environ["LLDB_LIB_DIR"] -        self.dsym = None -        self.framework_dir = None -        self.darwinWithFramework = self.platformIsDarwin() -        if sys.platform.startswith("darwin"): -            # Handle the framework environment variable if it is set -            if hasattr(lldbtest_config, 'lldbFrameworkPath'): -                framework_path = lldbtest_config.lldbFrameworkPath -                # Framework dir should be the directory containing the framework -                self.framework_dir = framework_path[:framework_path.rfind('LLDB.framework')] -            # If a framework dir was not specified assume the Xcode build -            # directory layout where the framework is in LLDB_LIB_DIR. -            else: -                self.framework_dir = lib_dir -            self.dsym = os.path.join(self.framework_dir, 'LLDB.framework', 'LLDB') -            # If the framework binary doesn't exist, assume we didn't actually -            # build a framework, and fallback to standard *nix behavior by -            # setting framework_dir and dsym to None. -            if not os.path.exists(self.dsym): -                self.framework_dir = None -                self.dsym = None -                self.darwinWithFramework = False -        self.makeBuildDir() - -    def setAsync(self, value): -        """ Sets async mode to True/False and ensures it is reset after the testcase completes.""" -        old_async = self.dbg.GetAsync() -        self.dbg.SetAsync(value) -        self.addTearDownHook(lambda: self.dbg.SetAsync(old_async)) - -    def cleanupSubprocesses(self): -        # Ensure any subprocesses are cleaned up -        for p in self.subprocesses: -            p.terminate() -            del p -        del self.subprocesses[:] -        # Ensure any forked processes are cleaned up -        for pid in self.forkedProcessPids: -            if os.path.exists("/proc/" + str(pid)): -                os.kill(pid, signal.SIGTERM) - -    def spawnSubprocess(self, executable, args=[], install_remote=True): -        """ Creates a subprocess.Popen object with the specified executable and arguments, -            saves it in self.subprocesses, and returns the object. -            NOTE: if using this function, ensure you also call: - -              self.addTearDownHook(self.cleanupSubprocesses) - -            otherwise the test suite will leak processes. -        """ -        proc = _RemoteProcess( -            install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn()) -        proc.launch(executable, args) -        self.subprocesses.append(proc) -        return proc - -    def forkSubprocess(self, executable, args=[]): -        """ Fork a subprocess with its own group ID. -            NOTE: if using this function, ensure you also call: - -              self.addTearDownHook(self.cleanupSubprocesses) - -            otherwise the test suite will leak processes. -        """ -        child_pid = os.fork() -        if child_pid == 0: -            # If more I/O support is required, this can be beefed up. -            fd = os.open(os.devnull, os.O_RDWR) -            os.dup2(fd, 1) -            os.dup2(fd, 2) -            # This call causes the child to have its of group ID -            os.setpgid(0, 0) -            os.execvp(executable, [executable] + args) -        # Give the child time to get through the execvp() call -        time.sleep(0.1) -        self.forkedProcessPids.append(child_pid) -        return child_pid - -    def HideStdout(self): -        """Hide output to stdout from the user. - -        During test execution, there might be cases where we don't want to show the -        standard output to the user.  For example, - -            self.runCmd(r'''sc print("\n\n\tHello!\n")''') - -        tests whether command abbreviation for 'script' works or not.  There is no -        need to show the 'Hello' output to the user as long as the 'script' command -        succeeds and we are not in TraceOn() mode (see the '-t' option). - -        In this case, the test method calls self.HideStdout(self) to redirect the -        sys.stdout to a null device, and restores the sys.stdout upon teardown. - -        Note that you should only call this method at most once during a test case -        execution.  Any subsequent call has no effect at all.""" -        if self.sys_stdout_hidden: -            return - -        self.sys_stdout_hidden = True -        old_stdout = sys.stdout -        sys.stdout = open(os.devnull, 'w') - -        def restore_stdout(): -            sys.stdout = old_stdout -        self.addTearDownHook(restore_stdout) - -    # ======================================================================= -    # Methods for customized teardown cleanups as well as execution of hooks. -    # ======================================================================= - -    def setTearDownCleanup(self, dictionary=None): -        """Register a cleanup action at tearDown() time with a dictinary""" -        self.dict = dictionary -        self.doTearDownCleanup = True - -    def addTearDownCleanup(self, dictionary): -        """Add a cleanup action at tearDown() time with a dictinary""" -        self.dicts.append(dictionary) -        self.doTearDownCleanups = True - -    def addTearDownHook(self, hook): -        """ -        Add a function to be run during tearDown() time. - -        Hooks are executed in a first come first serve manner. -        """ -        if six.callable(hook): -            with recording(self, traceAlways) as sbuf: -                print( -                    "Adding tearDown hook:", -                    getsource_if_available(hook), -                    file=sbuf) -            self.hooks.append(hook) - -        return self - -    def deletePexpectChild(self): -        # This is for the case of directly spawning 'lldb' and interacting with it -        # using pexpect. -        if self.child and self.child.isalive(): -            import pexpect -            with recording(self, traceAlways) as sbuf: -                print("tearing down the child process....", file=sbuf) -            try: -                if self.child_in_script_interpreter: -                    self.child.sendline('quit()') -                    self.child.expect_exact(self.child_prompt) -                self.child.sendline( -                    'settings set interpreter.prompt-on-quit false') -                self.child.sendline('quit') -                self.child.expect(pexpect.EOF) -            except (ValueError, pexpect.ExceptionPexpect): -                # child is already terminated -                pass -            except OSError as exception: -                import errno -                if exception.errno != errno.EIO: -                    # unexpected error -                    raise -                # child is already terminated -                pass -            finally: -                # Give it one final blow to make sure the child is terminated. -                self.child.close() - -    def tearDown(self): -        """Fixture for unittest test case teardown.""" -        #import traceback -        # traceback.print_stack() - -        self.deletePexpectChild() - -        # Check and run any hook functions. -        for hook in reversed(self.hooks): -            with recording(self, traceAlways) as sbuf: -                print( -                    "Executing tearDown hook:", -                    getsource_if_available(hook), -                    file=sbuf) -            if funcutils.requires_self(hook): -                hook(self) -            else: -                hook()  # try the plain call and hope it works - -        del self.hooks - -        # Perform registered teardown cleanup. -        if doCleanup and self.doTearDownCleanup: -            self.cleanup(dictionary=self.dict) - -        # In rare cases where there are multiple teardown cleanups added. -        if doCleanup and self.doTearDownCleanups: -            if self.dicts: -                for dict in reversed(self.dicts): -                    self.cleanup(dictionary=dict) - -    # ========================================================= -    # Various callbacks to allow introspection of test progress -    # ========================================================= - -    def markError(self): -        """Callback invoked when an error (unexpected exception) errored.""" -        self.__errored__ = True -        with recording(self, False) as sbuf: -            # False because there's no need to write "ERROR" to the stderr twice. -            # Once by the Python unittest framework, and a second time by us. -            print("ERROR", file=sbuf) - -    def markCleanupError(self): -        """Callback invoked when an error occurs while a test is cleaning up.""" -        self.__cleanup_errored__ = True -        with recording(self, False) as sbuf: -            # False because there's no need to write "CLEANUP_ERROR" to the stderr twice. -            # Once by the Python unittest framework, and a second time by us. -            print("CLEANUP_ERROR", file=sbuf) - -    def markFailure(self): -        """Callback invoked when a failure (test assertion failure) occurred.""" -        self.__failed__ = True -        with recording(self, False) as sbuf: -            # False because there's no need to write "FAIL" to the stderr twice. -            # Once by the Python unittest framework, and a second time by us. -            print("FAIL", file=sbuf) - -    def markExpectedFailure(self, err, bugnumber): -        """Callback invoked when an expected failure/error occurred.""" -        self.__expected__ = True -        with recording(self, False) as sbuf: -            # False because there's no need to write "expected failure" to the -            # stderr twice. -            # Once by the Python unittest framework, and a second time by us. -            if bugnumber is None: -                print("expected failure", file=sbuf) -            else: -                print( -                    "expected failure (problem id:" + str(bugnumber) + ")", -                    file=sbuf) - -    def markSkippedTest(self): -        """Callback invoked when a test is skipped.""" -        self.__skipped__ = True -        with recording(self, False) as sbuf: -            # False because there's no need to write "skipped test" to the -            # stderr twice. -            # Once by the Python unittest framework, and a second time by us. -            print("skipped test", file=sbuf) - -    def markUnexpectedSuccess(self, bugnumber): -        """Callback invoked when an unexpected success occurred.""" -        self.__unexpected__ = True -        with recording(self, False) as sbuf: -            # False because there's no need to write "unexpected success" to the -            # stderr twice. -            # Once by the Python unittest framework, and a second time by us. -            if bugnumber is None: -                print("unexpected success", file=sbuf) -            else: -                print( -                    "unexpected success (problem id:" + str(bugnumber) + ")", -                    file=sbuf) - -    def getRerunArgs(self): -        return " -f %s.%s" % (self.__class__.__name__, self._testMethodName) - -    def getLogBasenameForCurrentTest(self, prefix=None): -        """ -        returns a partial path that can be used as the beginning of the name of multiple -        log files pertaining to this test - -        <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method> -        """ -        dname = os.path.join(os.environ["LLDB_TEST"], -                             os.environ["LLDB_SESSION_DIRNAME"]) -        if not os.path.isdir(dname): -            os.mkdir(dname) - -        components = [] -        if prefix is not None: -            components.append(prefix) -        for c in configuration.session_file_format: -            if c == 'f': -                components.append(self.__class__.__module__) -            elif c == 'n': -                components.append(self.__class__.__name__) -            elif c == 'c': -                compiler = self.getCompiler() - -                if compiler[1] == ':': -                    compiler = compiler[2:] -                if os.path.altsep is not None: -                    compiler = compiler.replace(os.path.altsep, os.path.sep) -                path_components = [x for x in compiler.split(os.path.sep) if x != ""] - -                # Add at most 4 path components to avoid generating very long -                # filenames -                components.extend(path_components[-4:]) -            elif c == 'a': -                components.append(self.getArchitecture()) -            elif c == 'm': -                components.append(self.testMethodName) -        fname = "-".join(components) - -        return os.path.join(dname, fname) - -    def dumpSessionInfo(self): -        """ -        Dump the debugger interactions leading to a test error/failure.  This -        allows for more convenient postmortem analysis. - -        See also LLDBTestResult (dotest.py) which is a singlton class derived -        from TextTestResult and overwrites addError, addFailure, and -        addExpectedFailure methods to allow us to to mark the test instance as -        such. -        """ - -        # We are here because self.tearDown() detected that this test instance -        # either errored or failed.  The lldb.test_result singleton contains -        # two lists (erros and failures) which get populated by the unittest -        # framework.  Look over there for stack trace information. -        # -        # The lists contain 2-tuples of TestCase instances and strings holding -        # formatted tracebacks. -        # -        # See http://docs.python.org/library/unittest.html#unittest.TestResult. - -        # output tracebacks into session -        pairs = [] -        if self.__errored__: -            pairs = configuration.test_result.errors -            prefix = 'Error' -        elif self.__cleanup_errored__: -            pairs = configuration.test_result.cleanup_errors -            prefix = 'CleanupError' -        elif self.__failed__: -            pairs = configuration.test_result.failures -            prefix = 'Failure' -        elif self.__expected__: -            pairs = configuration.test_result.expectedFailures -            prefix = 'ExpectedFailure' -        elif self.__skipped__: -            prefix = 'SkippedTest' -        elif self.__unexpected__: -            prefix = 'UnexpectedSuccess' -        else: -            prefix = 'Success' - -        if not self.__unexpected__ and not self.__skipped__: -            for test, traceback in pairs: -                if test is self: -                    print(traceback, file=self.session) - -        # put footer (timestamp/rerun instructions) into session -        testMethod = getattr(self, self._testMethodName) -        if getattr(testMethod, "__benchmarks_test__", False): -            benchmarks = True -        else: -            benchmarks = False - -        import datetime -        print( -            "Session info generated @", -            datetime.datetime.now().ctime(), -            file=self.session) -        print( -            "To rerun this test, issue the following command from the 'test' directory:\n", -            file=self.session) -        print( -            "./dotest.py %s -v %s %s" % -            (self.getRunOptions(), -             ('+b' if benchmarks else '-t'), -                self.getRerunArgs()), -            file=self.session) -        self.session.close() -        del self.session - -        # process the log files -        log_files_for_this_test = glob.glob(self.log_basename + "*") - -        if prefix != 'Success' or lldbtest_config.log_success: -            # keep all log files, rename them to include prefix -            dst_log_basename = self.getLogBasenameForCurrentTest(prefix) -            for src in log_files_for_this_test: -                if os.path.isfile(src): -                    dst = src.replace(self.log_basename, dst_log_basename) -                    if os.name == "nt" and os.path.isfile(dst): -                        # On Windows, renaming a -> b will throw an exception if -                        # b exists.  On non-Windows platforms it silently -                        # replaces the destination.  Ultimately this means that -                        # atomic renames are not guaranteed to be possible on -                        # Windows, but we need this to work anyway, so just -                        # remove the destination first if it already exists. -                        remove_file(dst) - -                    lldbutil.mkdir_p(os.path.dirname(dst)) -                    os.rename(src, dst) -        else: -            # success!  (and we don't want log files) delete log files -            for log_file in log_files_for_this_test: -                remove_file(log_file) - -    # ==================================================== -    # Config. methods supported through a plugin interface -    # (enables reading of the current test configuration) -    # ==================================================== - -    def isMIPS(self): -        """Returns true if the architecture is MIPS.""" -        arch = self.getArchitecture() -        if re.match("mips", arch): -            return True -        return False - -    def isPPC64le(self): -        """Returns true if the architecture is PPC64LE.""" -        arch = self.getArchitecture() -        if re.match("powerpc64le", arch): -            return True -        return False - -    def getArchitecture(self): -        """Returns the architecture in effect the test suite is running with.""" -        module = builder_module() -        arch = module.getArchitecture() -        if arch == 'amd64': -            arch = 'x86_64' -        return arch - -    def getLldbArchitecture(self): -        """Returns the architecture of the lldb binary.""" -        if not hasattr(self, 'lldbArchitecture'): - -            # spawn local process -            command = [ -                lldbtest_config.lldbExec, -                "-o", -                "file " + lldbtest_config.lldbExec, -                "-o", -                "quit" -            ] - -            output = check_output(command) -            str = output.decode("utf-8") - -            for line in str.splitlines(): -                m = re.search( -                    "Current executable set to '.*' \\((.*)\\)\\.", line) -                if m: -                    self.lldbArchitecture = m.group(1) -                    break - -        return self.lldbArchitecture - -    def getCompiler(self): -        """Returns the compiler in effect the test suite is running with.""" -        module = builder_module() -        return module.getCompiler() - -    def getCompilerBinary(self): -        """Returns the compiler binary the test suite is running with.""" -        return self.getCompiler().split()[0] - -    def getCompilerVersion(self): -        """ Returns a string that represents the compiler version. -            Supports: llvm, clang. -        """ -        version = 'unknown' - -        compiler = self.getCompilerBinary() -        version_output = system([[compiler, "-v"]])[1] -        for line in version_output.split(os.linesep): -            m = re.search('version ([0-9\.]+)', line) -            if m: -                version = m.group(1) -        return version - -    def platformIsDarwin(self): -        """Returns true if the OS triple for the selected platform is any valid apple OS""" -        return lldbplatformutil.platformIsDarwin() - -    def hasDarwinFramework(self): -        return self.darwinWithFramework - -    def getPlatform(self): -        """Returns the target platform the test suite is running on.""" -        return lldbplatformutil.getPlatform() - -    def isIntelCompiler(self): -        """ Returns true if using an Intel (ICC) compiler, false otherwise. """ -        return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]]) - -    def expectedCompilerVersion(self, compiler_version): -        """Returns True iff compiler_version[1] matches the current compiler version. -           Use compiler_version[0] to specify the operator used to determine if a match has occurred. -           Any operator other than the following defaults to an equality test: -             '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not' -        """ -        if (compiler_version is None): -            return True -        operator = str(compiler_version[0]) -        version = compiler_version[1] - -        if (version is None): -            return True -        if (operator == '>'): -            return self.getCompilerVersion() > version -        if (operator == '>=' or operator == '=>'): -            return self.getCompilerVersion() >= version -        if (operator == '<'): -            return self.getCompilerVersion() < version -        if (operator == '<=' or operator == '=<'): -            return self.getCompilerVersion() <= version -        if (operator == '!=' or operator == '!' or operator == 'not'): -            return str(version) not in str(self.getCompilerVersion()) -        return str(version) in str(self.getCompilerVersion()) - -    def expectedCompiler(self, compilers): -        """Returns True iff any element of compilers is a sub-string of the current compiler.""" -        if (compilers is None): -            return True - -        for compiler in compilers: -            if compiler in self.getCompiler(): -                return True - -        return False - -    def expectedArch(self, archs): -        """Returns True iff any element of archs is a sub-string of the current architecture.""" -        if (archs is None): -            return True - -        for arch in archs: -            if arch in self.getArchitecture(): -                return True - -        return False - -    def getRunOptions(self): -        """Command line option for -A and -C to run this test again, called from -        self.dumpSessionInfo().""" -        arch = self.getArchitecture() -        comp = self.getCompiler() -        option_str = "" -        if arch: -            option_str = "-A " + arch -        if comp: -            option_str += " -C " + comp -        return option_str - -    def getDebugInfo(self): -        method = getattr(self, self.testMethodName) -        return getattr(method, "debug_info", None) - -    # ================================================== -    # Build methods supported through a plugin interface -    # ================================================== - -    def getstdlibFlag(self): -        """ Returns the proper -stdlib flag, or empty if not required.""" -        if self.platformIsDarwin() or self.getPlatform() == "freebsd" or self.getPlatform() == "openbsd": -            stdlibflag = "-stdlib=libc++" -        else:  # this includes NetBSD -            stdlibflag = "" -        return stdlibflag - -    def getstdFlag(self): -        """ Returns the proper stdflag. """ -        if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): -            stdflag = "-std=c++0x" -        else: -            stdflag = "-std=c++11" -        return stdflag - -    def buildDriver(self, sources, exe_name): -        """ Platform-specific way to build a program that links with LLDB (via the liblldb.so -            or LLDB.framework). -        """ -        stdflag = self.getstdFlag() -        stdlibflag = self.getstdlibFlag() - -        lib_dir = os.environ["LLDB_LIB_DIR"] -        if self.hasDarwinFramework(): -            d = {'CXX_SOURCES': sources, -                 'EXE': exe_name, -                 'CFLAGS_EXTRAS': "%s %s" % (stdflag, stdlibflag), -                 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, -                 'LD_EXTRAS': "%s -Wl,-rpath,%s" % (self.dsym, self.framework_dir), -                 } -        elif sys.platform.startswith('win'): -            d = { -                'CXX_SOURCES': sources, -                'EXE': exe_name, -                'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, -                                                 stdlibflag, -                                                 os.path.join( -                                                     os.environ["LLDB_SRC"], -                                                     "include")), -                'LD_EXTRAS': "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]} -        else: -            d = { -                'CXX_SOURCES': sources, -                'EXE': exe_name, -                'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag, -                                                 stdlibflag, -                                                 os.path.join( -                                                     os.environ["LLDB_SRC"], -                                                     "include")), -                'LD_EXTRAS': "-L%s/../lib -llldb -Wl,-rpath,%s/../lib" % (lib_dir, lib_dir)} -        if self.TraceOn(): -            print( -                "Building LLDB Driver (%s) from sources %s" % -                (exe_name, sources)) - -        self.buildDefault(dictionary=d) - -    def buildLibrary(self, sources, lib_name): -        """Platform specific way to build a default library. """ - -        stdflag = self.getstdFlag() - -        lib_dir = os.environ["LLDB_LIB_DIR"] -        if self.hasDarwinFramework(): -            d = {'DYLIB_CXX_SOURCES': sources, -                 'DYLIB_NAME': lib_name, -                 'CFLAGS_EXTRAS': "%s -stdlib=libc++" % stdflag, -                 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir, -                 'LD_EXTRAS': "%s -Wl,-rpath,%s -dynamiclib" % (self.dsym, self.framework_dir), -                 } -        elif self.getPlatform() == 'windows': -            d = { -                'DYLIB_CXX_SOURCES': sources, -                'DYLIB_NAME': lib_name, -                'CFLAGS_EXTRAS': "%s -I%s " % (stdflag, -                                               os.path.join( -                                                   os.environ["LLDB_SRC"], -                                                   "include")), -                'LD_EXTRAS': "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]} -        else: -            d = { -                'DYLIB_CXX_SOURCES': sources, -                'DYLIB_NAME': lib_name, -                'CFLAGS_EXTRAS': "%s -I%s -fPIC" % (stdflag, -                                                    os.path.join( -                                                        os.environ["LLDB_SRC"], -                                                        "include")), -                'LD_EXTRAS': "-shared -L%s/../lib -llldb -Wl,-rpath,%s/../lib" % (lib_dir, lib_dir)} -        if self.TraceOn(): -            print( -                "Building LLDB Library (%s) from sources %s" % -                (lib_name, sources)) - -        self.buildDefault(dictionary=d) - -    def buildProgram(self, sources, exe_name): -        """ Platform specific way to build an executable from C/C++ sources. """ -        d = {'CXX_SOURCES': sources, -             'EXE': exe_name} -        self.buildDefault(dictionary=d) - -    def buildDefault( -            self, -            architecture=None, -            compiler=None, -            dictionary=None): -        """Platform specific way to build the default binaries.""" -        testdir = self.mydir -        testname = self.getBuildDirBasename() -        if self.getDebugInfo(): -            raise Exception("buildDefault tests must set NO_DEBUG_INFO_TESTCASE") -        module = builder_module() -        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) -        if not module.buildDefault(self, architecture, compiler, -                                   dictionary, testdir, testname): -            raise Exception("Don't know how to build default binary") - -    def buildDsym( -            self, -            architecture=None, -            compiler=None, -            dictionary=None): -        """Platform specific way to build binaries with dsym info.""" -        testdir = self.mydir -        testname = self.getBuildDirBasename() -        if self.getDebugInfo() != "dsym": -            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") - -        module = builder_module() -        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) -        if not module.buildDsym(self, architecture, compiler, -                                dictionary, testdir, testname): -            raise Exception("Don't know how to build binary with dsym") - -    def buildDwarf( -            self, -            architecture=None, -            compiler=None, -            dictionary=None): -        """Platform specific way to build binaries with dwarf maps.""" -        testdir = self.mydir -        testname = self.getBuildDirBasename() -        if self.getDebugInfo() != "dwarf": -            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") - -        module = builder_module() -        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) -        if not module.buildDwarf(self, architecture, compiler, -                                   dictionary, testdir, testname): -            raise Exception("Don't know how to build binary with dwarf") - -    def buildDwo( -            self, -            architecture=None, -            compiler=None, -            dictionary=None): -        """Platform specific way to build binaries with dwarf maps.""" -        testdir = self.mydir -        testname = self.getBuildDirBasename() -        if self.getDebugInfo() != "dwo": -            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") - -        module = builder_module() -        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) -        if not module.buildDwo(self, architecture, compiler, -                                   dictionary, testdir, testname): -            raise Exception("Don't know how to build binary with dwo") - -    def buildGModules( -            self, -            architecture=None, -            compiler=None, -            dictionary=None): -        """Platform specific way to build binaries with gmodules info.""" -        testdir = self.mydir -        testname = self.getBuildDirBasename() -        if self.getDebugInfo() != "gmodules": -            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault") - -        module = builder_module() -        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) -        if not module.buildGModules(self, architecture, compiler, -                                    dictionary, testdir, testname): -            raise Exception("Don't know how to build binary with gmodules") - -    def signBinary(self, binary_path): -        if sys.platform.startswith("darwin"): -            codesign_cmd = "codesign --force --sign \"%s\" %s" % ( -                lldbtest_config.codesign_identity, binary_path) -            call(codesign_cmd, shell=True) - -    def findBuiltClang(self): -        """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler).""" -        paths_to_try = [ -            "llvm-build/Release+Asserts/x86_64/bin/clang", -            "llvm-build/Debug+Asserts/x86_64/bin/clang", -            "llvm-build/Release/x86_64/bin/clang", -            "llvm-build/Debug/x86_64/bin/clang", -        ] -        lldb_root_path = os.path.join( -            os.path.dirname(__file__), "..", "..", "..", "..") -        for p in paths_to_try: -            path = os.path.join(lldb_root_path, p) -            if os.path.exists(path): -                return path - -        # Tries to find clang at the same folder as the lldb -        lldb_dir = os.path.dirname(lldbtest_config.lldbExec) -        path = distutils.spawn.find_executable("clang", lldb_dir) -        if path is not None: -            return path - -        return os.environ["CC"] - -    def findYaml2obj(self): -        """ -        Get the path to the yaml2obj executable, which can be used to create -        test object files from easy to write yaml instructions. - -        Throws an Exception if the executable cannot be found. -        """ -        # Tries to find yaml2obj at the same folder as clang -        clang_dir = os.path.dirname(self.findBuiltClang()) -        path = distutils.spawn.find_executable("yaml2obj", clang_dir) -        if path is not None: -            return path -        raise Exception("yaml2obj executable not found") - - -    def yaml2obj(self, yaml_path, obj_path): -        """ -        Create an object file at the given path from a yaml file. - -        Throws subprocess.CalledProcessError if the object could not be created. -        """ -        yaml2obj = self.findYaml2obj() -        command = [yaml2obj, "-o=%s" % obj_path, yaml_path] -        system([command]) - -    def getBuildFlags( -            self, -            use_cpp11=True, -            use_libcxx=False, -            use_libstdcxx=False): -        """ Returns a dictionary (which can be provided to build* functions above) which -            contains OS-specific build flags. -        """ -        cflags = "" -        ldflags = "" - -        # On Mac OS X, unless specifically requested to use libstdc++, use -        # libc++ -        if not use_libstdcxx and self.platformIsDarwin(): -            use_libcxx = True - -        if use_libcxx and self.libcxxPath: -            cflags += "-stdlib=libc++ " -            if self.libcxxPath: -                libcxxInclude = os.path.join(self.libcxxPath, "include") -                libcxxLib = os.path.join(self.libcxxPath, "lib") -                if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib): -                    cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % ( -                        libcxxInclude, libcxxLib, libcxxLib) - -        if use_cpp11: -            cflags += "-std=" -            if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion(): -                cflags += "c++0x" -            else: -                cflags += "c++11" -        if self.platformIsDarwin() or self.getPlatform() == "freebsd": -            cflags += " -stdlib=libc++" -        elif self.getPlatform() == "openbsd": -            cflags += " -stdlib=libc++" -        elif self.getPlatform() == "netbsd": -            cflags += " -stdlib=libstdc++" -        elif "clang" in self.getCompiler(): -            cflags += " -stdlib=libstdc++" - -        return {'CFLAGS_EXTRAS': cflags, -                'LD_EXTRAS': ldflags, -                } - -    def cleanup(self, dictionary=None): -        """Platform specific way to do cleanup after build.""" -        module = builder_module() -        if not module.cleanup(self, dictionary): -            raise Exception( -                "Don't know how to do cleanup with dictionary: " + -                dictionary) - -    def getLLDBLibraryEnvVal(self): -        """ Returns the path that the OS-specific library search environment variable -            (self.dylibPath) should be set to in order for a program to find the LLDB -            library. If an environment variable named self.dylibPath is already set, -            the new path is appended to it and returned. -        """ -        existing_library_path = os.environ[ -            self.dylibPath] if self.dylibPath in os.environ else None -        lib_dir = os.environ["LLDB_LIB_DIR"] -        if existing_library_path: -            return "%s:%s" % (existing_library_path, lib_dir) -        elif sys.platform.startswith("darwin"): -            return os.path.join(lib_dir, 'LLDB.framework') -        else: -            return lib_dir - -    def getLibcPlusPlusLibs(self): -        if self.getPlatform() in ('freebsd', 'linux', 'netbsd', 'openbsd'): -            return ['libc++.so.1'] -        else: -            return ['libc++.1.dylib', 'libc++abi.dylib'] - -# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded. -# We change the test methods to create a new test method for each test for each debug info we are -# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding -# the new test method we remove the old method at the same time. This functionality can be -# supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test -# level by using the decorator @no_debug_info_test. - - -class LLDBTestCaseFactory(type): - -    def __new__(cls, name, bases, attrs): -        original_testcase = super( -            LLDBTestCaseFactory, cls).__new__( -            cls, name, bases, attrs) -        if original_testcase.NO_DEBUG_INFO_TESTCASE: -            return original_testcase - -        newattrs = {} -        for attrname, attrvalue in attrs.items(): -            if attrname.startswith("test") and not getattr( -                    attrvalue, "__no_debug_info_test__", False): - -                # If any debug info categories were explicitly tagged, assume that list to be -                # authoritative.  If none were specified, try with all debug -                # info formats. -                all_dbginfo_categories = set(test_categories.debug_info_categories) -                categories = set( -                    getattr( -                        attrvalue, -                        "categories", -                        [])) & all_dbginfo_categories -                if not categories: -                    categories = all_dbginfo_categories - -                for cat in categories: -                    @decorators.add_test_categories([cat]) -                    @wraps(attrvalue) -                    def test_method(self, attrvalue=attrvalue): -                        return attrvalue(self) - -                    method_name = attrname + "_" + cat -                    test_method.__name__ = method_name -                    test_method.debug_info = cat -                    newattrs[method_name] = test_method - -            else: -                newattrs[attrname] = attrvalue -        return super( -            LLDBTestCaseFactory, -            cls).__new__( -            cls, -            name, -            bases, -            newattrs) - -# Setup the metaclass for this class to change the list of the test -# methods when a new class is loaded - - -@add_metaclass(LLDBTestCaseFactory) -class TestBase(Base): -    """ -    This abstract base class is meant to be subclassed.  It provides default -    implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(), -    among other things. - -    Important things for test class writers: - -        - Overwrite the mydir class attribute, otherwise your test class won't -          run.  It specifies the relative directory to the top level 'test' so -          the test harness can change to the correct working directory before -          running your test. - -        - The setUp method sets up things to facilitate subsequent interactions -          with the debugger as part of the test.  These include: -              - populate the test method name -              - create/get a debugger set with synchronous mode (self.dbg) -              - get the command interpreter from with the debugger (self.ci) -              - create a result object for use with the command interpreter -                (self.res) -              - plus other stuffs - -        - The tearDown method tries to perform some necessary cleanup on behalf -          of the test to return the debugger to a good state for the next test. -          These include: -              - execute any tearDown hooks registered by the test method with -                TestBase.addTearDownHook(); examples can be found in -                settings/TestSettings.py -              - kill the inferior process associated with each target, if any, -                and, then delete the target from the debugger's target list -              - perform build cleanup before running the next test method in the -                same test class; examples of registering for this service can be -                found in types/TestIntegerTypes.py with the call: -                    - self.setTearDownCleanup(dictionary=d) - -        - Similarly setUpClass and tearDownClass perform classwise setup and -          teardown fixtures.  The tearDownClass method invokes a default build -          cleanup for the entire test class;  also, subclasses can implement the -          classmethod classCleanup(cls) to perform special class cleanup action. - -        - The instance methods runCmd and expect are used heavily by existing -          test cases to send a command to the command interpreter and to perform -          string/pattern matching on the output of such command execution.  The -          expect method also provides a mode to peform string/pattern matching -          without running a command. - -        - The build methods buildDefault, buildDsym, and buildDwarf are used to -          build the binaries used during a particular test scenario.  A plugin -          should be provided for the sys.platform running the test suite.  The -          Mac OS X implementation is located in plugins/darwin.py. -    """ - -    # Subclasses can set this to true (if they don't depend on debug info) to avoid running the -    # test multiple times with various debug info types. -    NO_DEBUG_INFO_TESTCASE = False - -    # Maximum allowed attempts when launching the inferior process. -    # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. -    maxLaunchCount = 1 - -    # Time to wait before the next launching attempt in second(s). -    # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. -    timeWaitNextLaunch = 1.0 - -    def generateSource(self, source): -        template = source + '.template' -        temp = os.path.join(self.getSourceDir(), template) -        with open(temp, 'r') as f: -            content = f.read() - -        public_api_dir = os.path.join( -            os.environ["LLDB_SRC"], "include", "lldb", "API") - -        # Look under the include/lldb/API directory and add #include statements -        # for all the SB API headers. -        public_headers = os.listdir(public_api_dir) -        # For different platforms, the include statement can vary. -        if self.hasDarwinFramework(): -            include_stmt = "'#include <%s>' % os.path.join('LLDB', header)" -        else: -            include_stmt = "'#include <%s>' % os.path.join('" + public_api_dir + "', header)" -        list = [eval(include_stmt) for header in public_headers if ( -            header.startswith("SB") and header.endswith(".h"))] -        includes = '\n'.join(list) -        new_content = content.replace('%include_SB_APIs%', includes) -        src = os.path.join(self.getBuildDir(), source) -        with open(src, 'w') as f: -            f.write(new_content) - -        self.addTearDownHook(lambda: os.remove(src)) - -    def setUp(self): -        #import traceback -        # traceback.print_stack() - -        # Works with the test driver to conditionally skip tests via -        # decorators. -        Base.setUp(self) - -        # Set the clang modules cache path used by LLDB. -        mod_cache = os.path.join(os.path.join(os.environ["LLDB_BUILD"], -                                              "module-cache-lldb")) -        self.runCmd('settings set symbols.clang-modules-cache-path "%s"' -                    % mod_cache) - -        # Disable Spotlight lookup. The testsuite creates -        # different binaries with the same UUID, because they only -        # differ in the debug info, which is not being hashed. -        self.runCmd('settings set symbols.enable-external-lookup false') - -        if "LLDB_MAX_LAUNCH_COUNT" in os.environ: -            self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"]) - -        if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ: -            self.timeWaitNextLaunch = float( -                os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"]) - -        # We want our debugger to be synchronous. -        self.dbg.SetAsync(False) - -        # Retrieve the associated command interpreter instance. -        self.ci = self.dbg.GetCommandInterpreter() -        if not self.ci: -            raise Exception('Could not get the command interpreter') - -        # And the result object. -        self.res = lldb.SBCommandReturnObject() - -    def registerSharedLibrariesWithTarget(self, target, shlibs): -        '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing - -        Any modules in the target that have their remote install file specification set will -        get uploaded to the remote host. This function registers the local copies of the -        shared libraries with the target and sets their remote install locations so they will -        be uploaded when the target is run. -        ''' -        if not shlibs or not self.platformContext: -            return None - -        shlib_environment_var = self.platformContext.shlib_environment_var -        shlib_prefix = self.platformContext.shlib_prefix -        shlib_extension = '.' + self.platformContext.shlib_extension - -        working_dir = self.get_process_working_directory() -        environment = ['%s=%s' % (shlib_environment_var, working_dir)] -        # Add any shared libraries to our target if remote so they get -        # uploaded into the working directory on the remote side -        for name in shlibs: -            # The path can be a full path to a shared library, or a make file name like "Foo" for -            # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a -            # basename like "libFoo.so". So figure out which one it is and resolve the local copy -            # of the shared library accordingly -            if os.path.isfile(name): -                local_shlib_path = name  # name is the full path to the local shared library -            else: -                # Check relative names -                local_shlib_path = os.path.join( -                    self.getBuildDir(), shlib_prefix + name + shlib_extension) -                if not os.path.exists(local_shlib_path): -                    local_shlib_path = os.path.join( -                        self.getBuildDir(), name + shlib_extension) -                    if not os.path.exists(local_shlib_path): -                        local_shlib_path = os.path.join(self.getBuildDir(), name) - -                # Make sure we found the local shared library in the above code -                self.assertTrue(os.path.exists(local_shlib_path)) - -            # Add the shared library to our target -            shlib_module = target.AddModule(local_shlib_path, None, None, None) -            if lldb.remote_platform: -                # We must set the remote install location if we want the shared library -                # to get uploaded to the remote target -                remote_shlib_path = lldbutil.append_to_process_working_directory(self, -                    os.path.basename(local_shlib_path)) -                shlib_module.SetRemoteInstallFileSpec( -                    lldb.SBFileSpec(remote_shlib_path, False)) - -        return environment - -    # utility methods that tests can use to access the current objects -    def target(self): -        if not self.dbg: -            raise Exception('Invalid debugger instance') -        return self.dbg.GetSelectedTarget() - -    def process(self): -        if not self.dbg: -            raise Exception('Invalid debugger instance') -        return self.dbg.GetSelectedTarget().GetProcess() - -    def thread(self): -        if not self.dbg: -            raise Exception('Invalid debugger instance') -        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread() - -    def frame(self): -        if not self.dbg: -            raise Exception('Invalid debugger instance') -        return self.dbg.GetSelectedTarget().GetProcess( -        ).GetSelectedThread().GetSelectedFrame() - -    def get_process_working_directory(self): -        '''Get the working directory that should be used when launching processes for local or remote processes.''' -        if lldb.remote_platform: -            # Remote tests set the platform working directory up in -            # TestBase.setUp() -            return lldb.remote_platform.GetWorkingDirectory() -        else: -            # local tests change directory into each test subdirectory -            return self.getBuildDir() - -    def tearDown(self): -        #import traceback -        # traceback.print_stack() - -        # Ensure all the references to SB objects have gone away so that we can -        # be sure that all test-specific resources have been freed before we -        # attempt to delete the targets. -        gc.collect() - -        # Delete the target(s) from the debugger as a general cleanup step. -        # This includes terminating the process for each target, if any. -        # We'd like to reuse the debugger for our next test without incurring -        # the initialization overhead. -        targets = [] -        for target in self.dbg: -            if target: -                targets.append(target) -                process = target.GetProcess() -                if process: -                    rc = self.invoke(process, "Kill") -                    self.assertTrue(rc.Success(), PROCESS_KILLED) -        for target in targets: -            self.dbg.DeleteTarget(target) - -        # Do this last, to make sure it's in reverse order from how we setup. -        Base.tearDown(self) - -        # This must be the last statement, otherwise teardown hooks or other -        # lines might depend on this still being active. -        del self.dbg - -    def switch_to_thread_with_stop_reason(self, stop_reason): -        """ -        Run the 'thread list' command, and select the thread with stop reason as -        'stop_reason'.  If no such thread exists, no select action is done. -        """ -        from .lldbutil import stop_reason_to_str -        self.runCmd('thread list') -        output = self.res.GetOutput() -        thread_line_pattern = re.compile( -            "^[ *] thread #([0-9]+):.*stop reason = %s" % -            stop_reason_to_str(stop_reason)) -        for line in output.splitlines(): -            matched = thread_line_pattern.match(line) -            if matched: -                self.runCmd('thread select %s' % matched.group(1)) - -    def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): -        """ -        Ask the command interpreter to handle the command and then check its -        return status. -        """ -        # Fail fast if 'cmd' is not meaningful. -        if not cmd or len(cmd) == 0: -            raise Exception("Bad 'cmd' parameter encountered") - -        trace = (True if traceAlways else trace) - -        if cmd.startswith("target create "): -            cmd = cmd.replace("target create ", "file ") - -        running = (cmd.startswith("run") or cmd.startswith("process launch")) - -        for i in range(self.maxLaunchCount if running else 1): -            self.ci.HandleCommand(cmd, self.res, inHistory) - -            with recording(self, trace) as sbuf: -                print("runCmd:", cmd, file=sbuf) -                if not check: -                    print("check of return status not required", file=sbuf) -                if self.res.Succeeded(): -                    print("output:", self.res.GetOutput(), file=sbuf) -                else: -                    print("runCmd failed!", file=sbuf) -                    print(self.res.GetError(), file=sbuf) - -            if self.res.Succeeded(): -                break -            elif running: -                # For process launch, wait some time before possible next try. -                time.sleep(self.timeWaitNextLaunch) -                with recording(self, trace) as sbuf: -                    print("Command '" + cmd + "' failed!", file=sbuf) - -        if check: -            output = "" -            if self.res.GetOutput(): -              output += "\nCommand output:\n" + self.res.GetOutput() -            if self.res.GetError(): -              output += "\nError output:\n" + self.res.GetError() -            if msg: -              msg += output -            if cmd: -              cmd += output -            self.assertTrue(self.res.Succeeded(), -                            msg if (msg) else CMD_MSG(cmd)) - -    def match( -            self, -            str, -            patterns, -            msg=None, -            trace=False, -            error=False, -            matching=True, -            exe=True): -        """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern - -        Otherwise, all the arguments have the same meanings as for the expect function""" - -        trace = (True if traceAlways else trace) - -        if exe: -            # First run the command.  If we are expecting error, set check=False. -            # Pass the assert message along since it provides more semantic -            # info. -            self.runCmd( -                str, -                msg=msg, -                trace=( -                    True if trace else False), -                check=not error) - -            # Then compare the output against expected strings. -            output = self.res.GetError() if error else self.res.GetOutput() - -            # If error is True, the API client expects the command to fail! -            if error: -                self.assertFalse(self.res.Succeeded(), -                                 "Command '" + str + "' is expected to fail!") -        else: -            # No execution required, just compare str against the golden input. -            output = str -            with recording(self, trace) as sbuf: -                print("looking at:", output, file=sbuf) - -        # The heading says either "Expecting" or "Not expecting". -        heading = "Expecting" if matching else "Not expecting" - -        for pattern in patterns: -            # Match Objects always have a boolean value of True. -            match_object = re.search(pattern, output) -            matched = bool(match_object) -            with recording(self, trace) as sbuf: -                print("%s pattern: %s" % (heading, pattern), file=sbuf) -                print("Matched" if matched else "Not matched", file=sbuf) -            if matched: -                break - -        self.assertTrue(matched if matching else not matched, -                        msg if msg else EXP_MSG(str, output, exe)) - -        return match_object - -    def check_completion_with_desc(self, str_input, match_desc_pairs): -        interp = self.dbg.GetCommandInterpreter() -        match_strings = lldb.SBStringList() -        description_strings = lldb.SBStringList() -        num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings) -        self.assertEqual(len(description_strings), len(match_strings)) - -        missing_pairs = [] -        for pair in match_desc_pairs: -            found_pair = False -            for i in range(num_matches + 1): -                match_candidate = match_strings.GetStringAtIndex(i) -                description_candidate = description_strings.GetStringAtIndex(i) -                if match_candidate == pair[0] and description_candidate == pair[1]: -                    found_pair = True -                    break -            if not found_pair: -                missing_pairs.append(pair) - -        if len(missing_pairs): -            error_msg = "Missing pairs:\n" -            for pair in missing_pairs: -                error_msg += " [" + pair[0] + ":" + pair[1] + "]\n" -            error_msg += "Got the following " + str(num_matches) + " completions back:\n" -            for i in range(num_matches + 1): -                match_candidate = match_strings.GetStringAtIndex(i) -                description_candidate = description_strings.GetStringAtIndex(i) -                error_msg += "[" + match_candidate + ":" + description_candidate + "]\n" -            self.assertEqual(0, len(missing_pairs), error_msg) - -    def complete_exactly(self, str_input, patterns): -        self.complete_from_to(str_input, patterns, True) - -    def complete_from_to(self, str_input, patterns, turn_off_re_match=False): -        """Test that the completion mechanism completes str_input to patterns, -        where patterns could be a pattern-string or a list of pattern-strings""" -        # Patterns should not be None in order to proceed. -        self.assertFalse(patterns is None) -        # And should be either a string or list of strings.  Check for list type -        # below, if not, make a list out of the singleton string.  If patterns -        # is not a string or not a list of strings, there'll be runtime errors -        # later on. -        if not isinstance(patterns, list): -            patterns = [patterns] - -        interp = self.dbg.GetCommandInterpreter() -        match_strings = lldb.SBStringList() -        num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) -        common_match = match_strings.GetStringAtIndex(0) -        if num_matches == 0: -            compare_string = str_input -        else: -            if common_match != None and len(common_match) > 0: -                compare_string = str_input + common_match -            else: -                compare_string = "" -                for idx in range(1, num_matches+1): -                    compare_string += match_strings.GetStringAtIndex(idx) + "\n" - -        for p in patterns: -            if turn_off_re_match: -                self.expect( -                    compare_string, msg=COMPLETION_MSG( -                        str_input, p, match_strings), exe=False, substrs=[p]) -            else: -                self.expect( -                    compare_string, msg=COMPLETION_MSG( -                        str_input, p, match_strings), exe=False, patterns=[p]) - -    def filecheck( -            self, -            command, -            check_file, -            filecheck_options = ''): -        # Run the command. -        self.runCmd( -                command, -                msg="FileCheck'ing result of `{0}`".format(command)) - -        # Get the error text if there was an error, and the regular text if not. -        output = self.res.GetOutput() if self.res.Succeeded() \ -                else self.res.GetError() - -        # Assemble the absolute path to the check file. As a convenience for -        # LLDB inline tests, assume that the check file is a relative path to -        # a file within the inline test directory. -        if check_file.endswith('.pyc'): -            check_file = check_file[:-1] -        check_file_abs = os.path.abspath(check_file) - -        # Run FileCheck. -        filecheck_bin = configuration.get_filecheck_path() -        if not filecheck_bin: -            self.assertTrue(False, "No valid FileCheck executable specified") -        filecheck_args = [filecheck_bin, check_file_abs] -        if filecheck_options: -            filecheck_args.append(filecheck_options) -        subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True) -        cmd_stdout, cmd_stderr = subproc.communicate(input=output) -        cmd_status = subproc.returncode - -        filecheck_cmd = " ".join(filecheck_args) -        filecheck_trace = """ ---- FileCheck trace (code={0}) --- -{1} - -FileCheck input: -{2} - -FileCheck output: -{3} -{4} -""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr) - -        trace = cmd_status != 0 or traceAlways -        with recording(self, trace) as sbuf: -            print(filecheck_trace, file=sbuf) - -        self.assertTrue(cmd_status == 0) - -    def expect( -            self, -            str, -            msg=None, -            patterns=None, -            startstr=None, -            endstr=None, -            substrs=None, -            trace=False, -            error=False, -            matching=True, -            exe=True, -            inHistory=False): -        """ -        Similar to runCmd; with additional expect style output matching ability. - -        Ask the command interpreter to handle the command and then check its -        return status.  The 'msg' parameter specifies an informational assert -        message.  We expect the output from running the command to start with -        'startstr', matches the substrings contained in 'substrs', and regexp -        matches the patterns contained in 'patterns'. - -        If the keyword argument error is set to True, it signifies that the API -        client is expecting the command to fail.  In this case, the error stream -        from running the command is retrieved and compared against the golden -        input, instead. - -        If the keyword argument matching is set to False, it signifies that the API -        client is expecting the output of the command not to match the golden -        input. - -        Finally, the required argument 'str' represents the lldb command to be -        sent to the command interpreter.  In case the keyword argument 'exe' is -        set to False, the 'str' is treated as a string to be matched/not-matched -        against the golden input. -        """ -        trace = (True if traceAlways else trace) - -        if exe: -            # First run the command.  If we are expecting error, set check=False. -            # Pass the assert message along since it provides more semantic -            # info. -            self.runCmd( -                str, -                msg=msg, -                trace=( -                    True if trace else False), -                check=not error, -                inHistory=inHistory) - -            # Then compare the output against expected strings. -            output = self.res.GetError() if error else self.res.GetOutput() - -            # If error is True, the API client expects the command to fail! -            if error: -                self.assertFalse(self.res.Succeeded(), -                                 "Command '" + str + "' is expected to fail!") -        else: -            # No execution required, just compare str against the golden input. -            if isinstance(str, lldb.SBCommandReturnObject): -                output = str.GetOutput() -            else: -                output = str -            with recording(self, trace) as sbuf: -                print("looking at:", output, file=sbuf) - -        if output is None: -            output = "" -        # The heading says either "Expecting" or "Not expecting". -        heading = "Expecting" if matching else "Not expecting" - -        # Start from the startstr, if specified. -        # If there's no startstr, set the initial state appropriately. -        matched = output.startswith(startstr) if startstr else ( -            True if matching else False) - -        if startstr: -            with recording(self, trace) as sbuf: -                print("%s start string: %s" % (heading, startstr), file=sbuf) -                print("Matched" if matched else "Not matched", file=sbuf) - -        # Look for endstr, if specified. -        keepgoing = matched if matching else not matched -        if endstr: -            matched = output.endswith(endstr) -            with recording(self, trace) as sbuf: -                print("%s end string: %s" % (heading, endstr), file=sbuf) -                print("Matched" if matched else "Not matched", file=sbuf) - -        # Look for sub strings, if specified. -        keepgoing = matched if matching else not matched -        if substrs and keepgoing: -            for substr in substrs: -                matched = output.find(substr) != -1 -                with recording(self, trace) as sbuf: -                    print("%s sub string: %s" % (heading, substr), file=sbuf) -                    print("Matched" if matched else "Not matched", file=sbuf) -                keepgoing = matched if matching else not matched -                if not keepgoing: -                    break - -        # Search for regular expression patterns, if specified. -        keepgoing = matched if matching else not matched -        if patterns and keepgoing: -            for pattern in patterns: -                # Match Objects always have a boolean value of True. -                matched = bool(re.search(pattern, output)) -                with recording(self, trace) as sbuf: -                    print("%s pattern: %s" % (heading, pattern), file=sbuf) -                    print("Matched" if matched else "Not matched", file=sbuf) -                keepgoing = matched if matching else not matched -                if not keepgoing: -                    break - -        self.assertTrue(matched if matching else not matched, -                        msg if msg else EXP_MSG(str, output, exe)) - -    def invoke(self, obj, name, trace=False): -        """Use reflection to call a method dynamically with no argument.""" -        trace = (True if traceAlways else trace) - -        method = getattr(obj, name) -        import inspect -        self.assertTrue(inspect.ismethod(method), -                        name + "is a method name of object: " + str(obj)) -        result = method() -        with recording(self, trace) as sbuf: -            print(str(method) + ":", result, file=sbuf) -        return result - -    def build( -            self, -            architecture=None, -            compiler=None, -            dictionary=None): -        """Platform specific way to build the default binaries.""" -        module = builder_module() - -        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) -        if self.getDebugInfo() is None: -            return self.buildDefault(architecture, compiler, dictionary) -        elif self.getDebugInfo() == "dsym": -            return self.buildDsym(architecture, compiler, dictionary) -        elif self.getDebugInfo() == "dwarf": -            return self.buildDwarf(architecture, compiler, dictionary) -        elif self.getDebugInfo() == "dwo": -            return self.buildDwo(architecture, compiler, dictionary) -        elif self.getDebugInfo() == "gmodules": -            return self.buildGModules(architecture, compiler, dictionary) -        else: -            self.fail("Can't build for debug info: %s" % self.getDebugInfo()) - -    def run_platform_command(self, cmd): -        platform = self.dbg.GetSelectedPlatform() -        shell_command = lldb.SBPlatformShellCommand(cmd) -        err = platform.Run(shell_command) -        return (err, shell_command.GetStatus(), shell_command.GetOutput()) - -    # ================================================= -    # Misc. helper methods for debugging test execution -    # ================================================= - -    def DebugSBValue(self, val): -        """Debug print a SBValue object, if traceAlways is True.""" -        from .lldbutil import value_type_to_str - -        if not traceAlways: -            return - -        err = sys.stderr -        err.write(val.GetName() + ":\n") -        err.write('\t' + "TypeName         -> " + val.GetTypeName() + '\n') -        err.write('\t' + "ByteSize         -> " + -                  str(val.GetByteSize()) + '\n') -        err.write('\t' + "NumChildren      -> " + -                  str(val.GetNumChildren()) + '\n') -        err.write('\t' + "Value            -> " + str(val.GetValue()) + '\n') -        err.write('\t' + "ValueAsUnsigned  -> " + -                  str(val.GetValueAsUnsigned()) + '\n') -        err.write( -            '\t' + -            "ValueType        -> " + -            value_type_to_str( -                val.GetValueType()) + -            '\n') -        err.write('\t' + "Summary          -> " + str(val.GetSummary()) + '\n') -        err.write('\t' + "IsPointerType    -> " + -                  str(val.TypeIsPointerType()) + '\n') -        err.write('\t' + "Location         -> " + val.GetLocation() + '\n') - -    def DebugSBType(self, type): -        """Debug print a SBType object, if traceAlways is True.""" -        if not traceAlways: -            return - -        err = sys.stderr -        err.write(type.GetName() + ":\n") -        err.write('\t' + "ByteSize        -> " + -                  str(type.GetByteSize()) + '\n') -        err.write('\t' + "IsPointerType   -> " + -                  str(type.IsPointerType()) + '\n') -        err.write('\t' + "IsReferenceType -> " + -                  str(type.IsReferenceType()) + '\n') - -    def DebugPExpect(self, child): -        """Debug the spwaned pexpect object.""" -        if not traceAlways: -            return - -        print(child) - -    @classmethod -    def RemoveTempFile(cls, file): -        if os.path.exists(file): -            remove_file(file) - -# On Windows, the first attempt to delete a recently-touched file can fail -# because of a race with antimalware scanners.  This function will detect a -# failure and retry. - - -def remove_file(file, num_retries=1, sleep_duration=0.5): -    for i in range(num_retries + 1): -        try: -            os.remove(file) -            return True -        except: -            time.sleep(sleep_duration) -            continue -    return False  | 
