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