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