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