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