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