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