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