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