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