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