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