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