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