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