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