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