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 platformIsDarwin(self):
1311        """Returns true if the OS triple for the selected platform is any valid apple OS"""
1312        return lldbplatformutil.platformIsDarwin()
1313
1314    def hasDarwinFramework(self):
1315        return self.darwinWithFramework
1316
1317    def getPlatform(self):
1318        """Returns the target platform the test suite is running on."""
1319        return lldbplatformutil.getPlatform()
1320
1321    def isIntelCompiler(self):
1322        """ Returns true if using an Intel (ICC) compiler, false otherwise. """
1323        return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]])
1324
1325    def expectedCompilerVersion(self, compiler_version):
1326        """Returns True iff compiler_version[1] matches the current compiler version.
1327           Use compiler_version[0] to specify the operator used to determine if a match has occurred.
1328           Any operator other than the following defaults to an equality test:
1329             '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
1330        """
1331        if (compiler_version is None):
1332            return True
1333        operator = str(compiler_version[0])
1334        version = compiler_version[1]
1335
1336        if (version is None):
1337            return True
1338        if (operator == '>'):
1339            return self.getCompilerVersion() > version
1340        if (operator == '>=' or operator == '=>'):
1341            return self.getCompilerVersion() >= version
1342        if (operator == '<'):
1343            return self.getCompilerVersion() < version
1344        if (operator == '<=' or operator == '=<'):
1345            return self.getCompilerVersion() <= version
1346        if (operator == '!=' or operator == '!' or operator == 'not'):
1347            return str(version) not in str(self.getCompilerVersion())
1348        return str(version) in str(self.getCompilerVersion())
1349
1350    def expectedCompiler(self, compilers):
1351        """Returns True iff any element of compilers is a sub-string of the current compiler."""
1352        if (compilers is None):
1353            return True
1354
1355        for compiler in compilers:
1356            if compiler in self.getCompiler():
1357                return True
1358
1359        return False
1360
1361    def expectedArch(self, archs):
1362        """Returns True iff any element of archs is a sub-string of the current architecture."""
1363        if (archs is None):
1364            return True
1365
1366        for arch in archs:
1367            if arch in self.getArchitecture():
1368                return True
1369
1370        return False
1371
1372    def getRunOptions(self):
1373        """Command line option for -A and -C to run this test again, called from
1374        self.dumpSessionInfo()."""
1375        arch = self.getArchitecture()
1376        comp = self.getCompiler()
1377        option_str = ""
1378        if arch:
1379            option_str = "-A " + arch
1380        if comp:
1381            option_str += " -C " + comp
1382        return option_str
1383
1384    def getDebugInfo(self):
1385        method = getattr(self, self.testMethodName)
1386        return getattr(method, "debug_info", None)
1387
1388    # ==================================================
1389    # Build methods supported through a plugin interface
1390    # ==================================================
1391
1392    def getstdlibFlag(self):
1393        """ Returns the proper -stdlib flag, or empty if not required."""
1394        if self.platformIsDarwin() or self.getPlatform() == "freebsd" or self.getPlatform() == "openbsd":
1395            stdlibflag = "-stdlib=libc++"
1396        else:  # this includes NetBSD
1397            stdlibflag = ""
1398        return stdlibflag
1399
1400    def getstdFlag(self):
1401        """ Returns the proper stdflag. """
1402        if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
1403            stdflag = "-std=c++0x"
1404        else:
1405            stdflag = "-std=c++11"
1406        return stdflag
1407
1408    def buildDriver(self, sources, exe_name):
1409        """ Platform-specific way to build a program that links with LLDB (via the liblldb.so
1410            or LLDB.framework).
1411        """
1412        stdflag = self.getstdFlag()
1413        stdlibflag = self.getstdlibFlag()
1414
1415        lib_dir = os.environ["LLDB_LIB_DIR"]
1416        if self.hasDarwinFramework():
1417            d = {'CXX_SOURCES': sources,
1418                 'EXE': exe_name,
1419                 'CFLAGS_EXTRAS': "%s %s" % (stdflag, stdlibflag),
1420                 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir,
1421                 'LD_EXTRAS': "%s -Wl,-rpath,%s" % (self.dsym, self.framework_dir),
1422                 }
1423        elif sys.platform.startswith('win'):
1424            d = {
1425                'CXX_SOURCES': sources,
1426                'EXE': exe_name,
1427                'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag,
1428                                                 stdlibflag,
1429                                                 os.path.join(
1430                                                     os.environ["LLDB_SRC"],
1431                                                     "include")),
1432                'LD_EXTRAS': "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]}
1433        else:
1434            d = {
1435                'CXX_SOURCES': sources,
1436                'EXE': exe_name,
1437                'CFLAGS_EXTRAS': "%s %s -I%s" % (stdflag,
1438                                                 stdlibflag,
1439                                                 os.path.join(
1440                                                     os.environ["LLDB_SRC"],
1441                                                     "include")),
1442                'LD_EXTRAS': "-L%s/../lib -llldb -Wl,-rpath,%s/../lib" % (lib_dir, lib_dir)}
1443        if self.TraceOn():
1444            print(
1445                "Building LLDB Driver (%s) from sources %s" %
1446                (exe_name, sources))
1447
1448        self.buildDefault(dictionary=d)
1449
1450    def buildLibrary(self, sources, lib_name):
1451        """Platform specific way to build a default library. """
1452
1453        stdflag = self.getstdFlag()
1454
1455        lib_dir = os.environ["LLDB_LIB_DIR"]
1456        if self.hasDarwinFramework():
1457            d = {'DYLIB_CXX_SOURCES': sources,
1458                 'DYLIB_NAME': lib_name,
1459                 'CFLAGS_EXTRAS': "%s -stdlib=libc++" % stdflag,
1460                 'FRAMEWORK_INCLUDES': "-F%s" % self.framework_dir,
1461                 'LD_EXTRAS': "%s -Wl,-rpath,%s -dynamiclib" % (self.dsym, self.framework_dir),
1462                 }
1463        elif self.getPlatform() == 'windows':
1464            d = {
1465                'DYLIB_CXX_SOURCES': sources,
1466                'DYLIB_NAME': lib_name,
1467                'CFLAGS_EXTRAS': "%s -I%s " % (stdflag,
1468                                               os.path.join(
1469                                                   os.environ["LLDB_SRC"],
1470                                                   "include")),
1471                'LD_EXTRAS': "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]}
1472        else:
1473            d = {
1474                'DYLIB_CXX_SOURCES': sources,
1475                'DYLIB_NAME': lib_name,
1476                'CFLAGS_EXTRAS': "%s -I%s -fPIC" % (stdflag,
1477                                                    os.path.join(
1478                                                        os.environ["LLDB_SRC"],
1479                                                        "include")),
1480                'LD_EXTRAS': "-shared -L%s/../lib -llldb -Wl,-rpath,%s/../lib" % (lib_dir, lib_dir)}
1481        if self.TraceOn():
1482            print(
1483                "Building LLDB Library (%s) from sources %s" %
1484                (lib_name, sources))
1485
1486        self.buildDefault(dictionary=d)
1487
1488    def buildProgram(self, sources, exe_name):
1489        """ Platform specific way to build an executable from C/C++ sources. """
1490        d = {'CXX_SOURCES': sources,
1491             'EXE': exe_name}
1492        self.buildDefault(dictionary=d)
1493
1494    def buildDefault(
1495            self,
1496            architecture=None,
1497            compiler=None,
1498            dictionary=None):
1499        """Platform specific way to build the default binaries."""
1500        testdir = self.mydir
1501        testname = self.getBuildDirBasename()
1502        if self.getDebugInfo():
1503            raise Exception("buildDefault tests must set NO_DEBUG_INFO_TESTCASE")
1504        module = builder_module()
1505        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1506        if not module.buildDefault(self, architecture, compiler,
1507                                   dictionary, testdir, testname):
1508            raise Exception("Don't know how to build default binary")
1509
1510    def buildDsym(
1511            self,
1512            architecture=None,
1513            compiler=None,
1514            dictionary=None):
1515        """Platform specific way to build binaries with dsym info."""
1516        testdir = self.mydir
1517        testname = self.getBuildDirBasename()
1518        if self.getDebugInfo() != "dsym":
1519            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1520
1521        module = builder_module()
1522        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1523        if not module.buildDsym(self, architecture, compiler,
1524                                dictionary, testdir, testname):
1525            raise Exception("Don't know how to build binary with dsym")
1526
1527    def buildDwarf(
1528            self,
1529            architecture=None,
1530            compiler=None,
1531            dictionary=None):
1532        """Platform specific way to build binaries with dwarf maps."""
1533        testdir = self.mydir
1534        testname = self.getBuildDirBasename()
1535        if self.getDebugInfo() != "dwarf":
1536            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1537
1538        module = builder_module()
1539        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1540        if not module.buildDwarf(self, architecture, compiler,
1541                                   dictionary, testdir, testname):
1542            raise Exception("Don't know how to build binary with dwarf")
1543
1544    def buildDwo(
1545            self,
1546            architecture=None,
1547            compiler=None,
1548            dictionary=None):
1549        """Platform specific way to build binaries with dwarf maps."""
1550        testdir = self.mydir
1551        testname = self.getBuildDirBasename()
1552        if self.getDebugInfo() != "dwo":
1553            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1554
1555        module = builder_module()
1556        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1557        if not module.buildDwo(self, architecture, compiler,
1558                                   dictionary, testdir, testname):
1559            raise Exception("Don't know how to build binary with dwo")
1560
1561    def buildGModules(
1562            self,
1563            architecture=None,
1564            compiler=None,
1565            dictionary=None):
1566        """Platform specific way to build binaries with gmodules info."""
1567        testdir = self.mydir
1568        testname = self.getBuildDirBasename()
1569        if self.getDebugInfo() != "gmodules":
1570            raise Exception("NO_DEBUG_INFO_TESTCASE must build with buildDefault")
1571
1572        module = builder_module()
1573        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
1574        if not module.buildGModules(self, architecture, compiler,
1575                                    dictionary, testdir, testname):
1576            raise Exception("Don't know how to build binary with gmodules")
1577
1578    def signBinary(self, binary_path):
1579        if sys.platform.startswith("darwin"):
1580            codesign_cmd = "codesign --force --sign \"%s\" %s" % (
1581                lldbtest_config.codesign_identity, binary_path)
1582            call(codesign_cmd, shell=True)
1583
1584    def findBuiltClang(self):
1585        """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
1586        paths_to_try = [
1587            "llvm-build/Release+Asserts/x86_64/bin/clang",
1588            "llvm-build/Debug+Asserts/x86_64/bin/clang",
1589            "llvm-build/Release/x86_64/bin/clang",
1590            "llvm-build/Debug/x86_64/bin/clang",
1591        ]
1592        lldb_root_path = os.path.join(
1593            os.path.dirname(__file__), "..", "..", "..", "..")
1594        for p in paths_to_try:
1595            path = os.path.join(lldb_root_path, p)
1596            if os.path.exists(path):
1597                return path
1598
1599        # Tries to find clang at the same folder as the lldb
1600        lldb_dir = os.path.dirname(lldbtest_config.lldbExec)
1601        path = distutils.spawn.find_executable("clang", lldb_dir)
1602        if path is not None:
1603            return path
1604
1605        return os.environ["CC"]
1606
1607    def findYaml2obj(self):
1608        """
1609        Get the path to the yaml2obj executable, which can be used to create
1610        test object files from easy to write yaml instructions.
1611
1612        Throws an Exception if the executable cannot be found.
1613        """
1614        # Tries to find yaml2obj at the same folder as clang
1615        clang_dir = os.path.dirname(self.findBuiltClang())
1616        path = distutils.spawn.find_executable("yaml2obj", clang_dir)
1617        if path is not None:
1618            return path
1619        raise Exception("yaml2obj executable not found")
1620
1621
1622    def yaml2obj(self, yaml_path, obj_path):
1623        """
1624        Create an object file at the given path from a yaml file.
1625
1626        Throws subprocess.CalledProcessError if the object could not be created.
1627        """
1628        yaml2obj = self.findYaml2obj()
1629        command = [yaml2obj, "-o=%s" % obj_path, yaml_path]
1630        system([command])
1631
1632    def getBuildFlags(
1633            self,
1634            use_cpp11=True,
1635            use_libcxx=False,
1636            use_libstdcxx=False):
1637        """ Returns a dictionary (which can be provided to build* functions above) which
1638            contains OS-specific build flags.
1639        """
1640        cflags = ""
1641        ldflags = ""
1642
1643        # On Mac OS X, unless specifically requested to use libstdc++, use
1644        # libc++
1645        if not use_libstdcxx and self.platformIsDarwin():
1646            use_libcxx = True
1647
1648        if use_libcxx and self.libcxxPath:
1649            cflags += "-stdlib=libc++ "
1650            if self.libcxxPath:
1651                libcxxInclude = os.path.join(self.libcxxPath, "include")
1652                libcxxLib = os.path.join(self.libcxxPath, "lib")
1653                if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib):
1654                    cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (
1655                        libcxxInclude, libcxxLib, libcxxLib)
1656
1657        if use_cpp11:
1658            cflags += "-std="
1659            if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
1660                cflags += "c++0x"
1661            else:
1662                cflags += "c++11"
1663        if self.platformIsDarwin() or self.getPlatform() == "freebsd":
1664            cflags += " -stdlib=libc++"
1665        elif self.getPlatform() == "openbsd":
1666            cflags += " -stdlib=libc++"
1667        elif self.getPlatform() == "netbsd":
1668            cflags += " -stdlib=libstdc++"
1669        elif "clang" in self.getCompiler():
1670            cflags += " -stdlib=libstdc++"
1671
1672        return {'CFLAGS_EXTRAS': cflags,
1673                'LD_EXTRAS': ldflags,
1674                }
1675
1676    def cleanup(self, dictionary=None):
1677        """Platform specific way to do cleanup after build."""
1678        module = builder_module()
1679        if not module.cleanup(self, dictionary):
1680            raise Exception(
1681                "Don't know how to do cleanup with dictionary: " +
1682                dictionary)
1683
1684    def getLLDBLibraryEnvVal(self):
1685        """ Returns the path that the OS-specific library search environment variable
1686            (self.dylibPath) should be set to in order for a program to find the LLDB
1687            library. If an environment variable named self.dylibPath is already set,
1688            the new path is appended to it and returned.
1689        """
1690        existing_library_path = os.environ[
1691            self.dylibPath] if self.dylibPath in os.environ else None
1692        lib_dir = os.environ["LLDB_LIB_DIR"]
1693        if existing_library_path:
1694            return "%s:%s" % (existing_library_path, lib_dir)
1695        elif sys.platform.startswith("darwin"):
1696            return os.path.join(lib_dir, 'LLDB.framework')
1697        else:
1698            return lib_dir
1699
1700    def getLibcPlusPlusLibs(self):
1701        if self.getPlatform() in ('freebsd', 'linux', 'netbsd', 'openbsd'):
1702            return ['libc++.so.1']
1703        else:
1704            return ['libc++.1.dylib', 'libc++abi.dylib']
1705
1706# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
1707# We change the test methods to create a new test method for each test for each debug info we are
1708# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
1709# the new test method we remove the old method at the same time. This functionality can be
1710# supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test
1711# level by using the decorator @no_debug_info_test.
1712
1713
1714class LLDBTestCaseFactory(type):
1715
1716    def __new__(cls, name, bases, attrs):
1717        original_testcase = super(
1718            LLDBTestCaseFactory, cls).__new__(
1719            cls, name, bases, attrs)
1720        if original_testcase.NO_DEBUG_INFO_TESTCASE:
1721            return original_testcase
1722
1723        newattrs = {}
1724        for attrname, attrvalue in attrs.items():
1725            if attrname.startswith("test") and not getattr(
1726                    attrvalue, "__no_debug_info_test__", False):
1727
1728                # If any debug info categories were explicitly tagged, assume that list to be
1729                # authoritative.  If none were specified, try with all debug
1730                # info formats.
1731                all_dbginfo_categories = set(test_categories.debug_info_categories)
1732                categories = set(
1733                    getattr(
1734                        attrvalue,
1735                        "categories",
1736                        [])) & all_dbginfo_categories
1737                if not categories:
1738                    categories = all_dbginfo_categories
1739
1740                for cat in categories:
1741                    @decorators.add_test_categories([cat])
1742                    @wraps(attrvalue)
1743                    def test_method(self, attrvalue=attrvalue):
1744                        return attrvalue(self)
1745
1746                    method_name = attrname + "_" + cat
1747                    test_method.__name__ = method_name
1748                    test_method.debug_info = cat
1749                    newattrs[method_name] = test_method
1750
1751            else:
1752                newattrs[attrname] = attrvalue
1753        return super(
1754            LLDBTestCaseFactory,
1755            cls).__new__(
1756            cls,
1757            name,
1758            bases,
1759            newattrs)
1760
1761# Setup the metaclass for this class to change the list of the test
1762# methods when a new class is loaded
1763
1764
1765@add_metaclass(LLDBTestCaseFactory)
1766class TestBase(Base):
1767    """
1768    This abstract base class is meant to be subclassed.  It provides default
1769    implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
1770    among other things.
1771
1772    Important things for test class writers:
1773
1774        - Overwrite the mydir class attribute, otherwise your test class won't
1775          run.  It specifies the relative directory to the top level 'test' so
1776          the test harness can change to the correct working directory before
1777          running your test.
1778
1779        - The setUp method sets up things to facilitate subsequent interactions
1780          with the debugger as part of the test.  These include:
1781              - populate the test method name
1782              - create/get a debugger set with synchronous mode (self.dbg)
1783              - get the command interpreter from with the debugger (self.ci)
1784              - create a result object for use with the command interpreter
1785                (self.res)
1786              - plus other stuffs
1787
1788        - The tearDown method tries to perform some necessary cleanup on behalf
1789          of the test to return the debugger to a good state for the next test.
1790          These include:
1791              - execute any tearDown hooks registered by the test method with
1792                TestBase.addTearDownHook(); examples can be found in
1793                settings/TestSettings.py
1794              - kill the inferior process associated with each target, if any,
1795                and, then delete the target from the debugger's target list
1796              - perform build cleanup before running the next test method in the
1797                same test class; examples of registering for this service can be
1798                found in types/TestIntegerTypes.py with the call:
1799                    - self.setTearDownCleanup(dictionary=d)
1800
1801        - Similarly setUpClass and tearDownClass perform classwise setup and
1802          teardown fixtures.  The tearDownClass method invokes a default build
1803          cleanup for the entire test class;  also, subclasses can implement the
1804          classmethod classCleanup(cls) to perform special class cleanup action.
1805
1806        - The instance methods runCmd and expect are used heavily by existing
1807          test cases to send a command to the command interpreter and to perform
1808          string/pattern matching on the output of such command execution.  The
1809          expect method also provides a mode to peform string/pattern matching
1810          without running a command.
1811
1812        - The build methods buildDefault, buildDsym, and buildDwarf are used to
1813          build the binaries used during a particular test scenario.  A plugin
1814          should be provided for the sys.platform running the test suite.  The
1815          Mac OS X implementation is located in plugins/darwin.py.
1816    """
1817
1818    # Subclasses can set this to true (if they don't depend on debug info) to avoid running the
1819    # test multiple times with various debug info types.
1820    NO_DEBUG_INFO_TESTCASE = False
1821
1822    # Maximum allowed attempts when launching the inferior process.
1823    # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
1824    maxLaunchCount = 1
1825
1826    # Time to wait before the next launching attempt in second(s).
1827    # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
1828    timeWaitNextLaunch = 1.0
1829
1830    def generateSource(self, source):
1831        template = source + '.template'
1832        temp = os.path.join(self.getSourceDir(), template)
1833        with open(temp, 'r') as f:
1834            content = f.read()
1835
1836        public_api_dir = os.path.join(
1837            os.environ["LLDB_SRC"], "include", "lldb", "API")
1838
1839        # Look under the include/lldb/API directory and add #include statements
1840        # for all the SB API headers.
1841        public_headers = os.listdir(public_api_dir)
1842        # For different platforms, the include statement can vary.
1843        if self.hasDarwinFramework():
1844            include_stmt = "'#include <%s>' % os.path.join('LLDB', header)"
1845        else:
1846            include_stmt = "'#include <%s>' % os.path.join('" + public_api_dir + "', header)"
1847        list = [eval(include_stmt) for header in public_headers if (
1848            header.startswith("SB") and header.endswith(".h"))]
1849        includes = '\n'.join(list)
1850        new_content = content.replace('%include_SB_APIs%', includes)
1851        src = os.path.join(self.getBuildDir(), source)
1852        with open(src, 'w') as f:
1853            f.write(new_content)
1854
1855        self.addTearDownHook(lambda: os.remove(src))
1856
1857    def setUp(self):
1858        #import traceback
1859        # traceback.print_stack()
1860
1861        # Works with the test driver to conditionally skip tests via
1862        # decorators.
1863        Base.setUp(self)
1864
1865        # Set the clang modules cache path used by LLDB.
1866        mod_cache = os.path.join(os.path.join(os.environ["LLDB_BUILD"],
1867                                              "module-cache-lldb"))
1868        self.runCmd('settings set symbols.clang-modules-cache-path "%s"'
1869                    % mod_cache)
1870
1871        # Disable Spotlight lookup. The testsuite creates
1872        # different binaries with the same UUID, because they only
1873        # differ in the debug info, which is not being hashed.
1874        self.runCmd('settings set symbols.enable-external-lookup false')
1875
1876        if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
1877            self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
1878
1879        if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
1880            self.timeWaitNextLaunch = float(
1881                os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
1882
1883        # We want our debugger to be synchronous.
1884        self.dbg.SetAsync(False)
1885
1886        # Retrieve the associated command interpreter instance.
1887        self.ci = self.dbg.GetCommandInterpreter()
1888        if not self.ci:
1889            raise Exception('Could not get the command interpreter')
1890
1891        # And the result object.
1892        self.res = lldb.SBCommandReturnObject()
1893
1894    def registerSharedLibrariesWithTarget(self, target, shlibs):
1895        '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing
1896
1897        Any modules in the target that have their remote install file specification set will
1898        get uploaded to the remote host. This function registers the local copies of the
1899        shared libraries with the target and sets their remote install locations so they will
1900        be uploaded when the target is run.
1901        '''
1902        if not shlibs or not self.platformContext:
1903            return None
1904
1905        shlib_environment_var = self.platformContext.shlib_environment_var
1906        shlib_prefix = self.platformContext.shlib_prefix
1907        shlib_extension = '.' + self.platformContext.shlib_extension
1908
1909        working_dir = self.get_process_working_directory()
1910        environment = ['%s=%s' % (shlib_environment_var, working_dir)]
1911        # Add any shared libraries to our target if remote so they get
1912        # uploaded into the working directory on the remote side
1913        for name in shlibs:
1914            # The path can be a full path to a shared library, or a make file name like "Foo" for
1915            # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
1916            # basename like "libFoo.so". So figure out which one it is and resolve the local copy
1917            # of the shared library accordingly
1918            if os.path.isfile(name):
1919                local_shlib_path = name  # name is the full path to the local shared library
1920            else:
1921                # Check relative names
1922                local_shlib_path = os.path.join(
1923                    self.getBuildDir(), shlib_prefix + name + shlib_extension)
1924                if not os.path.exists(local_shlib_path):
1925                    local_shlib_path = os.path.join(
1926                        self.getBuildDir(), name + shlib_extension)
1927                    if not os.path.exists(local_shlib_path):
1928                        local_shlib_path = os.path.join(self.getBuildDir(), name)
1929
1930                # Make sure we found the local shared library in the above code
1931                self.assertTrue(os.path.exists(local_shlib_path))
1932
1933            # Add the shared library to our target
1934            shlib_module = target.AddModule(local_shlib_path, None, None, None)
1935            if lldb.remote_platform:
1936                # We must set the remote install location if we want the shared library
1937                # to get uploaded to the remote target
1938                remote_shlib_path = lldbutil.append_to_process_working_directory(self,
1939                    os.path.basename(local_shlib_path))
1940                shlib_module.SetRemoteInstallFileSpec(
1941                    lldb.SBFileSpec(remote_shlib_path, False))
1942
1943        return environment
1944
1945    # utility methods that tests can use to access the current objects
1946    def target(self):
1947        if not self.dbg:
1948            raise Exception('Invalid debugger instance')
1949        return self.dbg.GetSelectedTarget()
1950
1951    def process(self):
1952        if not self.dbg:
1953            raise Exception('Invalid debugger instance')
1954        return self.dbg.GetSelectedTarget().GetProcess()
1955
1956    def thread(self):
1957        if not self.dbg:
1958            raise Exception('Invalid debugger instance')
1959        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread()
1960
1961    def frame(self):
1962        if not self.dbg:
1963            raise Exception('Invalid debugger instance')
1964        return self.dbg.GetSelectedTarget().GetProcess(
1965        ).GetSelectedThread().GetSelectedFrame()
1966
1967    def get_process_working_directory(self):
1968        '''Get the working directory that should be used when launching processes for local or remote processes.'''
1969        if lldb.remote_platform:
1970            # Remote tests set the platform working directory up in
1971            # TestBase.setUp()
1972            return lldb.remote_platform.GetWorkingDirectory()
1973        else:
1974            # local tests change directory into each test subdirectory
1975            return self.getBuildDir()
1976
1977    def tearDown(self):
1978        #import traceback
1979        # traceback.print_stack()
1980
1981        # Ensure all the references to SB objects have gone away so that we can
1982        # be sure that all test-specific resources have been freed before we
1983        # attempt to delete the targets.
1984        gc.collect()
1985
1986        # Delete the target(s) from the debugger as a general cleanup step.
1987        # This includes terminating the process for each target, if any.
1988        # We'd like to reuse the debugger for our next test without incurring
1989        # the initialization overhead.
1990        targets = []
1991        for target in self.dbg:
1992            if target:
1993                targets.append(target)
1994                process = target.GetProcess()
1995                if process:
1996                    rc = self.invoke(process, "Kill")
1997                    self.assertTrue(rc.Success(), PROCESS_KILLED)
1998        for target in targets:
1999            self.dbg.DeleteTarget(target)
2000
2001        # Do this last, to make sure it's in reverse order from how we setup.
2002        Base.tearDown(self)
2003
2004        # This must be the last statement, otherwise teardown hooks or other
2005        # lines might depend on this still being active.
2006        del self.dbg
2007
2008    def switch_to_thread_with_stop_reason(self, stop_reason):
2009        """
2010        Run the 'thread list' command, and select the thread with stop reason as
2011        'stop_reason'.  If no such thread exists, no select action is done.
2012        """
2013        from .lldbutil import stop_reason_to_str
2014        self.runCmd('thread list')
2015        output = self.res.GetOutput()
2016        thread_line_pattern = re.compile(
2017            "^[ *] thread #([0-9]+):.*stop reason = %s" %
2018            stop_reason_to_str(stop_reason))
2019        for line in output.splitlines():
2020            matched = thread_line_pattern.match(line)
2021            if matched:
2022                self.runCmd('thread select %s' % matched.group(1))
2023
2024    def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False):
2025        """
2026        Ask the command interpreter to handle the command and then check its
2027        return status.
2028        """
2029        # Fail fast if 'cmd' is not meaningful.
2030        if not cmd or len(cmd) == 0:
2031            raise Exception("Bad 'cmd' parameter encountered")
2032
2033        trace = (True if traceAlways else trace)
2034
2035        if cmd.startswith("target create "):
2036            cmd = cmd.replace("target create ", "file ")
2037
2038        running = (cmd.startswith("run") or cmd.startswith("process launch"))
2039
2040        for i in range(self.maxLaunchCount if running else 1):
2041            self.ci.HandleCommand(cmd, self.res, inHistory)
2042
2043            with recording(self, trace) as sbuf:
2044                print("runCmd:", cmd, file=sbuf)
2045                if not check:
2046                    print("check of return status not required", file=sbuf)
2047                if self.res.Succeeded():
2048                    print("output:", self.res.GetOutput(), file=sbuf)
2049                else:
2050                    print("runCmd failed!", file=sbuf)
2051                    print(self.res.GetError(), file=sbuf)
2052
2053            if self.res.Succeeded():
2054                break
2055            elif running:
2056                # For process launch, wait some time before possible next try.
2057                time.sleep(self.timeWaitNextLaunch)
2058                with recording(self, trace) as sbuf:
2059                    print("Command '" + cmd + "' failed!", file=sbuf)
2060
2061        if check:
2062            output = ""
2063            if self.res.GetOutput():
2064              output += "\nCommand output:\n" + self.res.GetOutput()
2065            if self.res.GetError():
2066              output += "\nError output:\n" + self.res.GetError()
2067            if msg:
2068              msg += output
2069            if cmd:
2070              cmd += output
2071            self.assertTrue(self.res.Succeeded(),
2072                            msg if (msg) else CMD_MSG(cmd))
2073
2074    def match(
2075            self,
2076            str,
2077            patterns,
2078            msg=None,
2079            trace=False,
2080            error=False,
2081            matching=True,
2082            exe=True):
2083        """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
2084
2085        Otherwise, all the arguments have the same meanings as for the expect function"""
2086
2087        trace = (True if traceAlways else trace)
2088
2089        if exe:
2090            # First run the command.  If we are expecting error, set check=False.
2091            # Pass the assert message along since it provides more semantic
2092            # info.
2093            self.runCmd(
2094                str,
2095                msg=msg,
2096                trace=(
2097                    True if trace else False),
2098                check=not error)
2099
2100            # Then compare the output against expected strings.
2101            output = self.res.GetError() if error else self.res.GetOutput()
2102
2103            # If error is True, the API client expects the command to fail!
2104            if error:
2105                self.assertFalse(self.res.Succeeded(),
2106                                 "Command '" + str + "' is expected to fail!")
2107        else:
2108            # No execution required, just compare str against the golden input.
2109            output = str
2110            with recording(self, trace) as sbuf:
2111                print("looking at:", output, file=sbuf)
2112
2113        # The heading says either "Expecting" or "Not expecting".
2114        heading = "Expecting" if matching else "Not expecting"
2115
2116        for pattern in patterns:
2117            # Match Objects always have a boolean value of True.
2118            match_object = re.search(pattern, output)
2119            matched = bool(match_object)
2120            with recording(self, trace) as sbuf:
2121                print("%s pattern: %s" % (heading, pattern), file=sbuf)
2122                print("Matched" if matched else "Not matched", file=sbuf)
2123            if matched:
2124                break
2125
2126        self.assertTrue(matched if matching else not matched,
2127                        msg if msg else EXP_MSG(str, output, exe))
2128
2129        return match_object
2130
2131    def check_completion_with_desc(self, str_input, match_desc_pairs):
2132        interp = self.dbg.GetCommandInterpreter()
2133        match_strings = lldb.SBStringList()
2134        description_strings = lldb.SBStringList()
2135        num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings)
2136        self.assertEqual(len(description_strings), len(match_strings))
2137
2138        missing_pairs = []
2139        for pair in match_desc_pairs:
2140            found_pair = False
2141            for i in range(num_matches + 1):
2142                match_candidate = match_strings.GetStringAtIndex(i)
2143                description_candidate = description_strings.GetStringAtIndex(i)
2144                if match_candidate == pair[0] and description_candidate == pair[1]:
2145                    found_pair = True
2146                    break
2147            if not found_pair:
2148                missing_pairs.append(pair)
2149
2150        if len(missing_pairs):
2151            error_msg = "Missing pairs:\n"
2152            for pair in missing_pairs:
2153                error_msg += " [" + pair[0] + ":" + pair[1] + "]\n"
2154            error_msg += "Got the following " + str(num_matches) + " completions back:\n"
2155            for i in range(num_matches + 1):
2156                match_candidate = match_strings.GetStringAtIndex(i)
2157                description_candidate = description_strings.GetStringAtIndex(i)
2158                error_msg += "[" + match_candidate + ":" + description_candidate + "]\n"
2159            self.assertEqual(0, len(missing_pairs), error_msg)
2160
2161    def complete_exactly(self, str_input, patterns):
2162        self.complete_from_to(str_input, patterns, True)
2163
2164    def complete_from_to(self, str_input, patterns, turn_off_re_match=False):
2165        """Test that the completion mechanism completes str_input to patterns,
2166        where patterns could be a pattern-string or a list of pattern-strings"""
2167        # Patterns should not be None in order to proceed.
2168        self.assertFalse(patterns is None)
2169        # And should be either a string or list of strings.  Check for list type
2170        # below, if not, make a list out of the singleton string.  If patterns
2171        # is not a string or not a list of strings, there'll be runtime errors
2172        # later on.
2173        if not isinstance(patterns, list):
2174            patterns = [patterns]
2175
2176        interp = self.dbg.GetCommandInterpreter()
2177        match_strings = lldb.SBStringList()
2178        num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings)
2179        common_match = match_strings.GetStringAtIndex(0)
2180        if num_matches == 0:
2181            compare_string = str_input
2182        else:
2183            if common_match != None and len(common_match) > 0:
2184                compare_string = str_input + common_match
2185            else:
2186                compare_string = ""
2187                for idx in range(1, num_matches+1):
2188                    compare_string += match_strings.GetStringAtIndex(idx) + "\n"
2189
2190        for p in patterns:
2191            if turn_off_re_match:
2192                self.expect(
2193                    compare_string, msg=COMPLETION_MSG(
2194                        str_input, p, match_strings), exe=False, substrs=[p])
2195            else:
2196                self.expect(
2197                    compare_string, msg=COMPLETION_MSG(
2198                        str_input, p, match_strings), exe=False, patterns=[p])
2199
2200    def filecheck(
2201            self,
2202            command,
2203            check_file,
2204            filecheck_options = ''):
2205        # Run the command.
2206        self.runCmd(
2207                command,
2208                msg="FileCheck'ing result of `{0}`".format(command))
2209
2210        # Get the error text if there was an error, and the regular text if not.
2211        output = self.res.GetOutput() if self.res.Succeeded() \
2212                else self.res.GetError()
2213
2214        # Assemble the absolute path to the check file. As a convenience for
2215        # LLDB inline tests, assume that the check file is a relative path to
2216        # a file within the inline test directory.
2217        if check_file.endswith('.pyc'):
2218            check_file = check_file[:-1]
2219        check_file_abs = os.path.abspath(check_file)
2220
2221        # Run FileCheck.
2222        filecheck_bin = configuration.get_filecheck_path()
2223        if not filecheck_bin:
2224            self.assertTrue(False, "No valid FileCheck executable specified")
2225        filecheck_args = [filecheck_bin, check_file_abs]
2226        if filecheck_options:
2227            filecheck_args.append(filecheck_options)
2228        subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True)
2229        cmd_stdout, cmd_stderr = subproc.communicate(input=output)
2230        cmd_status = subproc.returncode
2231
2232        filecheck_cmd = " ".join(filecheck_args)
2233        filecheck_trace = """
2234--- FileCheck trace (code={0}) ---
2235{1}
2236
2237FileCheck input:
2238{2}
2239
2240FileCheck output:
2241{3}
2242{4}
2243""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr)
2244
2245        trace = cmd_status != 0 or traceAlways
2246        with recording(self, trace) as sbuf:
2247            print(filecheck_trace, file=sbuf)
2248
2249        self.assertTrue(cmd_status == 0)
2250
2251    def expect(
2252            self,
2253            str,
2254            msg=None,
2255            patterns=None,
2256            startstr=None,
2257            endstr=None,
2258            substrs=None,
2259            trace=False,
2260            error=False,
2261            matching=True,
2262            exe=True,
2263            inHistory=False):
2264        """
2265        Similar to runCmd; with additional expect style output matching ability.
2266
2267        Ask the command interpreter to handle the command and then check its
2268        return status.  The 'msg' parameter specifies an informational assert
2269        message.  We expect the output from running the command to start with
2270        'startstr', matches the substrings contained in 'substrs', and regexp
2271        matches the patterns contained in 'patterns'.
2272
2273        If the keyword argument error is set to True, it signifies that the API
2274        client is expecting the command to fail.  In this case, the error stream
2275        from running the command is retrieved and compared against the golden
2276        input, instead.
2277
2278        If the keyword argument matching is set to False, it signifies that the API
2279        client is expecting the output of the command not to match the golden
2280        input.
2281
2282        Finally, the required argument 'str' represents the lldb command to be
2283        sent to the command interpreter.  In case the keyword argument 'exe' is
2284        set to False, the 'str' is treated as a string to be matched/not-matched
2285        against the golden input.
2286        """
2287        trace = (True if traceAlways else trace)
2288
2289        if exe:
2290            # First run the command.  If we are expecting error, set check=False.
2291            # Pass the assert message along since it provides more semantic
2292            # info.
2293            self.runCmd(
2294                str,
2295                msg=msg,
2296                trace=(
2297                    True if trace else False),
2298                check=not error,
2299                inHistory=inHistory)
2300
2301            # Then compare the output against expected strings.
2302            output = self.res.GetError() if error else self.res.GetOutput()
2303
2304            # If error is True, the API client expects the command to fail!
2305            if error:
2306                self.assertFalse(self.res.Succeeded(),
2307                                 "Command '" + str + "' is expected to fail!")
2308        else:
2309            # No execution required, just compare str against the golden input.
2310            if isinstance(str, lldb.SBCommandReturnObject):
2311                output = str.GetOutput()
2312            else:
2313                output = str
2314            with recording(self, trace) as sbuf:
2315                print("looking at:", output, file=sbuf)
2316
2317        if output is None:
2318            output = ""
2319        # The heading says either "Expecting" or "Not expecting".
2320        heading = "Expecting" if matching else "Not expecting"
2321
2322        # Start from the startstr, if specified.
2323        # If there's no startstr, set the initial state appropriately.
2324        matched = output.startswith(startstr) if startstr else (
2325            True if matching else False)
2326
2327        if startstr:
2328            with recording(self, trace) as sbuf:
2329                print("%s start string: %s" % (heading, startstr), file=sbuf)
2330                print("Matched" if matched else "Not matched", file=sbuf)
2331
2332        # Look for endstr, if specified.
2333        keepgoing = matched if matching else not matched
2334        if endstr:
2335            matched = output.endswith(endstr)
2336            with recording(self, trace) as sbuf:
2337                print("%s end string: %s" % (heading, endstr), file=sbuf)
2338                print("Matched" if matched else "Not matched", file=sbuf)
2339
2340        # Look for sub strings, if specified.
2341        keepgoing = matched if matching else not matched
2342        if substrs and keepgoing:
2343            for substr in substrs:
2344                matched = output.find(substr) != -1
2345                with recording(self, trace) as sbuf:
2346                    print("%s sub string: %s" % (heading, substr), file=sbuf)
2347                    print("Matched" if matched else "Not matched", file=sbuf)
2348                keepgoing = matched if matching else not matched
2349                if not keepgoing:
2350                    break
2351
2352        # Search for regular expression patterns, if specified.
2353        keepgoing = matched if matching else not matched
2354        if patterns and keepgoing:
2355            for pattern in patterns:
2356                # Match Objects always have a boolean value of True.
2357                matched = bool(re.search(pattern, output))
2358                with recording(self, trace) as sbuf:
2359                    print("%s pattern: %s" % (heading, pattern), file=sbuf)
2360                    print("Matched" if matched else "Not matched", file=sbuf)
2361                keepgoing = matched if matching else not matched
2362                if not keepgoing:
2363                    break
2364
2365        self.assertTrue(matched if matching else not matched,
2366                        msg if msg else EXP_MSG(str, output, exe))
2367
2368    def invoke(self, obj, name, trace=False):
2369        """Use reflection to call a method dynamically with no argument."""
2370        trace = (True if traceAlways else trace)
2371
2372        method = getattr(obj, name)
2373        import inspect
2374        self.assertTrue(inspect.ismethod(method),
2375                        name + "is a method name of object: " + str(obj))
2376        result = method()
2377        with recording(self, trace) as sbuf:
2378            print(str(method) + ":", result, file=sbuf)
2379        return result
2380
2381    def build(
2382            self,
2383            architecture=None,
2384            compiler=None,
2385            dictionary=None):
2386        """Platform specific way to build the default binaries."""
2387        module = builder_module()
2388
2389        dictionary = lldbplatformutil.finalize_build_dictionary(dictionary)
2390        if self.getDebugInfo() is None:
2391            return self.buildDefault(architecture, compiler, dictionary)
2392        elif self.getDebugInfo() == "dsym":
2393            return self.buildDsym(architecture, compiler, dictionary)
2394        elif self.getDebugInfo() == "dwarf":
2395            return self.buildDwarf(architecture, compiler, dictionary)
2396        elif self.getDebugInfo() == "dwo":
2397            return self.buildDwo(architecture, compiler, dictionary)
2398        elif self.getDebugInfo() == "gmodules":
2399            return self.buildGModules(architecture, compiler, dictionary)
2400        else:
2401            self.fail("Can't build for debug info: %s" % self.getDebugInfo())
2402
2403    def run_platform_command(self, cmd):
2404        platform = self.dbg.GetSelectedPlatform()
2405        shell_command = lldb.SBPlatformShellCommand(cmd)
2406        err = platform.Run(shell_command)
2407        return (err, shell_command.GetStatus(), shell_command.GetOutput())
2408
2409    # =================================================
2410    # Misc. helper methods for debugging test execution
2411    # =================================================
2412
2413    def DebugSBValue(self, val):
2414        """Debug print a SBValue object, if traceAlways is True."""
2415        from .lldbutil import value_type_to_str
2416
2417        if not traceAlways:
2418            return
2419
2420        err = sys.stderr
2421        err.write(val.GetName() + ":\n")
2422        err.write('\t' + "TypeName         -> " + val.GetTypeName() + '\n')
2423        err.write('\t' + "ByteSize         -> " +
2424                  str(val.GetByteSize()) + '\n')
2425        err.write('\t' + "NumChildren      -> " +
2426                  str(val.GetNumChildren()) + '\n')
2427        err.write('\t' + "Value            -> " + str(val.GetValue()) + '\n')
2428        err.write('\t' + "ValueAsUnsigned  -> " +
2429                  str(val.GetValueAsUnsigned()) + '\n')
2430        err.write(
2431            '\t' +
2432            "ValueType        -> " +
2433            value_type_to_str(
2434                val.GetValueType()) +
2435            '\n')
2436        err.write('\t' + "Summary          -> " + str(val.GetSummary()) + '\n')
2437        err.write('\t' + "IsPointerType    -> " +
2438                  str(val.TypeIsPointerType()) + '\n')
2439        err.write('\t' + "Location         -> " + val.GetLocation() + '\n')
2440
2441    def DebugSBType(self, type):
2442        """Debug print a SBType object, if traceAlways is True."""
2443        if not traceAlways:
2444            return
2445
2446        err = sys.stderr
2447        err.write(type.GetName() + ":\n")
2448        err.write('\t' + "ByteSize        -> " +
2449                  str(type.GetByteSize()) + '\n')
2450        err.write('\t' + "IsPointerType   -> " +
2451                  str(type.IsPointerType()) + '\n')
2452        err.write('\t' + "IsReferenceType -> " +
2453                  str(type.IsReferenceType()) + '\n')
2454
2455    def DebugPExpect(self, child):
2456        """Debug the spwaned pexpect object."""
2457        if not traceAlways:
2458            return
2459
2460        print(child)
2461
2462    @classmethod
2463    def RemoveTempFile(cls, file):
2464        if os.path.exists(file):
2465            remove_file(file)
2466
2467# On Windows, the first attempt to delete a recently-touched file can fail
2468# because of a race with antimalware scanners.  This function will detect a
2469# failure and retry.
2470
2471
2472def remove_file(file, num_retries=1, sleep_duration=0.5):
2473    for i in range(num_retries + 1):
2474        try:
2475            os.remove(file)
2476            return True
2477        except:
2478            time.sleep(sleep_duration)
2479            continue
2480    return False
2481