1from __future__ import absolute_import
2
3# System modules
4from distutils.version import LooseVersion
5from functools import wraps
6import os
7import platform
8import re
9import sys
10import tempfile
11import subprocess
12
13# Third-party modules
14import six
15import unittest2
16
17# LLDB modules
18import lldb
19from . import configuration
20from . import test_categories
21from . import lldbtest_config
22from lldbsuite.test_event.event_builder import EventBuilder
23from lldbsuite.support import funcutils
24from lldbsuite.test import lldbplatform
25from lldbsuite.test import lldbplatformutil
26
27
28class DecorateMode:
29    Skip, Xfail = range(2)
30
31
32# You can use no_match to reverse the test of the conditional that is used to match keyword
33# arguments in the skip / xfail decorators.  If oslist=["windows", "linux"] skips windows
34# and linux, oslist=no_match(["windows", "linux"]) skips *unless* windows
35# or linux.
36class no_match:
37
38    def __init__(self, item):
39        self.item = item
40
41
42def _check_expected_version(comparison, expected, actual):
43    def fn_leq(x, y): return x <= y
44
45    def fn_less(x, y): return x < y
46
47    def fn_geq(x, y): return x >= y
48
49    def fn_greater(x, y): return x > y
50
51    def fn_eq(x, y): return x == y
52
53    def fn_neq(x, y): return x != y
54
55    op_lookup = {
56        "==": fn_eq,
57        "=": fn_eq,
58        "!=": fn_neq,
59        "<>": fn_neq,
60        ">": fn_greater,
61        "<": fn_less,
62        ">=": fn_geq,
63        "<=": fn_leq
64    }
65    expected_str = '.'.join([str(x) for x in expected])
66    actual_str = '.'.join([str(x) for x in actual])
67
68    return op_lookup[comparison](
69        LooseVersion(actual_str),
70        LooseVersion(expected_str))
71
72
73_re_pattern_type = type(re.compile(''))
74def _match_decorator_property(expected, actual):
75    if actual is None or expected is None:
76        return True
77
78    if isinstance(expected, no_match):
79        return not _match_decorator_property(expected.item, actual)
80    elif isinstance(expected, (_re_pattern_type,) + six.string_types):
81        return re.search(expected, actual) is not None
82    elif hasattr(expected, "__iter__"):
83        return any([x is not None and _match_decorator_property(x, actual)
84                    for x in expected])
85    else:
86        return expected == actual
87
88
89def expectedFailure(expected_fn, bugnumber=None):
90    def expectedFailure_impl(func):
91        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
92            raise Exception(
93                "Decorator can only be used to decorate a test method")
94
95        @wraps(func)
96        def wrapper(*args, **kwargs):
97            self = args[0]
98            if funcutils.requires_self(expected_fn):
99                xfail_reason = expected_fn(self)
100            else:
101                xfail_reason = expected_fn()
102            if xfail_reason is not None:
103                if configuration.results_formatter_object is not None:
104                    # Mark this test as expected to fail.
105                    configuration.results_formatter_object.handle_event(
106                        EventBuilder.event_for_mark_test_expected_failure(self))
107                xfail_func = unittest2.expectedFailure(func)
108                xfail_func(*args, **kwargs)
109            else:
110                func(*args, **kwargs)
111        return wrapper
112    # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
113    # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])).  When called
114    # the first way, the first argument will be the actual function because decorators are
115    # weird like that.  So this is basically a check that says "which syntax was the original
116    # function decorated with?"
117    if six.callable(bugnumber):
118        return expectedFailure_impl(bugnumber)
119    else:
120        return expectedFailure_impl
121
122
123def skipTestIfFn(expected_fn, bugnumber=None):
124    def skipTestIfFn_impl(func):
125        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
126            raise Exception(
127                "@skipTestIfFn can only be used to decorate a test method")
128
129        @wraps(func)
130        def wrapper(*args, **kwargs):
131            self = args[0]
132            if funcutils.requires_self(expected_fn):
133                reason = expected_fn(self)
134            else:
135                reason = expected_fn()
136
137            if reason is not None:
138                self.skipTest(reason)
139            else:
140                func(*args, **kwargs)
141        return wrapper
142
143    # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
144    # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])).  When called
145    # the first way, the first argument will be the actual function because decorators are
146    # weird like that.  So this is basically a check that says "how was the
147    # decorator used"
148    if six.callable(bugnumber):
149        return skipTestIfFn_impl(bugnumber)
150    else:
151        return skipTestIfFn_impl
152
153
154def _decorateTest(mode,
155                  bugnumber=None, oslist=None, hostoslist=None,
156                  compiler=None, compiler_version=None,
157                  archs=None, triple=None,
158                  debug_info=None,
159                  swig_version=None, py_version=None,
160                  macos_version=None,
161                  remote=None, dwarf_version=None,
162                  setting=None):
163    def fn(self):
164        skip_for_os = _match_decorator_property(
165            lldbplatform.translate(oslist), self.getPlatform())
166        skip_for_hostos = _match_decorator_property(
167            lldbplatform.translate(hostoslist),
168            lldbplatformutil.getHostPlatform())
169        skip_for_compiler = _match_decorator_property(
170            compiler, self.getCompiler()) and self.expectedCompilerVersion(compiler_version)
171        skip_for_arch = _match_decorator_property(
172            archs, self.getArchitecture())
173        skip_for_debug_info = _match_decorator_property(
174            debug_info, self.getDebugInfo())
175        skip_for_triple = _match_decorator_property(
176            triple, lldb.selected_platform.GetTriple())
177        skip_for_remote = _match_decorator_property(
178            remote, lldb.remote_platform is not None)
179
180        skip_for_swig_version = (
181            swig_version is None) or (
182            not hasattr(
183                lldb,
184                'swig_version')) or (
185                _check_expected_version(
186                    swig_version[0],
187                    swig_version[1],
188                    lldb.swig_version))
189        skip_for_py_version = (
190            py_version is None) or _check_expected_version(
191            py_version[0], py_version[1], sys.version_info)
192        skip_for_macos_version = (macos_version is None) or (
193            (platform.mac_ver()[0] != "") and (_check_expected_version(
194                macos_version[0],
195                macos_version[1],
196                platform.mac_ver()[0])))
197        skip_for_dwarf_version = (dwarf_version is None) or (
198            _check_expected_version(dwarf_version[0], dwarf_version[1],
199                                    self.getDwarfVersion()))
200        skip_for_setting = (setting is None) or (
201            setting in configuration.settings)
202
203        # For the test to be skipped, all specified (e.g. not None) parameters must be True.
204        # An unspecified parameter means "any", so those are marked skip by default.  And we skip
205        # the final test if all conditions are True.
206        conditions = [(oslist, skip_for_os, "target o/s"),
207                      (hostoslist, skip_for_hostos, "host o/s"),
208                      (compiler, skip_for_compiler, "compiler or version"),
209                      (archs, skip_for_arch, "architecture"),
210                      (debug_info, skip_for_debug_info, "debug info format"),
211                      (triple, skip_for_triple, "target triple"),
212                      (swig_version, skip_for_swig_version, "swig version"),
213                      (py_version, skip_for_py_version, "python version"),
214                      (macos_version, skip_for_macos_version, "macOS version"),
215                      (remote, skip_for_remote, "platform locality (remote/local)"),
216                      (dwarf_version, skip_for_dwarf_version, "dwarf version"),
217                      (setting, skip_for_setting, "setting")]
218        reasons = []
219        final_skip_result = True
220        for this_condition in conditions:
221            final_skip_result = final_skip_result and this_condition[1]
222            if this_condition[0] is not None and this_condition[1]:
223                reasons.append(this_condition[2])
224        reason_str = None
225        if final_skip_result:
226            mode_str = {
227                DecorateMode.Skip: "skipping",
228                DecorateMode.Xfail: "xfailing"}[mode]
229            if len(reasons) > 0:
230                reason_str = ",".join(reasons)
231                reason_str = "{} due to the following parameter(s): {}".format(
232                    mode_str, reason_str)
233            else:
234                reason_str = "{} unconditionally"
235            if bugnumber is not None and not six.callable(bugnumber):
236                reason_str = reason_str + " [" + str(bugnumber) + "]"
237        return reason_str
238
239    if mode == DecorateMode.Skip:
240        return skipTestIfFn(fn, bugnumber)
241    elif mode == DecorateMode.Xfail:
242        return expectedFailure(fn, bugnumber)
243    else:
244        return None
245
246# provide a function to xfail on defined oslist, compiler version, and archs
247# if none is specified for any argument, that argument won't be checked and thus means for all
248# for example,
249# @expectedFailureAll, xfail for all platform/compiler/arch,
250# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture
251# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386
252
253
254def expectedFailureAll(bugnumber=None,
255                       oslist=None, hostoslist=None,
256                       compiler=None, compiler_version=None,
257                       archs=None, triple=None,
258                       debug_info=None,
259                       swig_version=None, py_version=None,
260                       macos_version=None,
261                       remote=None, dwarf_version=None,
262                       setting=None):
263    return _decorateTest(DecorateMode.Xfail,
264                         bugnumber=bugnumber,
265                         oslist=oslist, hostoslist=hostoslist,
266                         compiler=compiler, compiler_version=compiler_version,
267                         archs=archs, triple=triple,
268                         debug_info=debug_info,
269                         swig_version=swig_version, py_version=py_version,
270                         macos_version=None,
271                         remote=remote,dwarf_version=dwarf_version,
272                         setting=setting)
273
274
275# provide a function to skip on defined oslist, compiler version, and archs
276# if none is specified for any argument, that argument won't be checked and thus means for all
277# for example,
278# @skipIf, skip for all platform/compiler/arch,
279# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture
280# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386
281def skipIf(bugnumber=None,
282           oslist=None, hostoslist=None,
283           compiler=None, compiler_version=None,
284           archs=None, triple=None,
285           debug_info=None,
286           swig_version=None, py_version=None,
287           macos_version=None,
288           remote=None, dwarf_version=None,
289           setting=None):
290    return _decorateTest(DecorateMode.Skip,
291                         bugnumber=bugnumber,
292                         oslist=oslist, hostoslist=hostoslist,
293                         compiler=compiler, compiler_version=compiler_version,
294                         archs=archs, triple=triple,
295                         debug_info=debug_info,
296                         swig_version=swig_version, py_version=py_version,
297                         macos_version=macos_version,
298                         remote=remote, dwarf_version=dwarf_version,
299                         setting=setting)
300
301
302def _skip_for_android(reason, api_levels, archs):
303    def impl(obj):
304        result = lldbplatformutil.match_android_device(
305            obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels)
306        return reason if result else None
307    return impl
308
309
310def add_test_categories(cat):
311    """Add test categories to a TestCase method"""
312    cat = test_categories.validate(cat, True)
313
314    def impl(func):
315        if isinstance(func, type) and issubclass(func, unittest2.TestCase):
316            raise Exception(
317                "@add_test_categories can only be used to decorate a test method")
318        try:
319            if hasattr(func, "categories"):
320                cat.extend(func.categories)
321            setattr(func, "categories", cat)
322        except AttributeError:
323            raise Exception('Cannot assign categories to inline tests.')
324
325        return func
326
327    return impl
328
329
330def benchmarks_test(func):
331    """Decorate the item as a benchmarks test."""
332    def should_skip_benchmarks_test():
333        return "benchmarks test"
334
335    # Mark this function as such to separate them from the regular tests.
336    result = skipTestIfFn(should_skip_benchmarks_test)(func)
337    result.__benchmarks_test__ = True
338    return result
339
340
341def no_debug_info_test(func):
342    """Decorate the item as a test what don't use any debug info. If this annotation is specified
343       then the test runner won't generate a separate test for each debug info format. """
344    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
345        raise Exception(
346            "@no_debug_info_test can only be used to decorate a test method")
347
348    @wraps(func)
349    def wrapper(self, *args, **kwargs):
350        return func(self, *args, **kwargs)
351
352    # Mark this function as such to separate them from the regular tests.
353    wrapper.__no_debug_info_test__ = True
354    return wrapper
355
356def apple_simulator_test(platform):
357    """
358    Decorate the test as a test requiring a simulator for a specific platform.
359
360    Consider that a simulator is available if you have the corresponding SDK installed.
361    The SDK identifiers for simulators are iphonesimulator, appletvsimulator, watchsimulator
362    """
363    def should_skip_simulator_test():
364        if lldbplatformutil.getHostPlatform() != 'darwin':
365            return "simulator tests are run only on darwin hosts"
366        try:
367            DEVNULL = open(os.devnull, 'w')
368            output = subprocess.check_output(["xcodebuild", "-showsdks"], stderr=DEVNULL).decode("utf-8")
369            if re.search('%ssimulator' % platform, output):
370                return None
371            else:
372                return "%s simulator is not supported on this system." % platform
373        except subprocess.CalledProcessError:
374            return "Simulators are unsupported on this system (xcodebuild failed)"
375
376    return skipTestIfFn(should_skip_simulator_test)
377
378
379def debugserver_test(func):
380    """Decorate the item as a debugserver test."""
381    def should_skip_debugserver_test():
382        return "debugserver tests" if configuration.dont_do_debugserver_test else None
383    return skipTestIfFn(should_skip_debugserver_test)(func)
384
385
386def llgs_test(func):
387    """Decorate the item as a lldb-server test."""
388    def should_skip_llgs_tests():
389        return "llgs tests" if configuration.dont_do_llgs_test else None
390    return skipTestIfFn(should_skip_llgs_tests)(func)
391
392
393def not_remote_testsuite_ready(func):
394    """Decorate the item as a test which is not ready yet for remote testsuite."""
395    def is_remote():
396        return "Not ready for remote testsuite" if lldb.remote_platform else None
397    return skipTestIfFn(is_remote)(func)
398
399
400def expectedFailureOS(
401        oslist,
402        bugnumber=None,
403        compilers=None,
404        debug_info=None,
405        archs=None):
406    return expectedFailureAll(
407        oslist=oslist,
408        bugnumber=bugnumber,
409        compiler=compilers,
410        archs=archs,
411        debug_info=debug_info)
412
413
414def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None, archs=None):
415    # For legacy reasons, we support both "darwin" and "macosx" as OS X
416    # triples.
417    return expectedFailureOS(
418        lldbplatform.darwin_all,
419        bugnumber,
420        compilers,
421        debug_info=debug_info,
422        archs=archs)
423
424
425def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None):
426    """ Mark a test as xfail for Android.
427
428    Arguments:
429        bugnumber - The LLVM pr associated with the problem.
430        api_levels - A sequence of numbers specifying the Android API levels
431            for which a test is expected to fail. None means all API level.
432        arch - A sequence of architecture names specifying the architectures
433            for which a test is expected to fail. None means all architectures.
434    """
435    return expectedFailure(
436        _skip_for_android(
437            "xfailing on android",
438            api_levels,
439            archs),
440        bugnumber)
441
442
443def expectedFailureNetBSD(bugnumber=None):
444    return expectedFailureOS(
445        ['netbsd'],
446        bugnumber)
447
448# Flakey tests get two chances to run. If they fail the first time round, the result formatter
449# makes sure it is run one more time.
450
451
452def expectedFlakey(expected_fn, bugnumber=None):
453    def expectedFailure_impl(func):
454        @wraps(func)
455        def wrapper(*args, **kwargs):
456            self = args[0]
457            if expected_fn(self):
458                # Send event marking test as explicitly eligible for rerunning.
459                if configuration.results_formatter_object is not None:
460                    # Mark this test as rerunnable.
461                    configuration.results_formatter_object.handle_event(
462                        EventBuilder.event_for_mark_test_rerun_eligible(self))
463            func(*args, **kwargs)
464        return wrapper
465    # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)
466    # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])).  When called
467    # the first way, the first argument will be the actual function because decorators are
468    # weird like that.  So this is basically a check that says "which syntax was the original
469    # function decorated with?"
470    if six.callable(bugnumber):
471        return expectedFailure_impl(bugnumber)
472    else:
473        return expectedFailure_impl
474
475
476def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):
477    def fn(self):
478        return (self.getPlatform() in oslist and
479                self.expectedCompiler(compilers))
480    return expectedFlakey(fn, bugnumber)
481
482
483def expectedFlakeyDarwin(bugnumber=None, compilers=None):
484    # For legacy reasons, we support both "darwin" and "macosx" as OS X
485    # triples.
486    return expectedFlakeyOS(
487        lldbplatformutil.getDarwinOSTriples(),
488        bugnumber,
489        compilers)
490
491
492def expectedFlakeyFreeBSD(bugnumber=None, compilers=None):
493    return expectedFlakeyOS(['freebsd'], bugnumber, compilers)
494
495
496def expectedFlakeyLinux(bugnumber=None, compilers=None):
497    return expectedFlakeyOS(['linux'], bugnumber, compilers)
498
499
500def expectedFlakeyNetBSD(bugnumber=None, compilers=None):
501    return expectedFlakeyOS(['netbsd'], bugnumber, compilers)
502
503
504def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None):
505    return expectedFlakey(
506        _skip_for_android(
507            "flakey on android",
508            api_levels,
509            archs),
510        bugnumber)
511
512def skipIfOutOfTreeDebugserver(func):
513    """Decorate the item to skip tests if using an out-of-tree debugserver."""
514    def is_out_of_tree_debugserver():
515        return "out-of-tree debugserver" if lldbtest_config.out_of_tree_debugserver else None
516    return skipTestIfFn(is_out_of_tree_debugserver)(func)
517
518def skipIfRemote(func):
519    """Decorate the item to skip tests if testing remotely."""
520    def is_remote():
521        return "skip on remote platform" if lldb.remote_platform else None
522    return skipTestIfFn(is_remote)(func)
523
524
525def skipIfNoSBHeaders(func):
526    """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers."""
527    def are_sb_headers_missing():
528        if lldb.remote_platform:
529            return "skip because SBHeaders tests make no sense remotely"
530
531        if lldbplatformutil.getHostPlatform() == 'darwin':
532            header = os.path.join(
533                os.environ["LLDB_LIB_DIR"],
534                'LLDB.framework',
535                'Versions',
536                'Current',
537                'Headers',
538                'LLDB.h')
539            if os.path.exists(header):
540                return None
541
542        header = os.path.join(
543            os.environ["LLDB_SRC"],
544            "include",
545            "lldb",
546            "API",
547            "LLDB.h")
548        if not os.path.exists(header):
549            return "skip because LLDB.h header not found"
550        return None
551
552    return skipTestIfFn(are_sb_headers_missing)(func)
553
554
555def skipIfRosetta(func, bugnumber=None):
556    """Skip a test when running the testsuite on macOS under the Rosetta translation layer."""
557    def is_running_rosetta(self):
558        if not lldbplatformutil.getPlatform() in ['darwin', 'macosx']:
559            return False
560        return platform.uname()[5] == "arm" and self.getArchitecture() == "x86_64"
561    return skipTestIfFn(is_running_rosetta, bugnumber)(func)
562
563def skipIfiOSSimulator(func):
564    """Decorate the item to skip tests that should be skipped on the iOS Simulator."""
565    def is_ios_simulator():
566        return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None
567    return skipTestIfFn(is_ios_simulator)(func)
568
569def skipIfiOS(func):
570    return skipIfPlatform(["ios"])(func)
571
572def skipIftvOS(func):
573    return skipIfPlatform(["tvos"])(func)
574
575def skipIfwatchOS(func):
576    return skipIfPlatform(["watchos"])(func)
577
578def skipIfbridgeOS(func):
579    return skipIfPlatform(["bridgeos"])(func)
580
581def skipIfDarwinEmbedded(func):
582    """Decorate the item to skip tests that should be skipped on Darwin armv7/arm64 targets."""
583    return skipIfPlatform(
584        lldbplatform.translate(
585            lldbplatform.darwin_embedded))(func)
586
587def skipIfFreeBSD(func):
588    """Decorate the item to skip tests that should be skipped on FreeBSD."""
589    return skipIfPlatform(["freebsd"])(func)
590
591
592def skipIfNetBSD(func):
593    """Decorate the item to skip tests that should be skipped on NetBSD."""
594    return skipIfPlatform(["netbsd"])(func)
595
596
597def skipIfDarwin(func):
598    """Decorate the item to skip tests that should be skipped on Darwin."""
599    return skipIfPlatform(
600        lldbplatform.translate(
601            lldbplatform.darwin_all))(func)
602
603
604def skipIfLinux(func):
605    """Decorate the item to skip tests that should be skipped on Linux."""
606    return skipIfPlatform(["linux"])(func)
607
608
609def skipIfWindows(func):
610    """Decorate the item to skip tests that should be skipped on Windows."""
611    return skipIfPlatform(["windows"])(func)
612
613def skipUnlessWindows(func):
614    """Decorate the item to skip tests that should be skipped on any non-Windows platform."""
615    return skipUnlessPlatform(["windows"])(func)
616
617
618def skipUnlessDarwin(func):
619    """Decorate the item to skip tests that should be skipped on any non Darwin platform."""
620    return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func)
621
622def skipUnlessTargetAndroid(func):
623    return unittest2.skipUnless(lldbplatformutil.target_is_android(),
624                                "requires target to be Android")(func)
625
626
627def skipIfHostIncompatibleWithRemote(func):
628    """Decorate the item to skip tests if binaries built on this host are incompatible."""
629
630    def is_host_incompatible_with_remote(self):
631        host_arch = self.getLldbArchitecture()
632        host_platform = lldbplatformutil.getHostPlatform()
633        target_arch = self.getArchitecture()
634        target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform()
635        if not (target_arch == 'x86_64' and host_arch ==
636                'i386') and host_arch != target_arch:
637            return "skipping because target %s is not compatible with host architecture %s" % (
638                target_arch, host_arch)
639        if target_platform != host_platform:
640            return "skipping because target is %s but host is %s" % (
641                target_platform, host_platform)
642        if lldbplatformutil.match_android_device(target_arch):
643            return "skipping because target is android"
644        return None
645    return skipTestIfFn(is_host_incompatible_with_remote)(func)
646
647
648def skipIfPlatform(oslist):
649    """Decorate the item to skip tests if running on one of the listed platforms."""
650    # This decorator cannot be ported to `skipIf` yet because it is used on entire
651    # classes, which `skipIf` explicitly forbids.
652    return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist,
653                            "skip on %s" % (", ".join(oslist)))
654
655
656def skipUnlessPlatform(oslist):
657    """Decorate the item to skip tests unless running on one of the listed platforms."""
658    # This decorator cannot be ported to `skipIf` yet because it is used on entire
659    # classes, which `skipIf` explicitly forbids.
660    return unittest2.skipUnless(lldbplatformutil.getPlatform() in oslist,
661                                "requires one of %s" % (", ".join(oslist)))
662
663def skipUnlessArch(arch):
664    """Decorate the item to skip tests unless running on the specified architecture."""
665
666    def arch_doesnt_match(self):
667        target_arch = self.getArchitecture()
668        if arch != target_arch:
669            return "Test only runs on " + arch + ", but target arch is " + target_arch
670        return None
671
672    return skipTestIfFn(arch_doesnt_match)
673
674def skipIfTargetAndroid(bugnumber=None, api_levels=None, archs=None):
675    """Decorator to skip tests when the target is Android.
676
677    Arguments:
678        api_levels - The API levels for which the test should be skipped. If
679            it is None, then the test will be skipped for all API levels.
680        arch - A sequence of architecture names specifying the architectures
681            for which a test is skipped. None means all architectures.
682    """
683    return skipTestIfFn(
684        _skip_for_android(
685            "skipping for android",
686            api_levels,
687            archs),
688        bugnumber)
689
690def skipUnlessSupportedTypeAttribute(attr):
691    """Decorate the item to skip test unless Clang supports type __attribute__(attr)."""
692    def compiler_doesnt_support_struct_attribute(self):
693        compiler_path = self.getCompiler()
694        f = tempfile.NamedTemporaryFile()
695        cmd = [self.getCompiler(), "-x", "c++", "-c", "-o", f.name, "-"]
696        p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
697        stdout, stderr = p.communicate('struct __attribute__((%s)) Test {};'%attr)
698        if attr in stderr:
699            return "Compiler does not support attribute %s"%(attr)
700        return None
701    return skipTestIfFn(compiler_doesnt_support_struct_attribute)
702
703def skipUnlessHasCallSiteInfo(func):
704    """Decorate the function to skip testing unless call site info from clang is available."""
705
706    def is_compiler_clang_with_call_site_info(self):
707        compiler_path = self.getCompiler()
708        compiler = os.path.basename(compiler_path)
709        if not compiler.startswith("clang"):
710            return "Test requires clang as compiler"
711
712        f = tempfile.NamedTemporaryFile()
713        cmd = "echo 'int main() {}' | " \
714              "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.name)
715        if os.popen(cmd).close() is not None:
716            return "Compiler can't compile with call site info enabled"
717
718        with open(f.name, 'r') as ir_output_file:
719            buf = ir_output_file.read()
720
721        if 'DIFlagAllCallsDescribed' not in buf:
722            return "Compiler did not introduce DIFlagAllCallsDescribed IR flag"
723
724        return None
725    return skipTestIfFn(is_compiler_clang_with_call_site_info)(func)
726
727def skipUnlessThreadSanitizer(func):
728    """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
729
730    def is_compiler_clang_with_thread_sanitizer(self):
731        if is_running_under_asan():
732            return "Thread sanitizer tests are disabled when runing under ASAN"
733
734        compiler_path = self.getCompiler()
735        compiler = os.path.basename(compiler_path)
736        if not compiler.startswith("clang"):
737            return "Test requires clang as compiler"
738        if lldbplatformutil.getPlatform() == 'windows':
739            return "TSAN tests not compatible with 'windows'"
740        # rdar://28659145 - TSAN tests don't look like they're supported on i386
741        if self.getArchitecture() == 'i386' and platform.system() == 'Darwin':
742            return "TSAN tests not compatible with i386 targets"
743        f = tempfile.NamedTemporaryFile()
744        cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name)
745        if os.popen(cmd).close() is not None:
746            return None  # The compiler cannot compile at all, let's *not* skip the test
747        cmd = "echo 'int main() {}' | %s -fsanitize=thread -x c -o %s -" % (compiler_path, f.name)
748        if os.popen(cmd).close() is not None:
749            return "Compiler cannot compile with -fsanitize=thread"
750        return None
751    return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func)
752
753def skipUnlessUndefinedBehaviorSanitizer(func):
754    """Decorate the item to skip test unless -fsanitize=undefined is supported."""
755
756    def is_compiler_clang_with_ubsan(self):
757        if is_running_under_asan():
758            return "Undefined behavior sanitizer tests are disabled when runing under ASAN"
759
760        # Write out a temp file which exhibits UB.
761        inputf = tempfile.NamedTemporaryFile(suffix='.c', mode='w')
762        inputf.write('int main() { int x = 0; return x / x; }\n')
763        inputf.flush()
764
765        # We need to write out the object into a named temp file for inspection.
766        outputf = tempfile.NamedTemporaryFile()
767
768        # Try to compile with ubsan turned on.
769        cmd = '%s -fsanitize=undefined %s -o %s' % (self.getCompiler(), inputf.name, outputf.name)
770        if os.popen(cmd).close() is not None:
771            return "Compiler cannot compile with -fsanitize=undefined"
772
773        # Check that we actually see ubsan instrumentation in the binary.
774        cmd = 'nm %s' % outputf.name
775        with os.popen(cmd) as nm_output:
776            if '___ubsan_handle_divrem_overflow' not in nm_output.read():
777                return "Division by zero instrumentation is missing"
778
779        # Find the ubsan dylib.
780        # FIXME: This check should go away once compiler-rt gains support for __ubsan_on_report.
781        cmd = '%s -fsanitize=undefined -x c - -o - -### 2>&1' % self.getCompiler()
782        with os.popen(cmd) as cc_output:
783            driver_jobs = cc_output.read()
784            m = re.search(r'"([^"]+libclang_rt.ubsan_osx_dynamic.dylib)"', driver_jobs)
785            if not m:
786                return "Could not find the ubsan dylib used by the driver"
787            ubsan_dylib = m.group(1)
788
789        # Check that the ubsan dylib has special monitor hooks.
790        cmd = 'nm -gU %s' % ubsan_dylib
791        with os.popen(cmd) as nm_output:
792            syms = nm_output.read()
793            if '___ubsan_on_report' not in syms:
794                return "Missing ___ubsan_on_report"
795            if '___ubsan_get_current_report_data' not in syms:
796                return "Missing ___ubsan_get_current_report_data"
797
798        # OK, this dylib + compiler works for us.
799        return None
800
801    return skipTestIfFn(is_compiler_clang_with_ubsan)(func)
802
803def is_running_under_asan():
804    if ('ASAN_OPTIONS' in os.environ):
805        return "ASAN unsupported"
806    return None
807
808def skipUnlessAddressSanitizer(func):
809    """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
810
811    def is_compiler_with_address_sanitizer(self):
812        # Also don't run tests that use address sanitizer inside an
813        # address-sanitized LLDB. The tests don't support that
814        # configuration.
815        if is_running_under_asan():
816            return "Address sanitizer tests are disabled when runing under ASAN"
817
818        compiler_path = self.getCompiler()
819        compiler = os.path.basename(compiler_path)
820        f = tempfile.NamedTemporaryFile()
821        if lldbplatformutil.getPlatform() == 'windows':
822            return "ASAN tests not compatible with 'windows'"
823        cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name)
824        if os.popen(cmd).close() is not None:
825            return None  # The compiler cannot compile at all, let's *not* skip the test
826        cmd = "echo 'int main() {}' | %s -fsanitize=address -x c -o %s -" % (compiler_path, f.name)
827        if os.popen(cmd).close() is not None:
828            return "Compiler cannot compile with -fsanitize=address"
829        return None
830    return skipTestIfFn(is_compiler_with_address_sanitizer)(func)
831
832def skipIfAsan(func):
833    """Skip this test if the environment is set up to run LLDB *itself* under ASAN."""
834    return skipTestIfFn(is_running_under_asan)(func)
835
836def _get_bool_config_skip_if_decorator(key):
837    config = lldb.SBDebugger.GetBuildConfiguration()
838    value_node = config.GetValueForKey(key)
839    fail_value = True # More likely to notice if something goes wrong
840    have = value_node.GetValueForKey("value").GetBooleanValue(fail_value)
841    return unittest2.skipIf(not have, "requires " + key)
842
843def skipIfCursesSupportMissing(func):
844    return _get_bool_config_skip_if_decorator("curses")(func)
845
846def skipIfXmlSupportMissing(func):
847    return _get_bool_config_skip_if_decorator("xml")(func)
848
849def skipIfEditlineSupportMissing(func):
850    return _get_bool_config_skip_if_decorator("editline")(func)
851
852def skipIfLLVMTargetMissing(target):
853    config = lldb.SBDebugger.GetBuildConfiguration()
854    targets = config.GetValueForKey("targets").GetValueForKey("value")
855    found = False
856    for i in range(targets.GetSize()):
857        if targets.GetItemAtIndex(i).GetStringValue(99) == target:
858            found = True
859            break
860
861    return unittest2.skipIf(not found, "requires " + target)
862
863# Call sysctl on darwin to see if a specified hardware feature is available on this machine.
864def skipUnlessFeature(feature):
865    def is_feature_enabled(self):
866        if platform.system() == 'Darwin':
867            try:
868                DEVNULL = open(os.devnull, 'w')
869                output = subprocess.check_output(["/usr/sbin/sysctl", feature], stderr=DEVNULL).decode("utf-8")
870                # If 'feature: 1' was output, then this feature is available and
871                # the test should not be skipped.
872                if re.match('%s: 1\s*' % feature, output):
873                    return None
874                else:
875                    return "%s is not supported on this system." % feature
876            except subprocess.CalledProcessError:
877                return "%s is not supported on this system." % feature
878    return skipTestIfFn(is_feature_enabled)
879
880def skipIfReproducer(func):
881    """Skip this test if the environment is set up to run LLDB with reproducers."""
882    def is_reproducer():
883        if configuration.capture_path or configuration.replay_path:
884            return "reproducers unsupported"
885        return None
886    return skipTestIfFn(is_reproducer)(func)
887