1"""
2LLDB module which provides the abstract base class of lldb test case.
3
4The concrete subclass can override lldbtest.TesBase 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 print_function
35from __future__ import absolute_import
36
37# System modules
38import abc
39import collections
40from distutils.version import LooseVersion
41import gc
42import glob
43import inspect
44import os, sys, traceback
45import os.path
46import re
47import signal
48from subprocess import *
49import time
50import types
51
52# Third-party modules
53import unittest2
54from six import add_metaclass
55from six import StringIO as SixStringIO
56from six.moves.urllib import parse as urlparse
57import six
58
59# LLDB modules
60import lldb
61from . import lldbtest_config
62from . import lldbutil
63from . import test_categories
64
65# dosep.py starts lots and lots of dotest instances
66# This option helps you find if two (or more) dotest instances are using the same
67# directory at the same time
68# Enable it to cause test failures and stderr messages if dotest instances try to run in
69# the same directory simultaneously
70# it is disabled by default because it litters the test directories with ".dirlock" files
71debug_confirm_directory_exclusivity = False
72
73# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
74# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
75
76# By default, traceAlways is False.
77if "LLDB_COMMAND_TRACE" in os.environ and os.environ["LLDB_COMMAND_TRACE"]=="YES":
78    traceAlways = True
79else:
80    traceAlways = False
81
82# By default, doCleanup is True.
83if "LLDB_DO_CLEANUP" in os.environ and os.environ["LLDB_DO_CLEANUP"]=="NO":
84    doCleanup = False
85else:
86    doCleanup = True
87
88
89#
90# Some commonly used assert messages.
91#
92
93COMMAND_FAILED_AS_EXPECTED = "Command has failed as expected"
94
95CURRENT_EXECUTABLE_SET = "Current executable set successfully"
96
97PROCESS_IS_VALID = "Process is valid"
98
99PROCESS_KILLED = "Process is killed successfully"
100
101PROCESS_EXITED = "Process exited successfully"
102
103PROCESS_STOPPED = "Process status should be stopped"
104
105RUN_SUCCEEDED = "Process is launched successfully"
106
107RUN_COMPLETED = "Process exited successfully"
108
109BACKTRACE_DISPLAYED_CORRECTLY = "Backtrace displayed correctly"
110
111BREAKPOINT_CREATED = "Breakpoint created successfully"
112
113BREAKPOINT_STATE_CORRECT = "Breakpoint state is correct"
114
115BREAKPOINT_PENDING_CREATED = "Pending breakpoint created successfully"
116
117BREAKPOINT_HIT_ONCE = "Breakpoint resolved with hit cout = 1"
118
119BREAKPOINT_HIT_TWICE = "Breakpoint resolved with hit cout = 2"
120
121BREAKPOINT_HIT_THRICE = "Breakpoint resolved with hit cout = 3"
122
123MISSING_EXPECTED_REGISTERS = "At least one expected register is unavailable."
124
125OBJECT_PRINTED_CORRECTLY = "Object printed correctly"
126
127SOURCE_DISPLAYED_CORRECTLY = "Source code displayed correctly"
128
129STEP_OUT_SUCCEEDED = "Thread step-out succeeded"
130
131STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
132
133STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion"
134
135STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
136
137STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
138    STOPPED_DUE_TO_BREAKPOINT, "instead, the actual stop reason is: '%s'")
139
140STOPPED_DUE_TO_BREAKPOINT_CONDITION = "Stopped due to breakpoint condition"
141
142STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT = "Stopped due to breakpoint and ignore count"
143
144STOPPED_DUE_TO_SIGNAL = "Process state is stopped due to signal"
145
146STOPPED_DUE_TO_STEP_IN = "Process state is stopped due to step in"
147
148STOPPED_DUE_TO_WATCHPOINT = "Process should be stopped due to watchpoint"
149
150DATA_TYPES_DISPLAYED_CORRECTLY = "Data type(s) displayed correctly"
151
152VALID_BREAKPOINT = "Got a valid breakpoint"
153
154VALID_BREAKPOINT_LOCATION = "Got a valid breakpoint location"
155
156VALID_COMMAND_INTERPRETER = "Got a valid command interpreter"
157
158VALID_FILESPEC = "Got a valid filespec"
159
160VALID_MODULE = "Got a valid module"
161
162VALID_PROCESS = "Got a valid process"
163
164VALID_SYMBOL = "Got a valid symbol"
165
166VALID_TARGET = "Got a valid target"
167
168VALID_PLATFORM = "Got a valid platform"
169
170VALID_TYPE = "Got a valid type"
171
172VALID_VARIABLE = "Got a valid variable"
173
174VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly"
175
176WATCHPOINT_CREATED = "Watchpoint created successfully"
177
178def CMD_MSG(str):
179    '''A generic "Command '%s' returns successfully" message generator.'''
180    return "Command '%s' returns successfully" % str
181
182def COMPLETION_MSG(str_before, str_after):
183    '''A generic message generator for the completion mechanism.'''
184    return "'%s' successfully completes to '%s'" % (str_before, str_after)
185
186def EXP_MSG(str, exe):
187    '''A generic "'%s' returns expected result" message generator if exe.
188    Otherwise, it generates "'%s' matches expected result" message.'''
189    return "'%s' %s expected result" % (str, 'returns' if exe else 'matches')
190
191def SETTING_MSG(setting):
192    '''A generic "Value of setting '%s' is correct" message generator.'''
193    return "Value of setting '%s' is correct" % setting
194
195def EnvArray():
196    """Returns an env variable array from the os.environ map object."""
197    return list(map(lambda k,v: k+"="+v, list(os.environ.keys()), list(os.environ.values())))
198
199def line_number(filename, string_to_match):
200    """Helper function to return the line number of the first matched string."""
201    with open(filename, 'r') as f:
202        for i, line in enumerate(f):
203            if line.find(string_to_match) != -1:
204                # Found our match.
205                return i+1
206    raise Exception("Unable to find '%s' within file %s" % (string_to_match, filename))
207
208def pointer_size():
209    """Return the pointer size of the host system."""
210    import ctypes
211    a_pointer = ctypes.c_void_p(0xffff)
212    return 8 * ctypes.sizeof(a_pointer)
213
214def is_exe(fpath):
215    """Returns true if fpath is an executable."""
216    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
217
218def which(program):
219    """Returns the full path to a program; None otherwise."""
220    fpath, fname = os.path.split(program)
221    if fpath:
222        if is_exe(program):
223            return program
224    else:
225        for path in os.environ["PATH"].split(os.pathsep):
226            exe_file = os.path.join(path, program)
227            if is_exe(exe_file):
228                return exe_file
229    return None
230
231class recording(SixStringIO):
232    """
233    A nice little context manager for recording the debugger interactions into
234    our session object.  If trace flag is ON, it also emits the interactions
235    into the stderr.
236    """
237    def __init__(self, test, trace):
238        """Create a SixStringIO instance; record the session obj and trace flag."""
239        SixStringIO.__init__(self)
240        # The test might not have undergone the 'setUp(self)' phase yet, so that
241        # the attribute 'session' might not even exist yet.
242        self.session = getattr(test, "session", None) if test else None
243        self.trace = trace
244
245    def __enter__(self):
246        """
247        Context management protocol on entry to the body of the with statement.
248        Just return the SixStringIO object.
249        """
250        return self
251
252    def __exit__(self, type, value, tb):
253        """
254        Context management protocol on exit from the body of the with statement.
255        If trace is ON, it emits the recordings into stderr.  Always add the
256        recordings to our session object.  And close the SixStringIO object, too.
257        """
258        if self.trace:
259            print(self.getvalue(), file=sys.stderr)
260        if self.session:
261            print(self.getvalue(), file=self.session)
262        self.close()
263
264@add_metaclass(abc.ABCMeta)
265class _BaseProcess(object):
266
267    @abc.abstractproperty
268    def pid(self):
269        """Returns process PID if has been launched already."""
270
271    @abc.abstractmethod
272    def launch(self, executable, args):
273        """Launches new process with given executable and args."""
274
275    @abc.abstractmethod
276    def terminate(self):
277        """Terminates previously launched process.."""
278
279class _LocalProcess(_BaseProcess):
280
281    def __init__(self, trace_on):
282        self._proc = None
283        self._trace_on = trace_on
284        self._delayafterterminate = 0.1
285
286    @property
287    def pid(self):
288        return self._proc.pid
289
290    def launch(self, executable, args):
291        self._proc = Popen([executable] + args,
292                           stdout = open(os.devnull) if not self._trace_on else None,
293                           stdin = PIPE)
294
295    def terminate(self):
296        if self._proc.poll() == None:
297            # Terminate _proc like it does the pexpect
298            signals_to_try = [sig for sig in ['SIGHUP', 'SIGCONT', 'SIGINT'] if sig in dir(signal)]
299            for sig in signals_to_try:
300                try:
301                    self._proc.send_signal(getattr(signal, sig))
302                    time.sleep(self._delayafterterminate)
303                    if self._proc.poll() != None:
304                        return
305                except ValueError:
306                    pass  # Windows says SIGINT is not a valid signal to send
307            self._proc.terminate()
308            time.sleep(self._delayafterterminate)
309            if self._proc.poll() != None:
310                return
311            self._proc.kill()
312            time.sleep(self._delayafterterminate)
313
314    def poll(self):
315        return self._proc.poll()
316
317class _RemoteProcess(_BaseProcess):
318
319    def __init__(self, install_remote):
320        self._pid = None
321        self._install_remote = install_remote
322
323    @property
324    def pid(self):
325        return self._pid
326
327    def launch(self, executable, args):
328        if self._install_remote:
329            src_path = executable
330            dst_path = lldbutil.append_to_process_working_directory(os.path.basename(executable))
331
332            dst_file_spec = lldb.SBFileSpec(dst_path, False)
333            err = lldb.remote_platform.Install(lldb.SBFileSpec(src_path, True), dst_file_spec)
334            if err.Fail():
335                raise Exception("remote_platform.Install('%s', '%s') failed: %s" % (src_path, dst_path, err))
336        else:
337            dst_path = executable
338            dst_file_spec = lldb.SBFileSpec(executable, False)
339
340        launch_info = lldb.SBLaunchInfo(args)
341        launch_info.SetExecutableFile(dst_file_spec, True)
342        launch_info.SetWorkingDirectory(lldb.remote_platform.GetWorkingDirectory())
343
344        # Redirect stdout and stderr to /dev/null
345        launch_info.AddSuppressFileAction(1, False, True)
346        launch_info.AddSuppressFileAction(2, False, True)
347
348        err = lldb.remote_platform.Launch(launch_info)
349        if err.Fail():
350            raise Exception("remote_platform.Launch('%s', '%s') failed: %s" % (dst_path, args, err))
351        self._pid = launch_info.GetProcessID()
352
353    def terminate(self):
354        lldb.remote_platform.Kill(self._pid)
355
356# From 2.7's subprocess.check_output() convenience function.
357# Return a tuple (stdoutdata, stderrdata).
358def system(commands, **kwargs):
359    r"""Run an os command with arguments and return its output as a byte string.
360
361    If the exit code was non-zero it raises a CalledProcessError.  The
362    CalledProcessError object will have the return code in the returncode
363    attribute and output in the output attribute.
364
365    The arguments are the same as for the Popen constructor.  Example:
366
367    >>> check_output(["ls", "-l", "/dev/null"])
368    'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'
369
370    The stdout argument is not allowed as it is used internally.
371    To capture standard error in the result, use stderr=STDOUT.
372
373    >>> check_output(["/bin/sh", "-c",
374    ...               "ls -l non_existent_file ; exit 0"],
375    ...              stderr=STDOUT)
376    'ls: non_existent_file: No such file or directory\n'
377    """
378
379    # Assign the sender object to variable 'test' and remove it from kwargs.
380    test = kwargs.pop('sender', None)
381
382    # [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo']
383    commandList = [' '.join(x) for x in commands]
384    output = ""
385    error = ""
386    for shellCommand in commandList:
387        if 'stdout' in kwargs:
388            raise ValueError('stdout argument not allowed, it will be overridden.')
389        if 'shell' in kwargs and kwargs['shell']==False:
390            raise ValueError('shell=False not allowed')
391        process = Popen(shellCommand, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True, **kwargs)
392        pid = process.pid
393        this_output, this_error = process.communicate()
394        retcode = process.poll()
395
396        # Enable trace on failure return while tracking down FreeBSD buildbot issues
397        trace = traceAlways
398        if not trace and retcode and sys.platform.startswith("freebsd"):
399            trace = True
400
401        with recording(test, trace) as sbuf:
402            print(file=sbuf)
403            print("os command:", shellCommand, file=sbuf)
404            print("with pid:", pid, file=sbuf)
405            print("stdout:", this_output, file=sbuf)
406            print("stderr:", this_error, file=sbuf)
407            print("retcode:", retcode, file=sbuf)
408            print(file=sbuf)
409
410        if retcode:
411            cmd = kwargs.get("args")
412            if cmd is None:
413                cmd = shellCommand
414            raise CalledProcessError(retcode, cmd)
415        output = output + this_output
416        error = error + this_error
417    return (output, error)
418
419def getsource_if_available(obj):
420    """
421    Return the text of the source code for an object if available.  Otherwise,
422    a print representation is returned.
423    """
424    import inspect
425    try:
426        return inspect.getsource(obj)
427    except:
428        return repr(obj)
429
430def builder_module():
431    if sys.platform.startswith("freebsd"):
432        return __import__("builder_freebsd")
433    return __import__("builder_" + sys.platform)
434
435def run_adb_command(cmd, device_id):
436    device_id_args = []
437    if device_id:
438        device_id_args = ["-s", device_id]
439    full_cmd = ["adb"] + device_id_args + cmd
440    p = Popen(full_cmd, stdout=PIPE, stderr=PIPE)
441    stdout, stderr = p.communicate()
442    return p.returncode, stdout, stderr
443
444def append_android_envs(dictionary):
445    if dictionary is None:
446        dictionary = {}
447    dictionary["OS"] = "Android"
448    if android_device_api() >= 16:
449        dictionary["PIE"] = 1
450    return dictionary
451
452def target_is_android():
453    if not hasattr(target_is_android, 'result'):
454        triple = lldb.DBG.GetSelectedPlatform().GetTriple()
455        match = re.match(".*-.*-.*-android", triple)
456        target_is_android.result = match is not None
457    return target_is_android.result
458
459def android_device_api():
460    if not hasattr(android_device_api, 'result'):
461        assert lldb.platform_url is not None
462        device_id = None
463        parsed_url = urlparse.urlparse(lldb.platform_url)
464        host_name = parsed_url.netloc.split(":")[0]
465        if host_name != 'localhost':
466            device_id = host_name
467            if device_id.startswith('[') and device_id.endswith(']'):
468                device_id = device_id[1:-1]
469        retcode, stdout, stderr = run_adb_command(
470            ["shell", "getprop", "ro.build.version.sdk"], device_id)
471        if retcode == 0:
472            android_device_api.result = int(stdout)
473        else:
474            raise LookupError(
475                ">>> Unable to determine the API level of the Android device.\n"
476                ">>> stdout:\n%s\n"
477                ">>> stderr:\n%s\n" % (stdout, stderr))
478    return android_device_api.result
479
480def check_expected_version(comparison, expected, actual):
481    def fn_leq(x,y): return x <= y
482    def fn_less(x,y): return x < y
483    def fn_geq(x,y): return x >= y
484    def fn_greater(x,y): return x > y
485    def fn_eq(x,y): return x == y
486    def fn_neq(x,y): return x != y
487
488    op_lookup = {
489        "==": fn_eq,
490        "=": fn_eq,
491        "!=": fn_neq,
492        "<>": fn_neq,
493        ">": fn_greater,
494        "<": fn_less,
495        ">=": fn_geq,
496        "<=": fn_leq
497        }
498    expected_str = '.'.join([str(x) for x in expected])
499    actual_str = '.'.join([str(x) for x in actual])
500
501    return op_lookup[comparison](LooseVersion(actual_str), LooseVersion(expected_str))
502
503#
504# Decorators for categorizing test cases.
505#
506from functools import wraps
507def add_test_categories(cat):
508    """Decorate an item with test categories"""
509    cat = test_categories.validate(cat, True)
510    def impl(func):
511        func.getCategories = lambda test: cat
512        return func
513    return impl
514
515def benchmarks_test(func):
516    """Decorate the item as a benchmarks test."""
517    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
518        raise Exception("@benchmarks_test can only be used to decorate a test method")
519    @wraps(func)
520    def wrapper(self, *args, **kwargs):
521        if not lldb.just_do_benchmarks_test:
522            self.skipTest("benchmarks tests")
523        return func(self, *args, **kwargs)
524
525    # Mark this function as such to separate them from the regular tests.
526    wrapper.__benchmarks_test__ = True
527    return wrapper
528
529def no_debug_info_test(func):
530    """Decorate the item as a test what don't use any debug info. If this annotation is specified
531       then the test runner won't generate a separate test for each debug info format. """
532    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
533        raise Exception("@no_debug_info_test can only be used to decorate a test method")
534    @wraps(func)
535    def wrapper(self, *args, **kwargs):
536        return func(self, *args, **kwargs)
537
538    # Mark this function as such to separate them from the regular tests.
539    wrapper.__no_debug_info_test__ = True
540    return wrapper
541
542def dsym_test(func):
543    """Decorate the item as a dsym test."""
544    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
545        raise Exception("@dsym_test can only be used to decorate a test method")
546    @wraps(func)
547    def wrapper(self, *args, **kwargs):
548        if lldb.dont_do_dsym_test:
549            self.skipTest("dsym tests")
550        return func(self, *args, **kwargs)
551
552    # Mark this function as such to separate them from the regular tests.
553    wrapper.__dsym_test__ = True
554    return wrapper
555
556def dwarf_test(func):
557    """Decorate the item as a dwarf test."""
558    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
559        raise Exception("@dwarf_test can only be used to decorate a test method")
560    @wraps(func)
561    def wrapper(self, *args, **kwargs):
562        if lldb.dont_do_dwarf_test:
563            self.skipTest("dwarf tests")
564        return func(self, *args, **kwargs)
565
566    # Mark this function as such to separate them from the regular tests.
567    wrapper.__dwarf_test__ = True
568    return wrapper
569
570def dwo_test(func):
571    """Decorate the item as a dwo test."""
572    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
573        raise Exception("@dwo_test can only be used to decorate a test method")
574    @wraps(func)
575    def wrapper(self, *args, **kwargs):
576        if lldb.dont_do_dwo_test:
577            self.skipTest("dwo tests")
578        return func(self, *args, **kwargs)
579
580    # Mark this function as such to separate them from the regular tests.
581    wrapper.__dwo_test__ = True
582    return wrapper
583
584def debugserver_test(func):
585    """Decorate the item as a debugserver test."""
586    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
587        raise Exception("@debugserver_test can only be used to decorate a test method")
588    @wraps(func)
589    def wrapper(self, *args, **kwargs):
590        if lldb.dont_do_debugserver_test:
591            self.skipTest("debugserver tests")
592        return func(self, *args, **kwargs)
593
594    # Mark this function as such to separate them from the regular tests.
595    wrapper.__debugserver_test__ = True
596    return wrapper
597
598def llgs_test(func):
599    """Decorate the item as a lldb-server test."""
600    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
601        raise Exception("@llgs_test can only be used to decorate a test method")
602    @wraps(func)
603    def wrapper(self, *args, **kwargs):
604        if lldb.dont_do_llgs_test:
605            self.skipTest("llgs tests")
606        return func(self, *args, **kwargs)
607
608    # Mark this function as such to separate them from the regular tests.
609    wrapper.__llgs_test__ = True
610    return wrapper
611
612def not_remote_testsuite_ready(func):
613    """Decorate the item as a test which is not ready yet for remote testsuite."""
614    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
615        raise Exception("@not_remote_testsuite_ready can only be used to decorate a test method")
616    @wraps(func)
617    def wrapper(self, *args, **kwargs):
618        if lldb.lldbtest_remote_sandbox or lldb.remote_platform:
619            self.skipTest("not ready for remote testsuite")
620        return func(self, *args, **kwargs)
621
622    # Mark this function as such to separate them from the regular tests.
623    wrapper.__not_ready_for_remote_testsuite_test__ = True
624    return wrapper
625
626def expectedFailure(expected_fn, bugnumber=None):
627    def expectedFailure_impl(func):
628        @wraps(func)
629        def wrapper(*args, **kwargs):
630            from unittest2 import case
631            self = args[0]
632            if expected_fn(self):
633                xfail_func = unittest2.expectedFailure(func)
634                xfail_func(*args, **kwargs)
635            else:
636                func(*args, **kwargs)
637        return wrapper
638    # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments
639    # return decorator in this case, so it will be used to decorating original method
640    if six.callable(bugnumber):
641        return expectedFailure_impl(bugnumber)
642    else:
643        return expectedFailure_impl
644
645# You can also pass not_in(list) to reverse the sense of the test for the arguments that
646# are simple lists, namely oslist, compiler, and debug_info.
647
648def not_in (iterable):
649    return lambda x : x not in iterable
650
651def check_list_or_lambda (list_or_lambda, value):
652    if six.callable(list_or_lambda):
653        return list_or_lambda(value)
654    else:
655        return list_or_lambda is None or value is None or value in list_or_lambda
656
657# provide a function to xfail on defined oslist, compiler version, and archs
658# if none is specified for any argument, that argument won't be checked and thus means for all
659# for example,
660# @expectedFailureAll, xfail for all platform/compiler/arch,
661# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture
662# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386
663def expectedFailureAll(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, triple=None, debug_info=None, swig_version=None, py_version=None):
664    def fn(self):
665        oslist_passes = check_list_or_lambda(oslist, self.getPlatform())
666        compiler_passes = check_list_or_lambda(self.getCompiler(), compiler) and self.expectedCompilerVersion(compiler_version)
667        arch_passes = self.expectedArch(archs)
668        triple_passes = triple is None or re.match(triple, lldb.DBG.GetSelectedPlatform().GetTriple())
669        debug_info_passes = check_list_or_lambda(debug_info, self.debug_info)
670        swig_version_passes = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (check_expected_version(swig_version[0], swig_version[1], lldb.swig_version))
671        py_version_passes = (py_version is None) or check_expected_version(py_version[0], py_version[1], sys.version_info)
672
673        return (oslist_passes and
674                compiler_passes and
675                arch_passes and
676                triple_passes and
677                debug_info_passes and
678                swig_version_passes and
679                py_version_passes)
680    return expectedFailure(fn, bugnumber)
681
682def expectedFailureDwarf(bugnumber=None):
683    return expectedFailureAll(bugnumber=bugnumber, debug_info="dwarf")
684
685def expectedFailureDwo(bugnumber=None):
686    return expectedFailureAll(bugnumber=bugnumber, debug_info="dwo")
687
688def expectedFailureDsym(bugnumber=None):
689    return expectedFailureAll(bugnumber=bugnumber, debug_info="dsym")
690
691def expectedFailureCompiler(compiler, compiler_version=None, bugnumber=None):
692    if compiler_version is None:
693        compiler_version=['=', None]
694    return expectedFailureAll(bugnumber=bugnumber, compiler=compiler, compiler_version=compiler_version)
695
696# to XFAIL a specific clang versions, try this
697# @expectedFailureClang('bugnumber', ['<=', '3.4'])
698def expectedFailureClang(bugnumber=None, compiler_version=None):
699    return expectedFailureCompiler('clang', compiler_version, bugnumber)
700
701def expectedFailureGcc(bugnumber=None, compiler_version=None):
702    return expectedFailureCompiler('gcc', compiler_version, bugnumber)
703
704def expectedFailureIcc(bugnumber=None):
705    return expectedFailureCompiler('icc', None, bugnumber)
706
707def expectedFailureArch(arch, bugnumber=None):
708    def fn(self):
709        return arch in self.getArchitecture()
710    return expectedFailure(fn, bugnumber)
711
712def expectedFailurei386(bugnumber=None):
713    return expectedFailureArch('i386', bugnumber)
714
715def expectedFailurex86_64(bugnumber=None):
716    return expectedFailureArch('x86_64', bugnumber)
717
718def expectedFailureOS(oslist, bugnumber=None, compilers=None, debug_info=None):
719    def fn(self):
720        return (self.getPlatform() in oslist and
721                self.expectedCompiler(compilers) and
722                (debug_info is None or self.debug_info in debug_info))
723    return expectedFailure(fn, bugnumber)
724
725def expectedFailureHostOS(oslist, bugnumber=None, compilers=None):
726    def fn(self):
727        return (getHostPlatform() in oslist and
728                self.expectedCompiler(compilers))
729    return expectedFailure(fn, bugnumber)
730
731def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None):
732    # For legacy reasons, we support both "darwin" and "macosx" as OS X triples.
733    return expectedFailureOS(getDarwinOSTriples(), bugnumber, compilers, debug_info=debug_info)
734
735def expectedFailureFreeBSD(bugnumber=None, compilers=None, debug_info=None):
736    return expectedFailureOS(['freebsd'], bugnumber, compilers, debug_info=debug_info)
737
738def expectedFailureLinux(bugnumber=None, compilers=None, debug_info=None):
739    return expectedFailureOS(['linux'], bugnumber, compilers, debug_info=debug_info)
740
741def expectedFailureWindows(bugnumber=None, compilers=None, debug_info=None):
742    return expectedFailureOS(['windows'], bugnumber, compilers, debug_info=debug_info)
743
744def expectedFailureHostWindows(bugnumber=None, compilers=None):
745    return expectedFailureHostOS(['windows'], bugnumber, compilers)
746
747def matchAndroid(api_levels=None, archs=None):
748    def match(self):
749        if not target_is_android():
750            return False
751        if archs is not None and self.getArchitecture() not in archs:
752            return False
753        if api_levels is not None and android_device_api() not in api_levels:
754            return False
755        return True
756    return match
757
758
759def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None):
760    """ Mark a test as xfail for Android.
761
762    Arguments:
763        bugnumber - The LLVM pr associated with the problem.
764        api_levels - A sequence of numbers specifying the Android API levels
765            for which a test is expected to fail. None means all API level.
766        arch - A sequence of architecture names specifying the architectures
767            for which a test is expected to fail. None means all architectures.
768    """
769    return expectedFailure(matchAndroid(api_levels, archs), bugnumber)
770
771# if the test passes on the first try, we're done (success)
772# if the test fails once, then passes on the second try, raise an ExpectedFailure
773# if the test fails twice in a row, re-throw the exception from the second test run
774def expectedFlakey(expected_fn, bugnumber=None):
775    def expectedFailure_impl(func):
776        @wraps(func)
777        def wrapper(*args, **kwargs):
778            from unittest2 import case
779            self = args[0]
780            try:
781                func(*args, **kwargs)
782            # don't retry if the test case is already decorated with xfail or skip
783            except (case._ExpectedFailure, case.SkipTest, case._UnexpectedSuccess):
784                raise
785            except Exception:
786                if expected_fn(self):
787                    # before retry, run tearDown for previous run and setup for next
788                    try:
789                        self.tearDown()
790                        self.setUp()
791                        func(*args, **kwargs)
792                    except Exception:
793                        # oh snap! two failures in a row, record a failure/error
794                        raise
795                    # record the expected failure
796                    raise case._ExpectedFailure(sys.exc_info(), bugnumber)
797                else:
798                    raise
799        return wrapper
800    # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments
801    # return decorator in this case, so it will be used to decorating original method
802    if six.callable(bugnumber):
803        return expectedFailure_impl(bugnumber)
804    else:
805        return expectedFailure_impl
806
807def expectedFlakeyDwarf(bugnumber=None):
808    def fn(self):
809        return self.debug_info == "dwarf"
810    return expectedFlakey(fn, bugnumber)
811
812def expectedFlakeyDsym(bugnumber=None):
813    def fn(self):
814        return self.debug_info == "dwarf"
815    return expectedFlakey(fn, bugnumber)
816
817def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):
818    def fn(self):
819        return (self.getPlatform() in oslist and
820                self.expectedCompiler(compilers))
821    return expectedFlakey(fn, bugnumber)
822
823def expectedFlakeyDarwin(bugnumber=None, compilers=None):
824    # For legacy reasons, we support both "darwin" and "macosx" as OS X triples.
825    return expectedFlakeyOS(getDarwinOSTriples(), bugnumber, compilers)
826
827def expectedFlakeyLinux(bugnumber=None, compilers=None):
828    return expectedFlakeyOS(['linux'], bugnumber, compilers)
829
830def expectedFlakeyFreeBSD(bugnumber=None, compilers=None):
831    return expectedFlakeyOS(['freebsd'], bugnumber, compilers)
832
833def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None):
834    if compiler_version is None:
835        compiler_version=['=', None]
836    def fn(self):
837        return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version)
838    return expectedFlakey(fn, bugnumber)
839
840# @expectedFlakeyClang('bugnumber', ['<=', '3.4'])
841def expectedFlakeyClang(bugnumber=None, compiler_version=None):
842    return expectedFlakeyCompiler('clang', compiler_version, bugnumber)
843
844# @expectedFlakeyGcc('bugnumber', ['<=', '3.4'])
845def expectedFlakeyGcc(bugnumber=None, compiler_version=None):
846    return expectedFlakeyCompiler('gcc', compiler_version, bugnumber)
847
848def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None):
849    return expectedFlakey(matchAndroid(api_levels, archs), bugnumber)
850
851def skipIfRemote(func):
852    """Decorate the item to skip tests if testing remotely."""
853    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
854        raise Exception("@skipIfRemote can only be used to decorate a test method")
855    @wraps(func)
856    def wrapper(*args, **kwargs):
857        from unittest2 import case
858        if lldb.remote_platform:
859            self = args[0]
860            self.skipTest("skip on remote platform")
861        else:
862            func(*args, **kwargs)
863    return wrapper
864
865def skipUnlessListedRemote(remote_list=None):
866    def myImpl(func):
867        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
868            raise Exception("@skipIfRemote can only be used to decorate a "
869                            "test method")
870
871        @wraps(func)
872        def wrapper(*args, **kwargs):
873            if remote_list and lldb.remote_platform:
874                self = args[0]
875                triple = self.dbg.GetSelectedPlatform().GetTriple()
876                for r in remote_list:
877                    if r in triple:
878                        func(*args, **kwargs)
879                        return
880                self.skipTest("skip on remote platform %s" % str(triple))
881            else:
882                func(*args, **kwargs)
883        return wrapper
884
885    return myImpl
886
887def skipIfRemoteDueToDeadlock(func):
888    """Decorate the item to skip tests if testing remotely due to the test deadlocking."""
889    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
890        raise Exception("@skipIfRemote can only be used to decorate a test method")
891    @wraps(func)
892    def wrapper(*args, **kwargs):
893        from unittest2 import case
894        if lldb.remote_platform:
895            self = args[0]
896            self.skipTest("skip on remote platform (deadlocks)")
897        else:
898            func(*args, **kwargs)
899    return wrapper
900
901def skipIfNoSBHeaders(func):
902    """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers."""
903    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
904        raise Exception("@skipIfNoSBHeaders can only be used to decorate a test method")
905    @wraps(func)
906    def wrapper(*args, **kwargs):
907        from unittest2 import case
908        self = args[0]
909        if sys.platform.startswith("darwin"):
910            header = os.path.join(os.environ["LLDB_LIB_DIR"], 'LLDB.framework', 'Versions','Current','Headers','LLDB.h')
911        else:
912            header = os.path.join(os.environ["LLDB_SRC"], "include", "lldb", "API", "LLDB.h")
913        platform = sys.platform
914        if not os.path.exists(header):
915            self.skipTest("skip because LLDB.h header not found")
916        else:
917            func(*args, **kwargs)
918    return wrapper
919
920def skipIfiOSSimulator(func):
921    """Decorate the item to skip tests that should be skipped on the iOS Simulator."""
922    return unittest2.skipIf(hasattr(lldb, 'remote_platform_name') and lldb.remote_platform_name == 'ios-simulator', 'skip on the iOS Simulator')(func)
923
924def skipIfFreeBSD(func):
925    """Decorate the item to skip tests that should be skipped on FreeBSD."""
926    return skipIfPlatform(["freebsd"])(func)
927
928def getDarwinOSTriples():
929    return ['darwin', 'macosx', 'ios']
930
931def skipIfDarwin(func):
932    """Decorate the item to skip tests that should be skipped on Darwin."""
933    return skipIfPlatform(getDarwinOSTriples())(func)
934
935def skipIfLinux(func):
936    """Decorate the item to skip tests that should be skipped on Linux."""
937    return skipIfPlatform(["linux"])(func)
938
939def skipUnlessHostLinux(func):
940    """Decorate the item to skip tests that should be skipped on any non Linux host."""
941    return skipUnlessHostPlatform(["linux"])(func)
942
943def skipIfWindows(func):
944    """Decorate the item to skip tests that should be skipped on Windows."""
945    return skipIfPlatform(["windows"])(func)
946
947def skipIfHostWindows(func):
948    """Decorate the item to skip tests that should be skipped on Windows."""
949    return skipIfHostPlatform(["windows"])(func)
950
951def skipUnlessWindows(func):
952    """Decorate the item to skip tests that should be skipped on any non-Windows platform."""
953    return skipUnlessPlatform(["windows"])(func)
954
955def skipUnlessDarwin(func):
956    """Decorate the item to skip tests that should be skipped on any non Darwin platform."""
957    return skipUnlessPlatform(getDarwinOSTriples())(func)
958
959def skipUnlessGoInstalled(func):
960    """Decorate the item to skip tests when no Go compiler is available."""
961    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
962        raise Exception("@skipIfGcc can only be used to decorate a test method")
963    @wraps(func)
964    def wrapper(*args, **kwargs):
965        from unittest2 import case
966        self = args[0]
967        compiler = self.getGoCompilerVersion()
968        if not compiler:
969            self.skipTest("skipping because go compiler not found")
970        else:
971            # Ensure the version is the minimum version supported by
972            # the LLDB go support.
973            match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler)
974            if not match_version:
975                # Couldn't determine version.
976                self.skipTest(
977                    "skipping because go version could not be parsed "
978                    "out of {}".format(compiler))
979            else:
980                from distutils.version import StrictVersion
981                min_strict_version = StrictVersion("1.4.0")
982                compiler_strict_version = StrictVersion(match_version.group(1))
983                if compiler_strict_version < min_strict_version:
984                    self.skipTest(
985                        "skipping because available go version ({}) does "
986                        "not meet minimum required go version ({})".format(
987                            compiler_strict_version,
988                            min_strict_version))
989            func(*args, **kwargs)
990    return wrapper
991
992def getPlatform():
993    """Returns the target platform which the tests are running on."""
994    platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
995    if platform.startswith('freebsd'):
996        platform = 'freebsd'
997    return platform
998
999def getHostPlatform():
1000    """Returns the host platform running the test suite."""
1001    # Attempts to return a platform name matching a target Triple platform.
1002    if sys.platform.startswith('linux'):
1003        return 'linux'
1004    elif sys.platform.startswith('win32'):
1005        return 'windows'
1006    elif sys.platform.startswith('darwin'):
1007        return 'darwin'
1008    elif sys.platform.startswith('freebsd'):
1009        return 'freebsd'
1010    else:
1011        return sys.platform
1012
1013def platformIsDarwin():
1014    """Returns true if the OS triple for the selected platform is any valid apple OS"""
1015    return getPlatform() in getDarwinOSTriples()
1016
1017def skipIfHostIncompatibleWithRemote(func):
1018    """Decorate the item to skip tests if binaries built on this host are incompatible."""
1019    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1020        raise Exception("@skipIfHostIncompatibleWithRemote can only be used to decorate a test method")
1021    @wraps(func)
1022    def wrapper(*args, **kwargs):
1023        from unittest2 import case
1024        self = args[0]
1025        host_arch = self.getLldbArchitecture()
1026        host_platform = getHostPlatform()
1027        target_arch = self.getArchitecture()
1028        target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform()
1029        if not (target_arch == 'x86_64' and host_arch == 'i386') and host_arch != target_arch:
1030            self.skipTest("skipping because target %s is not compatible with host architecture %s" % (target_arch, host_arch))
1031        elif target_platform != host_platform:
1032            self.skipTest("skipping because target is %s but host is %s" % (target_platform, host_platform))
1033        else:
1034            func(*args, **kwargs)
1035    return wrapper
1036
1037def skipIfHostPlatform(oslist):
1038    """Decorate the item to skip tests if running on one of the listed host platforms."""
1039    return unittest2.skipIf(getHostPlatform() in oslist,
1040                            "skip on %s" % (", ".join(oslist)))
1041
1042def skipUnlessHostPlatform(oslist):
1043    """Decorate the item to skip tests unless running on one of the listed host platforms."""
1044    return unittest2.skipUnless(getHostPlatform() in oslist,
1045                                "requires on of %s" % (", ".join(oslist)))
1046
1047def skipUnlessArch(archlist):
1048    """Decorate the item to skip tests unless running on one of the listed architectures."""
1049    def myImpl(func):
1050        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1051            raise Exception("@skipUnlessArch can only be used to decorate a test method")
1052
1053        @wraps(func)
1054        def wrapper(*args, **kwargs):
1055            self = args[0]
1056            if self.getArchitecture() not in archlist:
1057                self.skipTest("skipping for architecture %s (requires one of %s)" %
1058                    (self.getArchitecture(), ", ".join(archlist)))
1059            else:
1060                func(*args, **kwargs)
1061        return wrapper
1062
1063    return myImpl
1064
1065def skipIfPlatform(oslist):
1066    """Decorate the item to skip tests if running on one of the listed platforms."""
1067    return unittest2.skipIf(getPlatform() in oslist,
1068                            "skip on %s" % (", ".join(oslist)))
1069
1070def skipUnlessPlatform(oslist):
1071    """Decorate the item to skip tests unless running on one of the listed platforms."""
1072    return unittest2.skipUnless(getPlatform() in oslist,
1073                                "requires on of %s" % (", ".join(oslist)))
1074
1075def skipIfLinuxClang(func):
1076    """Decorate the item to skip tests that should be skipped if building on
1077       Linux with clang.
1078    """
1079    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1080        raise Exception("@skipIfLinuxClang can only be used to decorate a test method")
1081    @wraps(func)
1082    def wrapper(*args, **kwargs):
1083        from unittest2 import case
1084        self = args[0]
1085        compiler = self.getCompiler()
1086        platform = self.getPlatform()
1087        if "clang" in compiler and platform == "linux":
1088            self.skipTest("skipping because Clang is used on Linux")
1089        else:
1090            func(*args, **kwargs)
1091    return wrapper
1092
1093# provide a function to skip on defined oslist, compiler version, and archs
1094# if none is specified for any argument, that argument won't be checked and thus means for all
1095# for example,
1096# @skipIf, skip for all platform/compiler/arch,
1097# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture
1098# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386
1099
1100# TODO: refactor current code, to make skipIfxxx functions to call this function
1101def skipIf(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, debug_info=None, swig_version=None, py_version=None):
1102    def fn(self):
1103        oslist_passes = oslist is None or self.getPlatform() in oslist
1104        compiler_passes = compiler is None or (compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version))
1105        arch_passes = self.expectedArch(archs)
1106        debug_info_passes = debug_info is None or self.debug_info in debug_info
1107        swig_version_passes = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (check_expected_version(swig_version[0], swig_version[1], lldb.swig_version))
1108        py_version_passes = (py_version is None) or check_expected_version(py_version[0], py_version[1], sys.version_info)
1109
1110        return (oslist_passes and
1111                compiler_passes and
1112                arch_passes and
1113                debug_info_passes and
1114                swig_version_passes and
1115                py_version_passes)
1116
1117    local_vars = locals()
1118    args = [x for x in inspect.getargspec(skipIf).args]
1119    arg_vals = [eval(x, globals(), local_vars) for x in args]
1120    args = [x for x in zip(args, arg_vals) if x[1] is not None]
1121    reasons = ['%s=%s' % (x, str(y)) for (x,y) in args]
1122    return skipTestIfFn(fn, bugnumber, skipReason='skipping because ' + ' && '.join(reasons))
1123
1124def skipIfDebugInfo(bugnumber=None, debug_info=None):
1125    return skipIf(bugnumber=bugnumber, debug_info=debug_info)
1126
1127def skipIfDWO(bugnumber=None):
1128    return skipIfDebugInfo(bugnumber, ["dwo"])
1129
1130def skipIfDwarf(bugnumber=None):
1131    return skipIfDebugInfo(bugnumber, ["dwarf"])
1132
1133def skipIfDsym(bugnumber=None):
1134    return skipIfDebugInfo(bugnumber, ["dsym"])
1135
1136def skipTestIfFn(expected_fn, bugnumber=None, skipReason=None):
1137    def skipTestIfFn_impl(func):
1138        @wraps(func)
1139        def wrapper(*args, **kwargs):
1140            from unittest2 import case
1141            self = args[0]
1142            if expected_fn(self):
1143               self.skipTest(skipReason)
1144            else:
1145                func(*args, **kwargs)
1146        return wrapper
1147    if six.callable(bugnumber):
1148        return skipTestIfFn_impl(bugnumber)
1149    else:
1150        return skipTestIfFn_impl
1151
1152def skipIfGcc(func):
1153    """Decorate the item to skip tests that should be skipped if building with gcc ."""
1154    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1155        raise Exception("@skipIfGcc can only be used to decorate a test method")
1156    @wraps(func)
1157    def wrapper(*args, **kwargs):
1158        from unittest2 import case
1159        self = args[0]
1160        compiler = self.getCompiler()
1161        if "gcc" in compiler:
1162            self.skipTest("skipping because gcc is the test compiler")
1163        else:
1164            func(*args, **kwargs)
1165    return wrapper
1166
1167def skipIfIcc(func):
1168    """Decorate the item to skip tests that should be skipped if building with icc ."""
1169    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1170        raise Exception("@skipIfIcc can only be used to decorate a test method")
1171    @wraps(func)
1172    def wrapper(*args, **kwargs):
1173        from unittest2 import case
1174        self = args[0]
1175        compiler = self.getCompiler()
1176        if "icc" in compiler:
1177            self.skipTest("skipping because icc is the test compiler")
1178        else:
1179            func(*args, **kwargs)
1180    return wrapper
1181
1182def skipIfi386(func):
1183    """Decorate the item to skip tests that should be skipped if building 32-bit."""
1184    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1185        raise Exception("@skipIfi386 can only be used to decorate a test method")
1186    @wraps(func)
1187    def wrapper(*args, **kwargs):
1188        from unittest2 import case
1189        self = args[0]
1190        if "i386" == self.getArchitecture():
1191            self.skipTest("skipping because i386 is not a supported architecture")
1192        else:
1193            func(*args, **kwargs)
1194    return wrapper
1195
1196def skipIfTargetAndroid(api_levels=None, archs=None):
1197    """Decorator to skip tests when the target is Android.
1198
1199    Arguments:
1200        api_levels - The API levels for which the test should be skipped. If
1201            it is None, then the test will be skipped for all API levels.
1202        arch - A sequence of architecture names specifying the architectures
1203            for which a test is skipped. None means all architectures.
1204    """
1205    def myImpl(func):
1206        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1207            raise Exception("@skipIfTargetAndroid can only be used to "
1208                            "decorate a test method")
1209        @wraps(func)
1210        def wrapper(*args, **kwargs):
1211            from unittest2 import case
1212            self = args[0]
1213            if matchAndroid(api_levels, archs)(self):
1214                self.skipTest("skiped on Android target with API %d and architecture %s" %
1215                        (android_device_api(), self.getArchitecture()))
1216            func(*args, **kwargs)
1217        return wrapper
1218    return myImpl
1219
1220def skipUnlessCompilerRt(func):
1221    """Decorate the item to skip tests if testing remotely."""
1222    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
1223        raise Exception("@skipUnless can only be used to decorate a test method")
1224    @wraps(func)
1225    def wrapper(*args, **kwargs):
1226        from unittest2 import case
1227        import os.path
1228        compilerRtPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "llvm","projects","compiler-rt")
1229        print(compilerRtPath)
1230        if not os.path.exists(compilerRtPath):
1231            self = args[0]
1232            self.skipTest("skip if compiler-rt not found")
1233        else:
1234            func(*args, **kwargs)
1235    return wrapper
1236
1237class _PlatformContext(object):
1238    """Value object class which contains platform-specific options."""
1239
1240    def __init__(self, shlib_environment_var, shlib_prefix, shlib_extension):
1241        self.shlib_environment_var = shlib_environment_var
1242        self.shlib_prefix = shlib_prefix
1243        self.shlib_extension = shlib_extension
1244
1245
1246class Base(unittest2.TestCase):
1247    """
1248    Abstract base for performing lldb (see TestBase) or other generic tests (see
1249    BenchBase for one example).  lldbtest.Base works with the test driver to
1250    accomplish things.
1251
1252    """
1253
1254    # The concrete subclass should override this attribute.
1255    mydir = None
1256
1257    # Keep track of the old current working directory.
1258    oldcwd = None
1259
1260    @staticmethod
1261    def compute_mydir(test_file):
1262        '''Subclasses should call this function to correctly calculate the required "mydir" attribute as follows:
1263
1264            mydir = TestBase.compute_mydir(__file__)'''
1265        test_dir = os.path.dirname(test_file)
1266        return test_dir[len(os.environ["LLDB_TEST"])+1:]
1267
1268    def TraceOn(self):
1269        """Returns True if we are in trace mode (tracing detailed test execution)."""
1270        return traceAlways
1271
1272    @classmethod
1273    def setUpClass(cls):
1274        """
1275        Python unittest framework class setup fixture.
1276        Do current directory manipulation.
1277        """
1278        # Fail fast if 'mydir' attribute is not overridden.
1279        if not cls.mydir or len(cls.mydir) == 0:
1280            raise Exception("Subclasses must override the 'mydir' attribute.")
1281
1282        # Save old working directory.
1283        cls.oldcwd = os.getcwd()
1284
1285        # Change current working directory if ${LLDB_TEST} is defined.
1286        # See also dotest.py which sets up ${LLDB_TEST}.
1287        if ("LLDB_TEST" in os.environ):
1288            full_dir = os.path.join(os.environ["LLDB_TEST"], cls.mydir)
1289            if traceAlways:
1290                print("Change dir to:", full_dir, file=sys.stderr)
1291            os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
1292
1293        if debug_confirm_directory_exclusivity:
1294            import lock
1295            cls.dir_lock = lock.Lock(os.path.join(full_dir, ".dirlock"))
1296            try:
1297                cls.dir_lock.try_acquire()
1298                # write the class that owns the lock into the lock file
1299                cls.dir_lock.handle.write(cls.__name__)
1300            except IOError as ioerror:
1301                # nothing else should have this directory lock
1302                # wait here until we get a lock
1303                cls.dir_lock.acquire()
1304                # read the previous owner from the lock file
1305                lock_id = cls.dir_lock.handle.read()
1306                print("LOCK ERROR: {} wants to lock '{}' but it is already locked by '{}'".format(cls.__name__, full_dir, lock_id), file=sys.stderr)
1307                raise ioerror
1308
1309        # Set platform context.
1310        if platformIsDarwin():
1311            cls.platformContext = _PlatformContext('DYLD_LIBRARY_PATH', 'lib', 'dylib')
1312        elif getPlatform() == "linux" or getPlatform() == "freebsd":
1313            cls.platformContext = _PlatformContext('LD_LIBRARY_PATH', 'lib', 'so')
1314        else:
1315            cls.platformContext = None
1316
1317    @classmethod
1318    def tearDownClass(cls):
1319        """
1320        Python unittest framework class teardown fixture.
1321        Do class-wide cleanup.
1322        """
1323
1324        if doCleanup and not lldb.skip_build_and_cleanup:
1325            # First, let's do the platform-specific cleanup.
1326            module = builder_module()
1327            module.cleanup()
1328
1329            # Subclass might have specific cleanup function defined.
1330            if getattr(cls, "classCleanup", None):
1331                if traceAlways:
1332                    print("Call class-specific cleanup function for class:", cls, file=sys.stderr)
1333                try:
1334                    cls.classCleanup()
1335                except:
1336                    exc_type, exc_value, exc_tb = sys.exc_info()
1337                    traceback.print_exception(exc_type, exc_value, exc_tb)
1338
1339        if debug_confirm_directory_exclusivity:
1340            cls.dir_lock.release()
1341            del cls.dir_lock
1342
1343        # Restore old working directory.
1344        if traceAlways:
1345            print("Restore dir to:", cls.oldcwd, file=sys.stderr)
1346        os.chdir(cls.oldcwd)
1347
1348    @classmethod
1349    def skipLongRunningTest(cls):
1350        """
1351        By default, we skip long running test case.
1352        This can be overridden by passing '-l' to the test driver (dotest.py).
1353        """
1354        if "LLDB_SKIP_LONG_RUNNING_TEST" in os.environ and "NO" == os.environ["LLDB_SKIP_LONG_RUNNING_TEST"]:
1355            return False
1356        else:
1357            return True
1358
1359    def enableLogChannelsForCurrentTest(self):
1360        if len(lldbtest_config.channels) == 0:
1361            return
1362
1363        # if debug channels are specified in lldbtest_config.channels,
1364        # create a new set of log files for every test
1365        log_basename = self.getLogBasenameForCurrentTest()
1366
1367        # confirm that the file is writeable
1368        host_log_path = "{}-host.log".format(log_basename)
1369        open(host_log_path, 'w').close()
1370
1371        log_enable = "log enable -Tpn -f {} ".format(host_log_path)
1372        for channel_with_categories in lldbtest_config.channels:
1373            channel_then_categories = channel_with_categories.split(' ', 1)
1374            channel = channel_then_categories[0]
1375            if len(channel_then_categories) > 1:
1376                categories = channel_then_categories[1]
1377            else:
1378                categories = "default"
1379
1380            if channel == "gdb-remote":
1381                # communicate gdb-remote categories to debugserver
1382                os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories
1383
1384            self.ci.HandleCommand(log_enable + channel_with_categories, self.res)
1385            if not self.res.Succeeded():
1386                raise Exception('log enable failed (check LLDB_LOG_OPTION env variable)')
1387
1388        # Communicate log path name to debugserver & lldb-server
1389        server_log_path = "{}-server.log".format(log_basename)
1390        open(server_log_path, 'w').close()
1391        os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path
1392
1393        # Communicate channels to lldb-server
1394        os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels)
1395
1396        if len(lldbtest_config.channels) == 0:
1397            return
1398
1399    def disableLogChannelsForCurrentTest(self):
1400        # close all log files that we opened
1401        for channel_and_categories in lldbtest_config.channels:
1402            # channel format - <channel-name> [<category0> [<category1> ...]]
1403            channel = channel_and_categories.split(' ', 1)[0]
1404            self.ci.HandleCommand("log disable " + channel, self.res)
1405            if not self.res.Succeeded():
1406                raise Exception('log disable failed (check LLDB_LOG_OPTION env variable)')
1407
1408    def setUp(self):
1409        """Fixture for unittest test case setup.
1410
1411        It works with the test driver to conditionally skip tests and does other
1412        initializations."""
1413        #import traceback
1414        #traceback.print_stack()
1415
1416        if "LIBCXX_PATH" in os.environ:
1417            self.libcxxPath = os.environ["LIBCXX_PATH"]
1418        else:
1419            self.libcxxPath = None
1420
1421        if "LLDBMI_EXEC" in os.environ:
1422            self.lldbMiExec = os.environ["LLDBMI_EXEC"]
1423        else:
1424            self.lldbMiExec = None
1425
1426        # If we spawn an lldb process for test (via pexpect), do not load the
1427        # init file unless told otherwise.
1428        if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]:
1429            self.lldbOption = ""
1430        else:
1431            self.lldbOption = "--no-lldbinit"
1432
1433        # Assign the test method name to self.testMethodName.
1434        #
1435        # For an example of the use of this attribute, look at test/types dir.
1436        # There are a bunch of test cases under test/types and we don't want the
1437        # module cacheing subsystem to be confused with executable name "a.out"
1438        # used for all the test cases.
1439        self.testMethodName = self._testMethodName
1440
1441        # Benchmarks test is decorated with @benchmarks_test,
1442        # which also sets the "__benchmarks_test__" attribute of the
1443        # function object to True.
1444        try:
1445            if lldb.just_do_benchmarks_test:
1446                testMethod = getattr(self, self._testMethodName)
1447                if getattr(testMethod, "__benchmarks_test__", False):
1448                    pass
1449                else:
1450                    self.skipTest("non benchmarks test")
1451        except AttributeError:
1452            pass
1453
1454        # This is for the case of directly spawning 'lldb'/'gdb' and interacting
1455        # with it using pexpect.
1456        self.child = None
1457        self.child_prompt = "(lldb) "
1458        # If the child is interacting with the embedded script interpreter,
1459        # there are two exits required during tear down, first to quit the
1460        # embedded script interpreter and second to quit the lldb command
1461        # interpreter.
1462        self.child_in_script_interpreter = False
1463
1464        # These are for customized teardown cleanup.
1465        self.dict = None
1466        self.doTearDownCleanup = False
1467        # And in rare cases where there are multiple teardown cleanups.
1468        self.dicts = []
1469        self.doTearDownCleanups = False
1470
1471        # List of spawned subproces.Popen objects
1472        self.subprocesses = []
1473
1474        # List of forked process PIDs
1475        self.forkedProcessPids = []
1476
1477        # Create a string buffer to record the session info, to be dumped into a
1478        # test case specific file if test failure is encountered.
1479        self.log_basename = self.getLogBasenameForCurrentTest()
1480
1481        session_file = "{}.log".format(self.log_basename)
1482        # Python 3 doesn't support unbuffered I/O in text mode.  Open buffered.
1483        self.session = open(session_file, "w")
1484
1485        # Optimistically set __errored__, __failed__, __expected__ to False
1486        # initially.  If the test errored/failed, the session info
1487        # (self.session) is then dumped into a session specific file for
1488        # diagnosis.
1489        self.__cleanup_errored__ = False
1490        self.__errored__    = False
1491        self.__failed__     = False
1492        self.__expected__   = False
1493        # We are also interested in unexpected success.
1494        self.__unexpected__ = False
1495        # And skipped tests.
1496        self.__skipped__ = False
1497
1498        # See addTearDownHook(self, hook) which allows the client to add a hook
1499        # function to be run during tearDown() time.
1500        self.hooks = []
1501
1502        # See HideStdout(self).
1503        self.sys_stdout_hidden = False
1504
1505        if self.platformContext:
1506            # set environment variable names for finding shared libraries
1507            self.dylibPath = self.platformContext.shlib_environment_var
1508
1509        # Create the debugger instance if necessary.
1510        try:
1511            self.dbg = lldb.DBG
1512        except AttributeError:
1513            self.dbg = lldb.SBDebugger.Create()
1514
1515        if not self.dbg:
1516            raise Exception('Invalid debugger instance')
1517
1518        # Retrieve the associated command interpreter instance.
1519        self.ci = self.dbg.GetCommandInterpreter()
1520        if not self.ci:
1521            raise Exception('Could not get the command interpreter')
1522
1523        # And the result object.
1524        self.res = lldb.SBCommandReturnObject()
1525
1526        self.enableLogChannelsForCurrentTest()
1527
1528        #Initialize debug_info
1529        self.debug_info = None
1530
1531    def runHooks(self, child=None, child_prompt=None, use_cmd_api=False):
1532        """Perform the run hooks to bring lldb debugger to the desired state.
1533
1534        By default, expect a pexpect spawned child and child prompt to be
1535        supplied (use_cmd_api=False).  If use_cmd_api is true, ignore the child
1536        and child prompt and use self.runCmd() to run the hooks one by one.
1537
1538        Note that child is a process spawned by pexpect.spawn().  If not, your
1539        test case is mostly likely going to fail.
1540
1541        See also dotest.py where lldb.runHooks are processed/populated.
1542        """
1543        if not lldb.runHooks:
1544            self.skipTest("No runhooks specified for lldb, skip the test")
1545        if use_cmd_api:
1546            for hook in lldb.runhooks:
1547                self.runCmd(hook)
1548        else:
1549            if not child or not child_prompt:
1550                self.fail("Both child and child_prompt need to be defined.")
1551            for hook in lldb.runHooks:
1552                child.sendline(hook)
1553                child.expect_exact(child_prompt)
1554
1555    def setAsync(self, value):
1556        """ Sets async mode to True/False and ensures it is reset after the testcase completes."""
1557        old_async = self.dbg.GetAsync()
1558        self.dbg.SetAsync(value)
1559        self.addTearDownHook(lambda: self.dbg.SetAsync(old_async))
1560
1561    def cleanupSubprocesses(self):
1562        # Ensure any subprocesses are cleaned up
1563        for p in self.subprocesses:
1564            p.terminate()
1565            del p
1566        del self.subprocesses[:]
1567        # Ensure any forked processes are cleaned up
1568        for pid in self.forkedProcessPids:
1569            if os.path.exists("/proc/" + str(pid)):
1570                os.kill(pid, signal.SIGTERM)
1571
1572    def spawnSubprocess(self, executable, args=[], install_remote=True):
1573        """ Creates a subprocess.Popen object with the specified executable and arguments,
1574            saves it in self.subprocesses, and returns the object.
1575            NOTE: if using this function, ensure you also call:
1576
1577              self.addTearDownHook(self.cleanupSubprocesses)
1578
1579            otherwise the test suite will leak processes.
1580        """
1581        proc = _RemoteProcess(install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn())
1582        proc.launch(executable, args)
1583        self.subprocesses.append(proc)
1584        return proc
1585
1586    def forkSubprocess(self, executable, args=[]):
1587        """ Fork a subprocess with its own group ID.
1588            NOTE: if using this function, ensure you also call:
1589
1590              self.addTearDownHook(self.cleanupSubprocesses)
1591
1592            otherwise the test suite will leak processes.
1593        """
1594        child_pid = os.fork()
1595        if child_pid == 0:
1596            # If more I/O support is required, this can be beefed up.
1597            fd = os.open(os.devnull, os.O_RDWR)
1598            os.dup2(fd, 1)
1599            os.dup2(fd, 2)
1600            # This call causes the child to have its of group ID
1601            os.setpgid(0,0)
1602            os.execvp(executable, [executable] + args)
1603        # Give the child time to get through the execvp() call
1604        time.sleep(0.1)
1605        self.forkedProcessPids.append(child_pid)
1606        return child_pid
1607
1608    def HideStdout(self):
1609        """Hide output to stdout from the user.
1610
1611        During test execution, there might be cases where we don't want to show the
1612        standard output to the user.  For example,
1613
1614            self.runCmd(r'''sc print("\n\n\tHello!\n")''')
1615
1616        tests whether command abbreviation for 'script' works or not.  There is no
1617        need to show the 'Hello' output to the user as long as the 'script' command
1618        succeeds and we are not in TraceOn() mode (see the '-t' option).
1619
1620        In this case, the test method calls self.HideStdout(self) to redirect the
1621        sys.stdout to a null device, and restores the sys.stdout upon teardown.
1622
1623        Note that you should only call this method at most once during a test case
1624        execution.  Any subsequent call has no effect at all."""
1625        if self.sys_stdout_hidden:
1626            return
1627
1628        self.sys_stdout_hidden = True
1629        old_stdout = sys.stdout
1630        sys.stdout = open(os.devnull, 'w')
1631        def restore_stdout():
1632            sys.stdout = old_stdout
1633        self.addTearDownHook(restore_stdout)
1634
1635    # =======================================================================
1636    # Methods for customized teardown cleanups as well as execution of hooks.
1637    # =======================================================================
1638
1639    def setTearDownCleanup(self, dictionary=None):
1640        """Register a cleanup action at tearDown() time with a dictinary"""
1641        self.dict = dictionary
1642        self.doTearDownCleanup = True
1643
1644    def addTearDownCleanup(self, dictionary):
1645        """Add a cleanup action at tearDown() time with a dictinary"""
1646        self.dicts.append(dictionary)
1647        self.doTearDownCleanups = True
1648
1649    def addTearDownHook(self, hook):
1650        """
1651        Add a function to be run during tearDown() time.
1652
1653        Hooks are executed in a first come first serve manner.
1654        """
1655        if six.callable(hook):
1656            with recording(self, traceAlways) as sbuf:
1657                print("Adding tearDown hook:", getsource_if_available(hook), file=sbuf)
1658            self.hooks.append(hook)
1659
1660        return self
1661
1662    def deletePexpectChild(self):
1663        # This is for the case of directly spawning 'lldb' and interacting with it
1664        # using pexpect.
1665        if self.child and self.child.isalive():
1666            import pexpect
1667            with recording(self, traceAlways) as sbuf:
1668                print("tearing down the child process....", file=sbuf)
1669            try:
1670                if self.child_in_script_interpreter:
1671                    self.child.sendline('quit()')
1672                    self.child.expect_exact(self.child_prompt)
1673                self.child.sendline('settings set interpreter.prompt-on-quit false')
1674                self.child.sendline('quit')
1675                self.child.expect(pexpect.EOF)
1676            except (ValueError, pexpect.ExceptionPexpect):
1677                # child is already terminated
1678                pass
1679            except OSError as exception:
1680                import errno
1681                if exception.errno != errno.EIO:
1682                    # unexpected error
1683                    raise
1684                # child is already terminated
1685                pass
1686            finally:
1687                # Give it one final blow to make sure the child is terminated.
1688                self.child.close()
1689
1690    def tearDown(self):
1691        """Fixture for unittest test case teardown."""
1692        #import traceback
1693        #traceback.print_stack()
1694
1695        self.deletePexpectChild()
1696
1697        # Check and run any hook functions.
1698        for hook in reversed(self.hooks):
1699            with recording(self, traceAlways) as sbuf:
1700                print("Executing tearDown hook:", getsource_if_available(hook), file=sbuf)
1701            import inspect
1702            hook_argc = len(inspect.getargspec(hook).args)
1703            if hook_argc == 0 or getattr(hook,'im_self',None):
1704                hook()
1705            elif hook_argc == 1:
1706                hook(self)
1707            else:
1708                hook() # try the plain call and hope it works
1709
1710        del self.hooks
1711
1712        # Perform registered teardown cleanup.
1713        if doCleanup and self.doTearDownCleanup:
1714            self.cleanup(dictionary=self.dict)
1715
1716        # In rare cases where there are multiple teardown cleanups added.
1717        if doCleanup and self.doTearDownCleanups:
1718            if self.dicts:
1719                for dict in reversed(self.dicts):
1720                    self.cleanup(dictionary=dict)
1721
1722        self.disableLogChannelsForCurrentTest()
1723
1724    # =========================================================
1725    # Various callbacks to allow introspection of test progress
1726    # =========================================================
1727
1728    def markError(self):
1729        """Callback invoked when an error (unexpected exception) errored."""
1730        self.__errored__ = True
1731        with recording(self, False) as sbuf:
1732            # False because there's no need to write "ERROR" to the stderr twice.
1733            # Once by the Python unittest framework, and a second time by us.
1734            print("ERROR", file=sbuf)
1735
1736    def markCleanupError(self):
1737        """Callback invoked when an error occurs while a test is cleaning up."""
1738        self.__cleanup_errored__ = True
1739        with recording(self, False) as sbuf:
1740            # False because there's no need to write "CLEANUP_ERROR" to the stderr twice.
1741            # Once by the Python unittest framework, and a second time by us.
1742            print("CLEANUP_ERROR", file=sbuf)
1743
1744    def markFailure(self):
1745        """Callback invoked when a failure (test assertion failure) occurred."""
1746        self.__failed__ = True
1747        with recording(self, False) as sbuf:
1748            # False because there's no need to write "FAIL" to the stderr twice.
1749            # Once by the Python unittest framework, and a second time by us.
1750            print("FAIL", file=sbuf)
1751
1752    def markExpectedFailure(self,err,bugnumber):
1753        """Callback invoked when an expected failure/error occurred."""
1754        self.__expected__ = True
1755        with recording(self, False) as sbuf:
1756            # False because there's no need to write "expected failure" to the
1757            # stderr twice.
1758            # Once by the Python unittest framework, and a second time by us.
1759            if bugnumber == None:
1760                print("expected failure", file=sbuf)
1761            else:
1762                print("expected failure (problem id:" + str(bugnumber) + ")", file=sbuf)
1763
1764    def markSkippedTest(self):
1765        """Callback invoked when a test is skipped."""
1766        self.__skipped__ = True
1767        with recording(self, False) as sbuf:
1768            # False because there's no need to write "skipped test" to the
1769            # stderr twice.
1770            # Once by the Python unittest framework, and a second time by us.
1771            print("skipped test", file=sbuf)
1772
1773    def markUnexpectedSuccess(self, bugnumber):
1774        """Callback invoked when an unexpected success occurred."""
1775        self.__unexpected__ = True
1776        with recording(self, False) as sbuf:
1777            # False because there's no need to write "unexpected success" to the
1778            # stderr twice.
1779            # Once by the Python unittest framework, and a second time by us.
1780            if bugnumber == None:
1781                print("unexpected success", file=sbuf)
1782            else:
1783                print("unexpected success (problem id:" + str(bugnumber) + ")", file=sbuf)
1784
1785    def getRerunArgs(self):
1786        return " -f %s.%s" % (self.__class__.__name__, self._testMethodName)
1787
1788    def getLogBasenameForCurrentTest(self, prefix=None):
1789        """
1790        returns a partial path that can be used as the beginning of the name of multiple
1791        log files pertaining to this test
1792
1793        <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method>
1794        """
1795        dname = os.path.join(os.environ["LLDB_TEST"],
1796                     os.environ["LLDB_SESSION_DIRNAME"])
1797        if not os.path.isdir(dname):
1798            os.mkdir(dname)
1799
1800        compiler = self.getCompiler()
1801
1802        if compiler[1] == ':':
1803            compiler = compiler[2:]
1804        if os.path.altsep is not None:
1805            compiler = compiler.replace(os.path.altsep, os.path.sep)
1806
1807        fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), "_".join(compiler.split(os.path.sep)))
1808        if len(fname) > 200:
1809            fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), compiler.split(os.path.sep)[-1])
1810
1811        if prefix is not None:
1812            fname = "{}-{}".format(prefix, fname)
1813
1814        return os.path.join(dname, fname)
1815
1816    def dumpSessionInfo(self):
1817        """
1818        Dump the debugger interactions leading to a test error/failure.  This
1819        allows for more convenient postmortem analysis.
1820
1821        See also LLDBTestResult (dotest.py) which is a singlton class derived
1822        from TextTestResult and overwrites addError, addFailure, and
1823        addExpectedFailure methods to allow us to to mark the test instance as
1824        such.
1825        """
1826
1827        # We are here because self.tearDown() detected that this test instance
1828        # either errored or failed.  The lldb.test_result singleton contains
1829        # two lists (erros and failures) which get populated by the unittest
1830        # framework.  Look over there for stack trace information.
1831        #
1832        # The lists contain 2-tuples of TestCase instances and strings holding
1833        # formatted tracebacks.
1834        #
1835        # See http://docs.python.org/library/unittest.html#unittest.TestResult.
1836
1837        # output tracebacks into session
1838        pairs = []
1839        if self.__errored__:
1840            pairs = lldb.test_result.errors
1841            prefix = 'Error'
1842        elif self.__cleanup_errored__:
1843            pairs = lldb.test_result.cleanup_errors
1844            prefix = 'CleanupError'
1845        elif self.__failed__:
1846            pairs = lldb.test_result.failures
1847            prefix = 'Failure'
1848        elif self.__expected__:
1849            pairs = lldb.test_result.expectedFailures
1850            prefix = 'ExpectedFailure'
1851        elif self.__skipped__:
1852            prefix = 'SkippedTest'
1853        elif self.__unexpected__:
1854            prefix = 'UnexpectedSuccess'
1855        else:
1856            prefix = 'Success'
1857
1858        if not self.__unexpected__ and not self.__skipped__:
1859            for test, traceback in pairs:
1860                if test is self:
1861                    print(traceback, file=self.session)
1862
1863        # put footer (timestamp/rerun instructions) into session
1864        testMethod = getattr(self, self._testMethodName)
1865        if getattr(testMethod, "__benchmarks_test__", False):
1866            benchmarks = True
1867        else:
1868            benchmarks = False
1869
1870        import datetime
1871        print("Session info generated @", datetime.datetime.now().ctime(), file=self.session)
1872        print("To rerun this test, issue the following command from the 'test' directory:\n", file=self.session)
1873        print("./dotest.py %s -v %s %s" % (self.getRunOptions(),
1874                                                 ('+b' if benchmarks else '-t'),
1875                                                 self.getRerunArgs()), file=self.session)
1876        self.session.close()
1877        del self.session
1878
1879        # process the log files
1880        log_files_for_this_test = glob.glob(self.log_basename + "*")
1881
1882        if prefix != 'Success' or lldbtest_config.log_success:
1883            # keep all log files, rename them to include prefix
1884            dst_log_basename = self.getLogBasenameForCurrentTest(prefix)
1885            for src in log_files_for_this_test:
1886                if os.path.isfile(src):
1887                    dst = src.replace(self.log_basename, dst_log_basename)
1888                    if os.name == "nt" and os.path.isfile(dst):
1889                        # On Windows, renaming a -> b will throw an exception if b exists.  On non-Windows platforms
1890                        # it silently replaces the destination.  Ultimately this means that atomic renames are not
1891                        # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the
1892                        # destination first if it already exists.
1893                        os.remove(dst)
1894
1895                    os.rename(src, dst)
1896        else:
1897            # success!  (and we don't want log files) delete log files
1898            for log_file in log_files_for_this_test:
1899                try:
1900                    os.unlink(log_file)
1901                except:
1902                    # We've seen consistent unlink failures on Windows, perhaps because the
1903                    # just-created log file is being scanned by anti-virus.  Empirically, this
1904                    # sleep-and-retry approach allows tests to succeed much more reliably.
1905                    # Attempts to figure out exactly what process was still holding a file handle
1906                    # have failed because running instrumentation like Process Monitor seems to
1907                    # slow things down enough that the problem becomes much less consistent.
1908                    time.sleep(0.5)
1909                    os.unlink(log_file)
1910
1911    # ====================================================
1912    # Config. methods supported through a plugin interface
1913    # (enables reading of the current test configuration)
1914    # ====================================================
1915
1916    def getArchitecture(self):
1917        """Returns the architecture in effect the test suite is running with."""
1918        module = builder_module()
1919        arch = module.getArchitecture()
1920        if arch == 'amd64':
1921            arch = 'x86_64'
1922        return arch
1923
1924    def getLldbArchitecture(self):
1925        """Returns the architecture of the lldb binary."""
1926        if not hasattr(self, 'lldbArchitecture'):
1927
1928            # spawn local process
1929            command = [
1930                lldbtest_config.lldbExec,
1931                "-o",
1932                "file " + lldbtest_config.lldbExec,
1933                "-o",
1934                "quit"
1935            ]
1936
1937            output = check_output(command)
1938            str = output.decode("utf-8");
1939
1940            for line in str.splitlines():
1941                m = re.search("Current executable set to '.*' \\((.*)\\)\\.", line)
1942                if m:
1943                    self.lldbArchitecture = m.group(1)
1944                    break
1945
1946        return self.lldbArchitecture
1947
1948    def getCompiler(self):
1949        """Returns the compiler in effect the test suite is running with."""
1950        module = builder_module()
1951        return module.getCompiler()
1952
1953    def getCompilerBinary(self):
1954        """Returns the compiler binary the test suite is running with."""
1955        return self.getCompiler().split()[0]
1956
1957    def getCompilerVersion(self):
1958        """ Returns a string that represents the compiler version.
1959            Supports: llvm, clang.
1960        """
1961        from .lldbutil import which
1962        version = 'unknown'
1963
1964        compiler = self.getCompilerBinary()
1965        version_output = system([[which(compiler), "-v"]])[1]
1966        for line in version_output.split(os.linesep):
1967            m = re.search('version ([0-9\.]+)', line)
1968            if m:
1969                version = m.group(1)
1970        return version
1971
1972    def getGoCompilerVersion(self):
1973        """ Returns a string that represents the go compiler version, or None if go is not found.
1974        """
1975        compiler = which("go")
1976        if compiler:
1977            version_output = system([[compiler, "version"]])[0]
1978            for line in version_output.split(os.linesep):
1979                m = re.search('go version (devel|go\\S+)', line)
1980                if m:
1981                    return m.group(1)
1982        return None
1983
1984    def platformIsDarwin(self):
1985        """Returns true if the OS triple for the selected platform is any valid apple OS"""
1986        return platformIsDarwin()
1987
1988    def getPlatform(self):
1989        """Returns the target platform the test suite is running on."""
1990        return getPlatform()
1991
1992    def isIntelCompiler(self):
1993        """ Returns true if using an Intel (ICC) compiler, false otherwise. """
1994        return any([x in self.getCompiler() for x in ["icc", "icpc", "icl"]])
1995
1996    def expectedCompilerVersion(self, compiler_version):
1997        """Returns True iff compiler_version[1] matches the current compiler version.
1998           Use compiler_version[0] to specify the operator used to determine if a match has occurred.
1999           Any operator other than the following defaults to an equality test:
2000             '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
2001        """
2002        if (compiler_version == None):
2003            return True
2004        operator = str(compiler_version[0])
2005        version = compiler_version[1]
2006
2007        if (version == None):
2008            return True
2009        if (operator == '>'):
2010            return self.getCompilerVersion() > version
2011        if (operator == '>=' or operator == '=>'):
2012            return self.getCompilerVersion() >= version
2013        if (operator == '<'):
2014            return self.getCompilerVersion() < version
2015        if (operator == '<=' or operator == '=<'):
2016            return self.getCompilerVersion() <= version
2017        if (operator == '!=' or operator == '!' or operator == 'not'):
2018            return str(version) not in str(self.getCompilerVersion())
2019        return str(version) in str(self.getCompilerVersion())
2020
2021    def expectedCompiler(self, compilers):
2022        """Returns True iff any element of compilers is a sub-string of the current compiler."""
2023        if (compilers == None):
2024            return True
2025
2026        for compiler in compilers:
2027            if compiler in self.getCompiler():
2028                return True
2029
2030        return False
2031
2032    def expectedArch(self, archs):
2033        """Returns True iff any element of archs is a sub-string of the current architecture."""
2034        if (archs == None):
2035            return True
2036
2037        for arch in archs:
2038            if arch in self.getArchitecture():
2039                return True
2040
2041        return False
2042
2043    def getRunOptions(self):
2044        """Command line option for -A and -C to run this test again, called from
2045        self.dumpSessionInfo()."""
2046        arch = self.getArchitecture()
2047        comp = self.getCompiler()
2048        if arch:
2049            option_str = "-A " + arch
2050        else:
2051            option_str = ""
2052        if comp:
2053            option_str += " -C " + comp
2054        return option_str
2055
2056    # ==================================================
2057    # Build methods supported through a plugin interface
2058    # ==================================================
2059
2060    def getstdlibFlag(self):
2061        """ Returns the proper -stdlib flag, or empty if not required."""
2062        if self.platformIsDarwin() or self.getPlatform() == "freebsd":
2063            stdlibflag = "-stdlib=libc++"
2064        else:
2065            stdlibflag = ""
2066        return stdlibflag
2067
2068    def getstdFlag(self):
2069        """ Returns the proper stdflag. """
2070        if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
2071          stdflag = "-std=c++0x"
2072        else:
2073          stdflag = "-std=c++11"
2074        return stdflag
2075
2076    def buildDriver(self, sources, exe_name):
2077        """ Platform-specific way to build a program that links with LLDB (via the liblldb.so
2078            or LLDB.framework).
2079        """
2080
2081        stdflag = self.getstdFlag()
2082        stdlibflag = self.getstdlibFlag()
2083
2084        lib_dir = os.environ["LLDB_LIB_DIR"]
2085        if sys.platform.startswith("darwin"):
2086            dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB')
2087            d = {'CXX_SOURCES' : sources,
2088                 'EXE' : exe_name,
2089                 'CFLAGS_EXTRAS' : "%s %s" % (stdflag, stdlibflag),
2090                 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir,
2091                 'LD_EXTRAS' : "%s -Wl,-rpath,%s" % (dsym, lib_dir),
2092                }
2093        elif sys.platform.startswith('freebsd') or sys.platform.startswith("linux") or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile':
2094            d = {'CXX_SOURCES' : sources,
2095                 'EXE' : exe_name,
2096                 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2097                 'LD_EXTRAS' : "-L%s -llldb" % lib_dir}
2098        elif sys.platform.startswith('win'):
2099            d = {'CXX_SOURCES' : sources,
2100                 'EXE' : exe_name,
2101                 'CFLAGS_EXTRAS' : "%s %s -I%s" % (stdflag, stdlibflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2102                 'LD_EXTRAS' : "-L%s -lliblldb" % os.environ["LLDB_IMPLIB_DIR"]}
2103        if self.TraceOn():
2104            print("Building LLDB Driver (%s) from sources %s" % (exe_name, sources))
2105
2106        self.buildDefault(dictionary=d)
2107
2108    def buildLibrary(self, sources, lib_name):
2109        """Platform specific way to build a default library. """
2110
2111        stdflag = self.getstdFlag()
2112
2113        lib_dir = os.environ["LLDB_LIB_DIR"]
2114        if self.platformIsDarwin():
2115            dsym = os.path.join(lib_dir, 'LLDB.framework', 'LLDB')
2116            d = {'DYLIB_CXX_SOURCES' : sources,
2117                 'DYLIB_NAME' : lib_name,
2118                 'CFLAGS_EXTRAS' : "%s -stdlib=libc++" % stdflag,
2119                 'FRAMEWORK_INCLUDES' : "-F%s" % lib_dir,
2120                 'LD_EXTRAS' : "%s -Wl,-rpath,%s -dynamiclib" % (dsym, lib_dir),
2121                }
2122        elif self.getPlatform() == 'freebsd' or self.getPlatform() == 'linux' or os.environ.get('LLDB_BUILD_TYPE') == 'Makefile':
2123            d = {'DYLIB_CXX_SOURCES' : sources,
2124                 'DYLIB_NAME' : lib_name,
2125                 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2126                 'LD_EXTRAS' : "-shared -L%s -llldb" % lib_dir}
2127        elif self.getPlatform() == 'windows':
2128            d = {'DYLIB_CXX_SOURCES' : sources,
2129                 'DYLIB_NAME' : lib_name,
2130                 'CFLAGS_EXTRAS' : "%s -I%s -fPIC" % (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
2131                 'LD_EXTRAS' : "-shared -l%s\liblldb.lib" % self.os.environ["LLDB_IMPLIB_DIR"]}
2132        if self.TraceOn():
2133            print("Building LLDB Library (%s) from sources %s" % (lib_name, sources))
2134
2135        self.buildDefault(dictionary=d)
2136
2137    def buildProgram(self, sources, exe_name):
2138        """ Platform specific way to build an executable from C/C++ sources. """
2139        d = {'CXX_SOURCES' : sources,
2140             'EXE' : exe_name}
2141        self.buildDefault(dictionary=d)
2142
2143    def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True):
2144        """Platform specific way to build the default binaries."""
2145        if lldb.skip_build_and_cleanup:
2146            return
2147        module = builder_module()
2148        if target_is_android():
2149            dictionary = append_android_envs(dictionary)
2150        if not module.buildDefault(self, architecture, compiler, dictionary, clean):
2151            raise Exception("Don't know how to build default binary")
2152
2153    def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True):
2154        """Platform specific way to build binaries with dsym info."""
2155        if lldb.skip_build_and_cleanup:
2156            return
2157        module = builder_module()
2158        if not module.buildDsym(self, architecture, compiler, dictionary, clean):
2159            raise Exception("Don't know how to build binary with dsym")
2160
2161    def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True):
2162        """Platform specific way to build binaries with dwarf maps."""
2163        if lldb.skip_build_and_cleanup:
2164            return
2165        module = builder_module()
2166        if target_is_android():
2167            dictionary = append_android_envs(dictionary)
2168        if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
2169            raise Exception("Don't know how to build binary with dwarf")
2170
2171    def buildDwo(self, architecture=None, compiler=None, dictionary=None, clean=True):
2172        """Platform specific way to build binaries with dwarf maps."""
2173        if lldb.skip_build_and_cleanup:
2174            return
2175        module = builder_module()
2176        if target_is_android():
2177            dictionary = append_android_envs(dictionary)
2178        if not module.buildDwo(self, architecture, compiler, dictionary, clean):
2179            raise Exception("Don't know how to build binary with dwo")
2180
2181    def buildGo(self):
2182        """Build the default go binary.
2183        """
2184        system([[which('go'), 'build -gcflags "-N -l" -o a.out main.go']])
2185
2186    def signBinary(self, binary_path):
2187        if sys.platform.startswith("darwin"):
2188            codesign_cmd = "codesign --force --sign lldb_codesign %s" % (binary_path)
2189            call(codesign_cmd, shell=True)
2190
2191    def findBuiltClang(self):
2192        """Tries to find and use Clang from the build directory as the compiler (instead of the system compiler)."""
2193        paths_to_try = [
2194          "llvm-build/Release+Asserts/x86_64/Release+Asserts/bin/clang",
2195          "llvm-build/Debug+Asserts/x86_64/Debug+Asserts/bin/clang",
2196          "llvm-build/Release/x86_64/Release/bin/clang",
2197          "llvm-build/Debug/x86_64/Debug/bin/clang",
2198        ]
2199        lldb_root_path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")
2200        for p in paths_to_try:
2201            path = os.path.join(lldb_root_path, p)
2202            if os.path.exists(path):
2203                return path
2204
2205        # Tries to find clang at the same folder as the lldb
2206        path = os.path.join(os.path.dirname(lldbtest_config.lldbExec), "clang")
2207        if os.path.exists(path):
2208            return path
2209
2210        return os.environ["CC"]
2211
2212    def getBuildFlags(self, use_cpp11=True, use_libcxx=False, use_libstdcxx=False):
2213        """ Returns a dictionary (which can be provided to build* functions above) which
2214            contains OS-specific build flags.
2215        """
2216        cflags = ""
2217        ldflags = ""
2218
2219        # On Mac OS X, unless specifically requested to use libstdc++, use libc++
2220        if not use_libstdcxx and self.platformIsDarwin():
2221            use_libcxx = True
2222
2223        if use_libcxx and self.libcxxPath:
2224            cflags += "-stdlib=libc++ "
2225            if self.libcxxPath:
2226                libcxxInclude = os.path.join(self.libcxxPath, "include")
2227                libcxxLib = os.path.join(self.libcxxPath, "lib")
2228                if os.path.isdir(libcxxInclude) and os.path.isdir(libcxxLib):
2229                    cflags += "-nostdinc++ -I%s -L%s -Wl,-rpath,%s " % (libcxxInclude, libcxxLib, libcxxLib)
2230
2231        if use_cpp11:
2232            cflags += "-std="
2233            if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
2234                cflags += "c++0x"
2235            else:
2236                cflags += "c++11"
2237        if self.platformIsDarwin() or self.getPlatform() == "freebsd":
2238            cflags += " -stdlib=libc++"
2239        elif "clang" in self.getCompiler():
2240            cflags += " -stdlib=libstdc++"
2241
2242        return {'CFLAGS_EXTRAS' : cflags,
2243                'LD_EXTRAS' : ldflags,
2244               }
2245
2246    def cleanup(self, dictionary=None):
2247        """Platform specific way to do cleanup after build."""
2248        if lldb.skip_build_and_cleanup:
2249            return
2250        module = builder_module()
2251        if not module.cleanup(self, dictionary):
2252            raise Exception("Don't know how to do cleanup with dictionary: "+dictionary)
2253
2254    def getLLDBLibraryEnvVal(self):
2255        """ Returns the path that the OS-specific library search environment variable
2256            (self.dylibPath) should be set to in order for a program to find the LLDB
2257            library. If an environment variable named self.dylibPath is already set,
2258            the new path is appended to it and returned.
2259        """
2260        existing_library_path = os.environ[self.dylibPath] if self.dylibPath in os.environ else None
2261        lib_dir = os.environ["LLDB_LIB_DIR"]
2262        if existing_library_path:
2263            return "%s:%s" % (existing_library_path, lib_dir)
2264        elif sys.platform.startswith("darwin"):
2265            return os.path.join(lib_dir, 'LLDB.framework')
2266        else:
2267            return lib_dir
2268
2269    def getLibcPlusPlusLibs(self):
2270        if self.getPlatform() == 'freebsd' or self.getPlatform() == 'linux':
2271            return ['libc++.so.1']
2272        else:
2273            return ['libc++.1.dylib','libc++abi.dylib']
2274
2275# Metaclass for TestBase to change the list of test metods when a new TestCase is loaded.
2276# We change the test methods to create a new test method for each test for each debug info we are
2277# testing. The name of the new test method will be '<original-name>_<debug-info>' and with adding
2278# the new test method we remove the old method at the same time.
2279class LLDBTestCaseFactory(type):
2280    def __new__(cls, name, bases, attrs):
2281        newattrs = {}
2282        for attrname, attrvalue in attrs.items():
2283            if attrname.startswith("test") and not getattr(attrvalue, "__no_debug_info_test__", False):
2284                @dsym_test
2285                @wraps(attrvalue)
2286                def dsym_test_method(self, attrvalue=attrvalue):
2287                    self.debug_info = "dsym"
2288                    return attrvalue(self)
2289                dsym_method_name = attrname + "_dsym"
2290                dsym_test_method.__name__ = dsym_method_name
2291                newattrs[dsym_method_name] = dsym_test_method
2292
2293                @dwarf_test
2294                @wraps(attrvalue)
2295                def dwarf_test_method(self, attrvalue=attrvalue):
2296                    self.debug_info = "dwarf"
2297                    return attrvalue(self)
2298                dwarf_method_name = attrname + "_dwarf"
2299                dwarf_test_method.__name__ = dwarf_method_name
2300                newattrs[dwarf_method_name] = dwarf_test_method
2301
2302                @dwo_test
2303                @wraps(attrvalue)
2304                def dwo_test_method(self, attrvalue=attrvalue):
2305                    self.debug_info = "dwo"
2306                    return attrvalue(self)
2307                dwo_method_name = attrname + "_dwo"
2308                dwo_test_method.__name__ = dwo_method_name
2309                newattrs[dwo_method_name] = dwo_test_method
2310            else:
2311                newattrs[attrname] = attrvalue
2312        return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs)
2313
2314# Setup the metaclass for this class to change the list of the test methods when a new class is loaded
2315@add_metaclass(LLDBTestCaseFactory)
2316class TestBase(Base):
2317    """
2318    This abstract base class is meant to be subclassed.  It provides default
2319    implementations for setUpClass(), tearDownClass(), setUp(), and tearDown(),
2320    among other things.
2321
2322    Important things for test class writers:
2323
2324        - Overwrite the mydir class attribute, otherwise your test class won't
2325          run.  It specifies the relative directory to the top level 'test' so
2326          the test harness can change to the correct working directory before
2327          running your test.
2328
2329        - The setUp method sets up things to facilitate subsequent interactions
2330          with the debugger as part of the test.  These include:
2331              - populate the test method name
2332              - create/get a debugger set with synchronous mode (self.dbg)
2333              - get the command interpreter from with the debugger (self.ci)
2334              - create a result object for use with the command interpreter
2335                (self.res)
2336              - plus other stuffs
2337
2338        - The tearDown method tries to perform some necessary cleanup on behalf
2339          of the test to return the debugger to a good state for the next test.
2340          These include:
2341              - execute any tearDown hooks registered by the test method with
2342                TestBase.addTearDownHook(); examples can be found in
2343                settings/TestSettings.py
2344              - kill the inferior process associated with each target, if any,
2345                and, then delete the target from the debugger's target list
2346              - perform build cleanup before running the next test method in the
2347                same test class; examples of registering for this service can be
2348                found in types/TestIntegerTypes.py with the call:
2349                    - self.setTearDownCleanup(dictionary=d)
2350
2351        - Similarly setUpClass and tearDownClass perform classwise setup and
2352          teardown fixtures.  The tearDownClass method invokes a default build
2353          cleanup for the entire test class;  also, subclasses can implement the
2354          classmethod classCleanup(cls) to perform special class cleanup action.
2355
2356        - The instance methods runCmd and expect are used heavily by existing
2357          test cases to send a command to the command interpreter and to perform
2358          string/pattern matching on the output of such command execution.  The
2359          expect method also provides a mode to peform string/pattern matching
2360          without running a command.
2361
2362        - The build methods buildDefault, buildDsym, and buildDwarf are used to
2363          build the binaries used during a particular test scenario.  A plugin
2364          should be provided for the sys.platform running the test suite.  The
2365          Mac OS X implementation is located in plugins/darwin.py.
2366    """
2367
2368    # Maximum allowed attempts when launching the inferior process.
2369    # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable.
2370    maxLaunchCount = 3;
2371
2372    # Time to wait before the next launching attempt in second(s).
2373    # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable.
2374    timeWaitNextLaunch = 1.0;
2375
2376    def doDelay(self):
2377        """See option -w of dotest.py."""
2378        if ("LLDB_WAIT_BETWEEN_TEST_CASES" in os.environ and
2379            os.environ["LLDB_WAIT_BETWEEN_TEST_CASES"] == 'YES'):
2380            waitTime = 1.0
2381            if "LLDB_TIME_WAIT_BETWEEN_TEST_CASES" in os.environ:
2382                waitTime = float(os.environ["LLDB_TIME_WAIT_BETWEEN_TEST_CASES"])
2383            time.sleep(waitTime)
2384
2385    # Returns the list of categories to which this test case belongs
2386    # by default, look for a ".categories" file, and read its contents
2387    # if no such file exists, traverse the hierarchy - we guarantee
2388    # a .categories to exist at the top level directory so we do not end up
2389    # looping endlessly - subclasses are free to define their own categories
2390    # in whatever way makes sense to them
2391    def getCategories(self):
2392        import inspect
2393        import os.path
2394        folder = inspect.getfile(self.__class__)
2395        folder = os.path.dirname(folder)
2396        while folder != '/':
2397                categories_file_name = os.path.join(folder,".categories")
2398                if os.path.exists(categories_file_name):
2399                        categories_file = open(categories_file_name,'r')
2400                        categories = categories_file.readline()
2401                        categories_file.close()
2402                        categories = str.replace(categories,'\n','')
2403                        categories = str.replace(categories,'\r','')
2404                        return categories.split(',')
2405                else:
2406                        folder = os.path.dirname(folder)
2407                        continue
2408
2409    def setUp(self):
2410        #import traceback
2411        #traceback.print_stack()
2412
2413        # Works with the test driver to conditionally skip tests via decorators.
2414        Base.setUp(self)
2415
2416        try:
2417            if lldb.blacklist:
2418                className = self.__class__.__name__
2419                classAndMethodName = "%s.%s" % (className, self._testMethodName)
2420                if className in lldb.blacklist:
2421                    self.skipTest(lldb.blacklist.get(className))
2422                elif classAndMethodName in lldb.blacklist:
2423                    self.skipTest(lldb.blacklist.get(classAndMethodName))
2424        except AttributeError:
2425            pass
2426
2427        # Insert some delay between successive test cases if specified.
2428        self.doDelay()
2429
2430        if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
2431            self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
2432
2433        if "LLDB_TIME_WAIT_NEXT_LAUNCH" in os.environ:
2434            self.timeWaitNextLaunch = float(os.environ["LLDB_TIME_WAIT_NEXT_LAUNCH"])
2435
2436        #
2437        # Warning: MAJOR HACK AHEAD!
2438        # If we are running testsuite remotely (by checking lldb.lldbtest_remote_sandbox),
2439        # redefine the self.dbg.CreateTarget(filename) method to execute a "file filename"
2440        # command, instead.  See also runCmd() where it decorates the "file filename" call
2441        # with additional functionality when running testsuite remotely.
2442        #
2443        if lldb.lldbtest_remote_sandbox:
2444            def DecoratedCreateTarget(arg):
2445                self.runCmd("file %s" % arg)
2446                target = self.dbg.GetSelectedTarget()
2447                #
2448                # SBtarget.LaunchSimple () currently not working for remote platform?
2449                # johnny @ 04/23/2012
2450                #
2451                def DecoratedLaunchSimple(argv, envp, wd):
2452                    self.runCmd("run")
2453                    return target.GetProcess()
2454                target.LaunchSimple = DecoratedLaunchSimple
2455
2456                return target
2457            self.dbg.CreateTarget = DecoratedCreateTarget
2458            if self.TraceOn():
2459                print("self.dbg.Create is redefined to:\n%s" % getsource_if_available(DecoratedCreateTarget))
2460
2461        # We want our debugger to be synchronous.
2462        self.dbg.SetAsync(False)
2463
2464        # Retrieve the associated command interpreter instance.
2465        self.ci = self.dbg.GetCommandInterpreter()
2466        if not self.ci:
2467            raise Exception('Could not get the command interpreter')
2468
2469        # And the result object.
2470        self.res = lldb.SBCommandReturnObject()
2471
2472        # Run global pre-flight code, if defined via the config file.
2473        if lldb.pre_flight:
2474            lldb.pre_flight(self)
2475
2476        if lldb.remote_platform and lldb.remote_platform_working_dir:
2477            remote_test_dir = lldbutil.join_remote_paths(
2478                    lldb.remote_platform_working_dir,
2479                    self.getArchitecture(),
2480                    str(self.test_number),
2481                    self.mydir)
2482            error = lldb.remote_platform.MakeDirectory(remote_test_dir, 448) # 448 = 0o700
2483            if error.Success():
2484                lldb.remote_platform.SetWorkingDirectory(remote_test_dir)
2485
2486                # This function removes all files from the current working directory while leaving
2487                # the directories in place. The cleaup is required to reduce the disk space required
2488                # by the test suit while leaving the directories untached is neccessary because
2489                # sub-directories might belong to an other test
2490                def clean_working_directory():
2491                    # TODO: Make it working on Windows when we need it for remote debugging support
2492                    # TODO: Replace the heuristic to remove the files with a logic what collects the
2493                    # list of files we have to remove during test runs.
2494                    shell_cmd = lldb.SBPlatformShellCommand("rm %s/*" % remote_test_dir)
2495                    lldb.remote_platform.Run(shell_cmd)
2496                self.addTearDownHook(clean_working_directory)
2497            else:
2498                print("error: making remote directory '%s': %s" % (remote_test_dir, error))
2499
2500    def registerSharedLibrariesWithTarget(self, target, shlibs):
2501        '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing
2502
2503        Any modules in the target that have their remote install file specification set will
2504        get uploaded to the remote host. This function registers the local copies of the
2505        shared libraries with the target and sets their remote install locations so they will
2506        be uploaded when the target is run.
2507        '''
2508        if not shlibs or not self.platformContext:
2509            return None
2510
2511        shlib_environment_var = self.platformContext.shlib_environment_var
2512        shlib_prefix = self.platformContext.shlib_prefix
2513        shlib_extension = '.' + self.platformContext.shlib_extension
2514
2515        working_dir = self.get_process_working_directory()
2516        environment = ['%s=%s' % (shlib_environment_var, working_dir)]
2517        # Add any shared libraries to our target if remote so they get
2518        # uploaded into the working directory on the remote side
2519        for name in shlibs:
2520            # The path can be a full path to a shared library, or a make file name like "Foo" for
2521            # "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
2522            # basename like "libFoo.so". So figure out which one it is and resolve the local copy
2523            # of the shared library accordingly
2524            if os.path.exists(name):
2525                local_shlib_path = name # name is the full path to the local shared library
2526            else:
2527                # Check relative names
2528                local_shlib_path = os.path.join(os.getcwd(), shlib_prefix + name + shlib_extension)
2529                if not os.path.exists(local_shlib_path):
2530                    local_shlib_path = os.path.join(os.getcwd(), name + shlib_extension)
2531                    if not os.path.exists(local_shlib_path):
2532                        local_shlib_path = os.path.join(os.getcwd(), name)
2533
2534                # Make sure we found the local shared library in the above code
2535                self.assertTrue(os.path.exists(local_shlib_path))
2536
2537            # Add the shared library to our target
2538            shlib_module = target.AddModule(local_shlib_path, None, None, None)
2539            if lldb.remote_platform:
2540                # We must set the remote install location if we want the shared library
2541                # to get uploaded to the remote target
2542                remote_shlib_path = lldbutil.append_to_process_working_directory(os.path.basename(local_shlib_path))
2543                shlib_module.SetRemoteInstallFileSpec(lldb.SBFileSpec(remote_shlib_path, False))
2544
2545        return environment
2546
2547    # utility methods that tests can use to access the current objects
2548    def target(self):
2549        if not self.dbg:
2550            raise Exception('Invalid debugger instance')
2551        return self.dbg.GetSelectedTarget()
2552
2553    def process(self):
2554        if not self.dbg:
2555            raise Exception('Invalid debugger instance')
2556        return self.dbg.GetSelectedTarget().GetProcess()
2557
2558    def thread(self):
2559        if not self.dbg:
2560            raise Exception('Invalid debugger instance')
2561        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread()
2562
2563    def frame(self):
2564        if not self.dbg:
2565            raise Exception('Invalid debugger instance')
2566        return self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
2567
2568    def get_process_working_directory(self):
2569        '''Get the working directory that should be used when launching processes for local or remote processes.'''
2570        if lldb.remote_platform:
2571            # Remote tests set the platform working directory up in TestBase.setUp()
2572            return lldb.remote_platform.GetWorkingDirectory()
2573        else:
2574            # local tests change directory into each test subdirectory
2575            return os.getcwd()
2576
2577    def tearDown(self):
2578        #import traceback
2579        #traceback.print_stack()
2580
2581        # Ensure all the references to SB objects have gone away so that we can
2582        # be sure that all test-specific resources have been freed before we
2583        # attempt to delete the targets.
2584        gc.collect()
2585
2586        # Delete the target(s) from the debugger as a general cleanup step.
2587        # This includes terminating the process for each target, if any.
2588        # We'd like to reuse the debugger for our next test without incurring
2589        # the initialization overhead.
2590        targets = []
2591        for target in self.dbg:
2592            if target:
2593                targets.append(target)
2594                process = target.GetProcess()
2595                if process:
2596                    rc = self.invoke(process, "Kill")
2597                    self.assertTrue(rc.Success(), PROCESS_KILLED)
2598        for target in targets:
2599            self.dbg.DeleteTarget(target)
2600
2601        # Run global post-flight code, if defined via the config file.
2602        if lldb.post_flight:
2603            lldb.post_flight(self)
2604
2605        # Do this last, to make sure it's in reverse order from how we setup.
2606        Base.tearDown(self)
2607
2608        # This must be the last statement, otherwise teardown hooks or other
2609        # lines might depend on this still being active.
2610        del self.dbg
2611
2612    def switch_to_thread_with_stop_reason(self, stop_reason):
2613        """
2614        Run the 'thread list' command, and select the thread with stop reason as
2615        'stop_reason'.  If no such thread exists, no select action is done.
2616        """
2617        from .lldbutil import stop_reason_to_str
2618        self.runCmd('thread list')
2619        output = self.res.GetOutput()
2620        thread_line_pattern = re.compile("^[ *] thread #([0-9]+):.*stop reason = %s" %
2621                                         stop_reason_to_str(stop_reason))
2622        for line in output.splitlines():
2623            matched = thread_line_pattern.match(line)
2624            if matched:
2625                self.runCmd('thread select %s' % matched.group(1))
2626
2627    def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False):
2628        """
2629        Ask the command interpreter to handle the command and then check its
2630        return status.
2631        """
2632        # Fail fast if 'cmd' is not meaningful.
2633        if not cmd or len(cmd) == 0:
2634            raise Exception("Bad 'cmd' parameter encountered")
2635
2636        trace = (True if traceAlways else trace)
2637
2638        # This is an opportunity to insert the 'platform target-install' command if we are told so
2639        # via the settig of lldb.lldbtest_remote_sandbox.
2640        if cmd.startswith("target create "):
2641            cmd = cmd.replace("target create ", "file ")
2642        if cmd.startswith("file ") and lldb.lldbtest_remote_sandbox:
2643            with recording(self, trace) as sbuf:
2644                the_rest = cmd.split("file ")[1]
2645                # Split the rest of the command line.
2646                atoms = the_rest.split()
2647                #
2648                # NOTE: This assumes that the options, if any, follow the file command,
2649                # instead of follow the specified target.
2650                #
2651                target = atoms[-1]
2652                # Now let's get the absolute pathname of our target.
2653                abs_target = os.path.abspath(target)
2654                print("Found a file command, target (with absolute pathname)=%s" % abs_target, file=sbuf)
2655                fpath, fname = os.path.split(abs_target)
2656                parent_dir = os.path.split(fpath)[0]
2657                platform_target_install_command = 'platform target-install %s %s' % (fpath, lldb.lldbtest_remote_sandbox)
2658                print("Insert this command to be run first: %s" % platform_target_install_command, file=sbuf)
2659                self.ci.HandleCommand(platform_target_install_command, self.res)
2660                # And this is the file command we want to execute, instead.
2661                #
2662                # Warning: SIDE EFFECT AHEAD!!!
2663                # Populate the remote executable pathname into the lldb namespace,
2664                # so that test cases can grab this thing out of the namespace.
2665                #
2666                lldb.lldbtest_remote_sandboxed_executable = abs_target.replace(parent_dir, lldb.lldbtest_remote_sandbox)
2667                cmd = "file -P %s %s %s" % (lldb.lldbtest_remote_sandboxed_executable, the_rest.replace(target, ''), abs_target)
2668                print("And this is the replaced file command: %s" % cmd, file=sbuf)
2669
2670        running = (cmd.startswith("run") or cmd.startswith("process launch"))
2671
2672        for i in range(self.maxLaunchCount if running else 1):
2673            self.ci.HandleCommand(cmd, self.res, inHistory)
2674
2675            with recording(self, trace) as sbuf:
2676                print("runCmd:", cmd, file=sbuf)
2677                if not check:
2678                    print("check of return status not required", file=sbuf)
2679                if self.res.Succeeded():
2680                    print("output:", self.res.GetOutput(), file=sbuf)
2681                else:
2682                    print("runCmd failed!", file=sbuf)
2683                    print(self.res.GetError(), file=sbuf)
2684
2685            if self.res.Succeeded():
2686                break
2687            elif running:
2688                # For process launch, wait some time before possible next try.
2689                time.sleep(self.timeWaitNextLaunch)
2690                with recording(self, trace) as sbuf:
2691                    print("Command '" + cmd + "' failed!", file=sbuf)
2692
2693        if check:
2694            self.assertTrue(self.res.Succeeded(),
2695                            msg if msg else CMD_MSG(cmd))
2696
2697    def match (self, str, patterns, msg=None, trace=False, error=False, matching=True, exe=True):
2698        """run command in str, and match the result against regexp in patterns returning the match object for the first matching pattern
2699
2700        Otherwise, all the arguments have the same meanings as for the expect function"""
2701
2702        trace = (True if traceAlways else trace)
2703
2704        if exe:
2705            # First run the command.  If we are expecting error, set check=False.
2706            # Pass the assert message along since it provides more semantic info.
2707            self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error)
2708
2709            # Then compare the output against expected strings.
2710            output = self.res.GetError() if error else self.res.GetOutput()
2711
2712            # If error is True, the API client expects the command to fail!
2713            if error:
2714                self.assertFalse(self.res.Succeeded(),
2715                                 "Command '" + str + "' is expected to fail!")
2716        else:
2717            # No execution required, just compare str against the golden input.
2718            output = str
2719            with recording(self, trace) as sbuf:
2720                print("looking at:", output, file=sbuf)
2721
2722        # The heading says either "Expecting" or "Not expecting".
2723        heading = "Expecting" if matching else "Not expecting"
2724
2725        for pattern in patterns:
2726            # Match Objects always have a boolean value of True.
2727            match_object = re.search(pattern, output)
2728            matched = bool(match_object)
2729            with recording(self, trace) as sbuf:
2730                print("%s pattern: %s" % (heading, pattern), file=sbuf)
2731                print("Matched" if matched else "Not matched", file=sbuf)
2732            if matched:
2733                break
2734
2735        self.assertTrue(matched if matching else not matched,
2736                        msg if msg else EXP_MSG(str, exe))
2737
2738        return match_object
2739
2740    def expect(self, str, msg=None, patterns=None, startstr=None, endstr=None, substrs=None, trace=False, error=False, matching=True, exe=True, inHistory=False):
2741        """
2742        Similar to runCmd; with additional expect style output matching ability.
2743
2744        Ask the command interpreter to handle the command and then check its
2745        return status.  The 'msg' parameter specifies an informational assert
2746        message.  We expect the output from running the command to start with
2747        'startstr', matches the substrings contained in 'substrs', and regexp
2748        matches the patterns contained in 'patterns'.
2749
2750        If the keyword argument error is set to True, it signifies that the API
2751        client is expecting the command to fail.  In this case, the error stream
2752        from running the command is retrieved and compared against the golden
2753        input, instead.
2754
2755        If the keyword argument matching is set to False, it signifies that the API
2756        client is expecting the output of the command not to match the golden
2757        input.
2758
2759        Finally, the required argument 'str' represents the lldb command to be
2760        sent to the command interpreter.  In case the keyword argument 'exe' is
2761        set to False, the 'str' is treated as a string to be matched/not-matched
2762        against the golden input.
2763        """
2764        trace = (True if traceAlways else trace)
2765
2766        if exe:
2767            # First run the command.  If we are expecting error, set check=False.
2768            # Pass the assert message along since it provides more semantic info.
2769            self.runCmd(str, msg=msg, trace = (True if trace else False), check = not error, inHistory=inHistory)
2770
2771            # Then compare the output against expected strings.
2772            output = self.res.GetError() if error else self.res.GetOutput()
2773
2774            # If error is True, the API client expects the command to fail!
2775            if error:
2776                self.assertFalse(self.res.Succeeded(),
2777                                 "Command '" + str + "' is expected to fail!")
2778        else:
2779            # No execution required, just compare str against the golden input.
2780            if isinstance(str,lldb.SBCommandReturnObject):
2781                output = str.GetOutput()
2782            else:
2783                output = str
2784            with recording(self, trace) as sbuf:
2785                print("looking at:", output, file=sbuf)
2786
2787        # The heading says either "Expecting" or "Not expecting".
2788        heading = "Expecting" if matching else "Not expecting"
2789
2790        # Start from the startstr, if specified.
2791        # If there's no startstr, set the initial state appropriately.
2792        matched = output.startswith(startstr) if startstr else (True if matching else False)
2793
2794        if startstr:
2795            with recording(self, trace) as sbuf:
2796                print("%s start string: %s" % (heading, startstr), file=sbuf)
2797                print("Matched" if matched else "Not matched", file=sbuf)
2798
2799        # Look for endstr, if specified.
2800        keepgoing = matched if matching else not matched
2801        if endstr:
2802            matched = output.endswith(endstr)
2803            with recording(self, trace) as sbuf:
2804                print("%s end string: %s" % (heading, endstr), file=sbuf)
2805                print("Matched" if matched else "Not matched", file=sbuf)
2806
2807        # Look for sub strings, if specified.
2808        keepgoing = matched if matching else not matched
2809        if substrs and keepgoing:
2810            for str in substrs:
2811                matched = output.find(str) != -1
2812                with recording(self, trace) as sbuf:
2813                    print("%s sub string: %s" % (heading, str), file=sbuf)
2814                    print("Matched" if matched else "Not matched", file=sbuf)
2815                keepgoing = matched if matching else not matched
2816                if not keepgoing:
2817                    break
2818
2819        # Search for regular expression patterns, if specified.
2820        keepgoing = matched if matching else not matched
2821        if patterns and keepgoing:
2822            for pattern in patterns:
2823                # Match Objects always have a boolean value of True.
2824                matched = bool(re.search(pattern, output))
2825                with recording(self, trace) as sbuf:
2826                    print("%s pattern: %s" % (heading, pattern), file=sbuf)
2827                    print("Matched" if matched else "Not matched", file=sbuf)
2828                keepgoing = matched if matching else not matched
2829                if not keepgoing:
2830                    break
2831
2832        self.assertTrue(matched if matching else not matched,
2833                        msg if msg else EXP_MSG(str, exe))
2834
2835    def invoke(self, obj, name, trace=False):
2836        """Use reflection to call a method dynamically with no argument."""
2837        trace = (True if traceAlways else trace)
2838
2839        method = getattr(obj, name)
2840        import inspect
2841        self.assertTrue(inspect.ismethod(method),
2842                        name + "is a method name of object: " + str(obj))
2843        result = method()
2844        with recording(self, trace) as sbuf:
2845            print(str(method) + ":",  result, file=sbuf)
2846        return result
2847
2848    def build(self, architecture=None, compiler=None, dictionary=None, clean=True):
2849        """Platform specific way to build the default binaries."""
2850        if lldb.skip_build_and_cleanup:
2851            return
2852        module = builder_module()
2853        if target_is_android():
2854            dictionary = append_android_envs(dictionary)
2855        if self.debug_info is None:
2856            return self.buildDefault(architecture, compiler, dictionary, clean)
2857        elif self.debug_info == "dsym":
2858            return self.buildDsym(architecture, compiler, dictionary, clean)
2859        elif self.debug_info == "dwarf":
2860            return self.buildDwarf(architecture, compiler, dictionary, clean)
2861        elif self.debug_info == "dwo":
2862            return self.buildDwo(architecture, compiler, dictionary, clean)
2863        else:
2864            self.fail("Can't build for debug info: %s" % self.debug_info)
2865
2866    # =================================================
2867    # Misc. helper methods for debugging test execution
2868    # =================================================
2869
2870    def DebugSBValue(self, val):
2871        """Debug print a SBValue object, if traceAlways is True."""
2872        from .lldbutil import value_type_to_str
2873
2874        if not traceAlways:
2875            return
2876
2877        err = sys.stderr
2878        err.write(val.GetName() + ":\n")
2879        err.write('\t' + "TypeName         -> " + val.GetTypeName()            + '\n')
2880        err.write('\t' + "ByteSize         -> " + str(val.GetByteSize())       + '\n')
2881        err.write('\t' + "NumChildren      -> " + str(val.GetNumChildren())    + '\n')
2882        err.write('\t' + "Value            -> " + str(val.GetValue())          + '\n')
2883        err.write('\t' + "ValueAsUnsigned  -> " + str(val.GetValueAsUnsigned())+ '\n')
2884        err.write('\t' + "ValueType        -> " + value_type_to_str(val.GetValueType()) + '\n')
2885        err.write('\t' + "Summary          -> " + str(val.GetSummary())        + '\n')
2886        err.write('\t' + "IsPointerType    -> " + str(val.TypeIsPointerType()) + '\n')
2887        err.write('\t' + "Location         -> " + val.GetLocation()            + '\n')
2888
2889    def DebugSBType(self, type):
2890        """Debug print a SBType object, if traceAlways is True."""
2891        if not traceAlways:
2892            return
2893
2894        err = sys.stderr
2895        err.write(type.GetName() + ":\n")
2896        err.write('\t' + "ByteSize        -> " + str(type.GetByteSize())     + '\n')
2897        err.write('\t' + "IsPointerType   -> " + str(type.IsPointerType())   + '\n')
2898        err.write('\t' + "IsReferenceType -> " + str(type.IsReferenceType()) + '\n')
2899
2900    def DebugPExpect(self, child):
2901        """Debug the spwaned pexpect object."""
2902        if not traceAlways:
2903            return
2904
2905        print(child)
2906
2907    @classmethod
2908    def RemoveTempFile(cls, file):
2909        if os.path.exists(file):
2910            os.remove(file)
2911