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