brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.1 KiB · 7311b17 Raw
1190 lines · python
1# System modules2 3# allow the use of the `list[str]` type hint in Python 3.84from __future__ import annotations5 6from functools import wraps7from packaging import version8import ctypes9import locale10import os11import platform12import re13import sys14import tempfile15import subprocess16import json17 18# Third-party modules19import unittest20 21# LLDB modules22import lldb23from . import configuration24from . import test_categories25from . import lldbtest_config26from lldbsuite.support import funcutils27from lldbsuite.support import temp_file28from lldbsuite.test import lldbplatform29from lldbsuite.test import lldbplatformutil30from lldbsuite.test.cpu_feature import CPUFeature31 32 33class DecorateMode:34    Skip, Xfail = range(2)35 36 37# You can use no_match to reverse the test of the conditional that is used to match keyword38# arguments in the skip / xfail decorators.  If oslist=["windows", "linux"] skips windows39# and linux, oslist=no_match(["windows", "linux"]) skips *unless* windows40# or linux.41class no_match:42    def __init__(self, item):43        self.item = item44 45 46def _check_expected_version(comparison, expected, actual):47    def fn_leq(x, y):48        return x <= y49 50    def fn_less(x, y):51        return x < y52 53    def fn_geq(x, y):54        return x >= y55 56    def fn_greater(x, y):57        return x > y58 59    def fn_eq(x, y):60        return x == y61 62    def fn_neq(x, y):63        return x != y64 65    op_lookup = {66        "==": fn_eq,67        "=": fn_eq,68        "!=": fn_neq,69        "<>": fn_neq,70        ">": fn_greater,71        "<": fn_less,72        ">=": fn_geq,73        "<=": fn_leq,74    }75 76    return op_lookup[comparison](version.parse(actual), version.parse(expected))77 78 79def _match_decorator_property(expected, actual):80    if expected is None:81        return True82 83    if actual is None:84        return False85 86    if isinstance(expected, no_match):87        return not _match_decorator_property(expected.item, actual)88 89    # Python 3.6 doesn't declare a `re.Pattern` type, get the dynamic type.90    pattern_type = type(re.compile(""))91    if isinstance(expected, (pattern_type, str)):92        return re.search(expected, actual) is not None93 94    if hasattr(expected, "__iter__"):95        return any(96            [x is not None and _match_decorator_property(x, actual) for x in expected]97        )98 99    return expected == actual100 101 102def _compiler_supports(103    compiler, flag, source="int main() {}", output_file=temp_file.OnDiskTempFile()104):105    """Test whether the compiler supports the given flag."""106    with output_file:107        if platform.system() == "Darwin":108            compiler = "xcrun " + compiler109        try:110            cmd = "echo '%s' | %s %s -x c -o %s -" % (111                source,112                compiler,113                flag,114                output_file.path,115            )116            subprocess.check_call(cmd, shell=True)117        except subprocess.CalledProcessError:118            return False119        return True120 121 122def expectedFailureIf(condition, bugnumber=None):123    def expectedFailure_impl(func):124        if isinstance(func, type) and issubclass(func, unittest.TestCase):125            raise Exception("Decorator can only be used to decorate a test method")126 127        if condition:128            return unittest.expectedFailure(func)129        return func130 131    if callable(bugnumber):132        return expectedFailure_impl(bugnumber)133    else:134        return expectedFailure_impl135 136 137def skipTestIfFn(expected_fn, bugnumber=None):138    def skipTestIfFn_impl(func):139        if isinstance(func, type) and issubclass(func, unittest.TestCase):140            reason = expected_fn()141            # The return value is the reason (or None if we don't skip), so142            # reason is used for both args.143            return unittest.skipIf(condition=reason, reason=reason)(func)144 145        @wraps(func)146        def wrapper(*args, **kwargs):147            self = args[0]148            if funcutils.requires_self(expected_fn):149                reason = expected_fn(self)150            else:151                reason = expected_fn()152 153            if reason is not None:154                self.skipTest(reason)155            else:156                return func(*args, **kwargs)157 158        return wrapper159 160    # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)161    # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])).  When called162    # the first way, the first argument will be the actual function because decorators are163    # weird like that.  So this is basically a check that says "how was the164    # decorator used"165    if callable(bugnumber):166        return skipTestIfFn_impl(bugnumber)167    else:168        return skipTestIfFn_impl169 170 171def _xfailForDebugInfo(expected_fn, bugnumber=None):172    def expectedFailure_impl(func):173        if isinstance(func, type) and issubclass(func, unittest.TestCase):174            raise Exception("Decorator can only be used to decorate a test method")175 176        func.__xfail_for_debug_info_cat_fn__ = expected_fn177        return func178 179    if callable(bugnumber):180        return expectedFailure_impl(bugnumber)181    else:182        return expectedFailure_impl183 184 185def _skipForDebugInfo(expected_fn, bugnumber=None):186    def skipImpl(func):187        if isinstance(func, type) and issubclass(func, unittest.TestCase):188            raise Exception("Decorator can only be used to decorate a test method")189 190        func.__skip_for_debug_info_cat_fn__ = expected_fn191        return func192 193    if callable(bugnumber):194        return skipImpl(bugnumber)195    else:196        return skipImpl197 198 199def _decorateTest(200    mode,201    bugnumber=None,202    oslist=None,203    hostoslist=None,204    compiler=None,205    compiler_version=None,206    archs=None,207    triple=None,208    debug_info=None,209    swig_version=None,210    py_version=None,211    macos_version=None,212    remote=None,213    dwarf_version=None,214    setting=None,215    asan=None,216):217    def fn(actual_debug_info=None):218        skip_for_os = _match_decorator_property(219            lldbplatform.translate(oslist), lldbplatformutil.getPlatform()220        )221        skip_for_hostos = _match_decorator_property(222            lldbplatform.translate(hostoslist), lldbplatformutil.getHostPlatform()223        )224        skip_for_compiler = _match_decorator_property(225            compiler, lldbplatformutil.getCompiler()226        ) and lldbplatformutil.expectedCompilerVersion(compiler_version)227        skip_for_arch = _match_decorator_property(228            archs, lldbplatformutil.getArchitecture()229        )230        skip_for_debug_info = _match_decorator_property(debug_info, actual_debug_info)231        skip_for_triple = _match_decorator_property(232            triple, lldb.selected_platform.GetTriple()233        )234        skip_for_remote = _match_decorator_property(235            remote, lldb.remote_platform is not None236        )237 238        skip_for_swig_version = (239            (swig_version is None)240            or (not hasattr(lldb, "swig_version"))241            or (242                _check_expected_version(243                    swig_version[0], swig_version[1], lldb.swig_version244                )245            )246        )247        skip_for_py_version = (py_version is None) or _check_expected_version(248            py_version[0],249            py_version[1],250            "{}.{}".format(sys.version_info.major, sys.version_info.minor),251        )252        skip_for_macos_version = (macos_version is None) or (253            (platform.mac_ver()[0] != "")254            and (255                _check_expected_version(256                    macos_version[0], macos_version[1], platform.mac_ver()[0]257                )258            )259        )260        skip_for_dwarf_version = (dwarf_version is None) or (261            _check_expected_version(262                dwarf_version[0], dwarf_version[1], lldbplatformutil.getDwarfVersion()263            )264        )265        skip_for_setting = (setting is None) or (setting in configuration.settings)266        skip_for_asan = (asan is None) or is_running_under_asan()267 268        # For the test to be skipped, all specified (e.g. not None) parameters must be True.269        # An unspecified parameter means "any", so those are marked skip by default.  And we skip270        # the final test if all conditions are True.271        conditions = [272            (oslist, skip_for_os, "target o/s"),273            (hostoslist, skip_for_hostos, "host o/s"),274            (compiler, skip_for_compiler, "compiler or version"),275            (archs, skip_for_arch, "architecture"),276            (debug_info, skip_for_debug_info, "debug info format"),277            (triple, skip_for_triple, "target triple"),278            (swig_version, skip_for_swig_version, "swig version"),279            (py_version, skip_for_py_version, "python version"),280            (macos_version, skip_for_macos_version, "macOS version"),281            (remote, skip_for_remote, "platform locality (remote/local)"),282            (dwarf_version, skip_for_dwarf_version, "dwarf version"),283            (setting, skip_for_setting, "setting"),284            (asan, skip_for_asan, "running under asan"),285        ]286        reasons = []287        final_skip_result = True288        for this_condition in conditions:289            final_skip_result = final_skip_result and this_condition[1]290            if this_condition[0] is not None and this_condition[1]:291                reasons.append(this_condition[2])292        reason_str = None293        if final_skip_result:294            mode_str = {DecorateMode.Skip: "skipping", DecorateMode.Xfail: "xfailing"}[295                mode296            ]297            if len(reasons) > 0:298                reason_str = ",".join(reasons)299                reason_str = "{} due to the following parameter(s): {}".format(300                    mode_str, reason_str301                )302            else:303                reason_str = "{} unconditionally".format(mode_str)304            if bugnumber is not None and not callable(bugnumber):305                reason_str = reason_str + " [" + str(bugnumber) + "]"306        return reason_str307 308    if mode == DecorateMode.Skip:309        if debug_info:310            return _skipForDebugInfo(fn, bugnumber)311        return skipTestIfFn(fn, bugnumber)312    elif mode == DecorateMode.Xfail:313        if debug_info:314            return _xfailForDebugInfo(fn, bugnumber)315        return expectedFailureIf(fn(), bugnumber)316    else:317        return None318 319 320# provide a function to xfail on defined oslist, compiler version, and archs321# if none is specified for any argument, that argument won't be checked and thus means for all322# for example,323# @expectedFailureAll, xfail for all platform/compiler/arch,324# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture325# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386326 327 328def expectedFailureAll(329    bugnumber=None,330    oslist=None,331    hostoslist=None,332    compiler=None,333    compiler_version=None,334    archs=None,335    triple=None,336    debug_info=None,337    swig_version=None,338    py_version=None,339    macos_version=None,340    remote=None,341    dwarf_version=None,342    setting=None,343    asan=None,344):345    return _decorateTest(346        DecorateMode.Xfail,347        bugnumber=bugnumber,348        oslist=oslist,349        hostoslist=hostoslist,350        compiler=compiler,351        compiler_version=compiler_version,352        archs=archs,353        triple=triple,354        debug_info=debug_info,355        swig_version=swig_version,356        py_version=py_version,357        macos_version=macos_version,358        remote=remote,359        dwarf_version=dwarf_version,360        setting=setting,361        asan=asan,362    )363 364 365# provide a function to skip on defined oslist, compiler version, and archs366# if none is specified for any argument, that argument won't be checked and thus means for all367# for example,368# @skipIf, skip for all platform/compiler/arch,369# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture370# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 (all conditions must be true)371def skipIf(372    bugnumber=None,373    oslist=None,374    hostoslist=None,375    compiler=None,376    compiler_version=None,377    archs=None,378    triple=None,379    debug_info=None,380    swig_version=None,381    py_version=None,382    macos_version=None,383    remote=None,384    dwarf_version=None,385    setting=None,386    asan=None,387):388    return _decorateTest(389        DecorateMode.Skip,390        bugnumber=bugnumber,391        oslist=oslist,392        hostoslist=hostoslist,393        compiler=compiler,394        compiler_version=compiler_version,395        archs=archs,396        triple=triple,397        debug_info=debug_info,398        swig_version=swig_version,399        py_version=py_version,400        macos_version=macos_version,401        remote=remote,402        dwarf_version=dwarf_version,403        setting=setting,404        asan=asan,405    )406 407 408def skip(bugnumber=None):409    return _decorateTest(DecorateMode.Skip, bugnumber=bugnumber)410 411 412def _skip_fn_for_android(reason, api_levels, archs):413    def impl():414        result = lldbplatformutil.match_android_device(415            lldbplatformutil.getArchitecture(),416            valid_archs=archs,417            valid_api_levels=api_levels,418        )419        return reason if result else None420 421    return impl422 423 424def add_test_categories(cat):425    """Add test categories to a TestCase method"""426    cat = test_categories.validate(cat, True)427 428    def impl(func):429        try:430            if hasattr(func, "categories"):431                cat.extend(func.categories)432            setattr(func, "categories", cat)433        except AttributeError:434            raise Exception("Cannot assign categories to inline tests.")435 436        return func437 438    return impl439 440 441def no_debug_info_test(func):442    """Decorate the item as a test what don't use any debug info. If this annotation is specified443    then the test runner won't generate a separate test for each debug info format."""444    if isinstance(func, type) and issubclass(func, unittest.TestCase):445        raise Exception(446            "@no_debug_info_test can only be used to decorate a test method"447        )448 449    @wraps(func)450    def wrapper(self, *args, **kwargs):451        return func(self, *args, **kwargs)452 453    # Mark this function as such to separate them from the regular tests.454    wrapper.__no_debug_info_test__ = True455    return wrapper456 457 458def apple_simulator_test(platform):459    """460    Decorate the test as a test requiring a simulator for a specific platform.461 462    Consider that a simulator is available if you have the corresponding SDK463    and runtime installed.464 465    The SDK identifiers for simulators are iphonesimulator, appletvsimulator,466    watchsimulator467    """468 469    def should_skip_simulator_test():470        if lldbplatformutil.getHostPlatform() not in ["darwin", "macosx"]:471            return "simulator tests are run only on darwin hosts."472 473        # Make sure we recognize the platform.474        mapping = {475            "iphone": "ios",476            "appletv": "tvos",477            "watch": "watchos",478        }479        if platform not in mapping:480            return "unknown simulator platform: {}".format(platform)481 482        # Make sure we have an SDK.483        try:484            output = subprocess.check_output(485                ["xcodebuild", "-showsdks"], stderr=subprocess.DEVNULL486            ).decode("utf-8")487            if not re.search("%ssimulator" % platform, output):488                return "%s simulator is not supported on this system." % platform489        except subprocess.CalledProcessError:490            return "Simulators are unsupported on this system (xcodebuild failed)"491 492        # Make sure we a simulator runtime.493        try:494            sim_devices_str = subprocess.check_output(495                ["xcrun", "simctl", "list", "-j", "devices"]496            ).decode("utf-8")497 498            sim_devices = json.loads(sim_devices_str)["devices"]499            for simulator in sim_devices:500                if isinstance(simulator, dict):501                    runtime = simulator["name"]502                    devices = simulator["devices"]503                else:504                    runtime = simulator505                    devices = sim_devices[simulator]506 507                if not mapping[platform] in runtime.lower():508                    continue509 510                for device in devices:511                    if (512                        "availability" in device513                        and device["availability"] == "(available)"514                    ):515                        return None516                    if "isAvailable" in device and device["isAvailable"]:517                        return None518 519            return "{} simulator is not supported on this system.".format(platform)520        except (subprocess.CalledProcessError, json.decoder.JSONDecodeError):521            return "Simulators are unsupported on this system (simctl failed)"522 523    return skipTestIfFn(should_skip_simulator_test)524 525 526def debugserver_test(func):527    """Decorate the item as a debugserver test."""528    return add_test_categories(["debugserver"])(func)529 530 531def llgs_test(func):532    """Decorate the item as a lldb-server test."""533    return add_test_categories(["llgs"])(func)534 535 536def expectedFailureOS(537    oslist, bugnumber=None, compilers=None, debug_info=None, archs=None538):539    return expectedFailureAll(540        oslist=oslist,541        bugnumber=bugnumber,542        compiler=compilers,543        archs=archs,544        debug_info=debug_info,545    )546 547 548def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None, archs=None):549    # For legacy reasons, we support both "darwin" and "macosx" as OS X550    # triples.551    return expectedFailureOS(552        lldbplatform.darwin_all,553        bugnumber,554        compilers,555        debug_info=debug_info,556        archs=archs,557    )558 559 560def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None):561    """Mark a test as xfail for Android.562 563    Arguments:564        bugnumber - The LLVM pr associated with the problem.565        api_levels - A sequence of numbers specifying the Android API levels566            for which a test is expected to fail. None means all API level.567        arch - A sequence of architecture names specifying the architectures568            for which a test is expected to fail. None means all architectures.569    """570    return expectedFailureIf(571        _skip_fn_for_android("xfailing on android", api_levels, archs)(), bugnumber572    )573 574 575def expectedFailureNetBSD(bugnumber=None):576    return expectedFailureOS(["netbsd"], bugnumber)577 578 579def expectedFailureWindows(bugnumber=None):580    return expectedFailureOS(["windows"], bugnumber)581 582 583# TODO: This decorator does not do anything. Remove it.584def expectedFlakey(expected_fn, bugnumber=None):585    def expectedFailure_impl(func):586        @wraps(func)587        def wrapper(*args, **kwargs):588            func(*args, **kwargs)589 590        return wrapper591 592    # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows)593    # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])).  When called594    # the first way, the first argument will be the actual function because decorators are595    # weird like that.  So this is basically a check that says "which syntax was the original596    # function decorated with?"597    if callable(bugnumber):598        return expectedFailure_impl(bugnumber)599    else:600        return expectedFailure_impl601 602 603def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):604    def fn(self):605        return (606            lldbplatformutil.getPlatform() in oslist607            and lldbplatformutil.expectedCompiler(compilers)608        )609 610    return expectedFlakey(fn, bugnumber)611 612 613def expectedFlakeyDarwin(bugnumber=None, compilers=None):614    # For legacy reasons, we support both "darwin" and "macosx" as OS X615    # triples.616    return expectedFlakeyOS(lldbplatformutil.getDarwinOSTriples(), bugnumber, compilers)617 618 619def expectedFlakeyFreeBSD(bugnumber=None, compilers=None):620    return expectedFlakeyOS(["freebsd"], bugnumber, compilers)621 622 623def expectedFlakeyLinux(bugnumber=None, compilers=None):624    return expectedFlakeyOS(["linux"], bugnumber, compilers)625 626 627def expectedFlakeyNetBSD(bugnumber=None, compilers=None):628    return expectedFlakeyOS(["netbsd"], bugnumber, compilers)629 630 631def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None):632    return expectedFlakey(633        _skip_fn_for_android("flakey on android", api_levels, archs), bugnumber634    )635 636 637def skipIfOutOfTreeDebugserver(func):638    """Decorate the item to skip tests if using an out-of-tree debugserver."""639 640    def is_out_of_tree_debugserver():641        return (642            "out-of-tree debugserver"643            if lldbtest_config.out_of_tree_debugserver644            else None645        )646 647    return skipTestIfFn(is_out_of_tree_debugserver)(func)648 649 650def skipIfOutOfTreeLibunwind(func):651    """Decorate the item to skip tests if libunwind was not built in-tree."""652 653    def is_out_of_tree_libunwind():654        if not configuration.llvm_tools_dir:655            return "out-of-tree libunwind"656 657        # llvm_tools_dir is typically <build>/bin, so lib is a sibling.658        llvm_lib_dir = os.path.join(659            os.path.dirname(configuration.llvm_tools_dir), "lib"660        )661 662        if not os.path.isdir(llvm_lib_dir):663            return "out-of-tree libunwind"664 665        # Check for libunwind library (any extension).666        for filename in os.listdir(llvm_lib_dir):667            if filename.startswith("libunwind.") or filename.startswith("unwind."):668                return None669 670        return "out-of-tree libunwind"671 672    return skipTestIfFn(is_out_of_tree_libunwind)(func)673 674 675def skipIfRemote(func):676    """Decorate the item to skip tests if testing remotely."""677    return unittest.skipIf(lldb.remote_platform, "skip on remote platform")(func)678 679 680def skipIfNoSBHeaders(func):681    """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers."""682 683    def are_sb_headers_missing():684        if lldb.remote_platform:685            return "skip because SBHeaders tests make no sense remotely"686 687        if (688            lldbplatformutil.getHostPlatform() == "darwin"689            and configuration.lldb_framework_path690        ):691            header = os.path.join(692                configuration.lldb_framework_path,693                "Versions",694                "Current",695                "Headers",696                "LLDB.h",697            )698            if os.path.exists(header):699                return None700 701        header = os.path.join(702            os.environ["LLDB_SRC"], "include", "lldb", "API", "LLDB.h"703        )704        if not os.path.exists(header):705            return "skip because LLDB.h header not found"706        return None707 708    return skipTestIfFn(are_sb_headers_missing)(func)709 710 711def skipIfRosetta(bugnumber):712    """Skip a test when running the testsuite on macOS under the Rosetta translation layer."""713 714    def is_running_rosetta():715        if lldbplatformutil.getPlatform() in ["darwin", "macosx"]:716            if (platform.uname()[5] == "arm") and (717                lldbplatformutil.getArchitecture() == "x86_64"718            ):719                return "skipped under Rosetta"720        return None721 722    return skipTestIfFn(is_running_rosetta)723 724 725def skipIfiOSSimulator(func):726    """Decorate the item to skip tests that should be skipped on the iOS Simulator."""727 728    def is_ios_simulator():729        return (730            "skip on the iOS Simulator"731            if configuration.lldb_platform_name == "ios-simulator"732            else None733        )734 735    return skipTestIfFn(is_ios_simulator)(func)736 737 738def skipIfiOS(func):739    return skipIfPlatform(lldbplatform.translate(lldbplatform.ios))(func)740 741 742def skipIftvOS(func):743    return skipIfPlatform(lldbplatform.translate(lldbplatform.tvos))(func)744 745 746def skipIfwatchOS(func):747    return skipIfPlatform(lldbplatform.translate(lldbplatform.watchos))(func)748 749 750def skipIfbridgeOS(func):751    return skipIfPlatform(lldbplatform.translate(lldbplatform.bridgeos))(func)752 753 754def skipIfDarwinEmbedded(func):755    """Decorate the item to skip tests that should be skipped on Darwin armv7/arm64 targets."""756    return skipIfPlatform(lldbplatform.translate(lldbplatform.darwin_embedded))(func)757 758 759def skipIfDarwinSimulator(func):760    """Decorate the item to skip tests that should be skipped on Darwin simulator targets."""761    return skipIfPlatform(lldbplatform.translate(lldbplatform.darwin_simulator))(func)762 763 764def skipIfFreeBSD(func):765    """Decorate the item to skip tests that should be skipped on FreeBSD."""766    return skipIfPlatform(["freebsd"])(func)767 768 769def skipIfNetBSD(func):770    """Decorate the item to skip tests that should be skipped on NetBSD."""771    return skipIfPlatform(["netbsd"])(func)772 773 774def skipIfDarwin(func):775    """Decorate the item to skip tests that should be skipped on Darwin."""776    return skipIfPlatform(lldbplatform.translate(lldbplatform.darwin_all))(func)777 778 779def skipIfLinux(func):780    """Decorate the item to skip tests that should be skipped on Linux."""781    return skipIfPlatform(["linux"])(func)782 783 784def skipIfWindows(func):785    """Decorate the item to skip tests that should be skipped on Windows."""786    return skipIfPlatform(["windows"])(func)787 788 789def skipIfWindowsAndNonEnglish(func):790    """Decorate the item to skip tests that should be skipped on non-English locales on Windows."""791 792    def is_Windows_NonEnglish():793        if sys.platform != "win32":794            return None795        kernel = ctypes.windll.kernel32796        if locale.windows_locale[kernel.GetUserDefaultUILanguage()] == "en_US":797            return None798        return "skipping non-English Windows locale"799 800    return skipTestIfFn(is_Windows_NonEnglish)(func)801 802 803def skipUnlessWindows(func):804    """Decorate the item to skip tests that should be skipped on any non-Windows platform."""805    return skipUnlessPlatform(["windows"])(func)806 807 808def skipUnlessDarwin(func):809    """Decorate the item to skip tests that should be skipped on any non Darwin platform."""810    return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func)811 812 813def skipUnlessTargetAndroid(func):814    return unittest.skipUnless(815        lldbplatformutil.target_is_android(), "requires target to be Android"816    )(func)817 818 819def skipIfHostIncompatibleWithTarget(func):820    """Decorate the item to skip tests when the host and target are incompatible."""821 822    def is_host_incompatible_with_remote():823        host_arch = lldbplatformutil.getLLDBArchitecture()824        host_platform = lldbplatformutil.getHostPlatform()825        target_arch = lldbplatformutil.getArchitecture()826        target_platform = lldbplatformutil.getPlatform()827        if (828            not (target_arch == "x86_64" and host_arch == "i386")829            and host_arch != target_arch830        ):831            return (832                "skipping because target %s is not compatible with host architecture %s"833                % (target_arch, host_arch)834            )835        if target_platform != host_platform:836            return "skipping because target is %s but host is %s" % (837                target_platform,838                host_platform,839            )840        if lldbplatformutil.match_android_device(target_arch):841            return "skipping because target is android"842        return None843 844    return skipTestIfFn(is_host_incompatible_with_remote)(func)845 846 847def skipIfPlatform(oslist):848    """Decorate the item to skip tests if running on one of the listed platforms."""849    # This decorator cannot be ported to `skipIf` yet because it is used on entire850    # classes, which `skipIf` explicitly forbids.851    return unittest.skipIf(852        lldbplatformutil.getPlatform() in oslist, "skip on %s" % (", ".join(oslist))853    )854 855 856def skipUnlessPlatform(oslist):857    """Decorate the item to skip tests unless running on one of the listed platforms."""858    # This decorator cannot be ported to `skipIf` yet because it is used on entire859    # classes, which `skipIf` explicitly forbids.860    return unittest.skipUnless(861        lldbplatformutil.getPlatform() in oslist,862        "requires one of %s" % (", ".join(oslist)),863    )864 865 866def skipUnlessArch(arch):867    """Decorate the item to skip tests unless running on the specified architecture."""868 869    def arch_doesnt_match():870        target_arch = lldbplatformutil.getArchitecture()871        if arch != target_arch:872            return "Test only runs on " + arch + ", but target arch is " + target_arch873        return None874 875    return skipTestIfFn(arch_doesnt_match)876 877 878def skipIfTargetAndroid(bugnumber=None, api_levels=None, archs=None):879    """Decorator to skip tests when the target is Android.880 881    Arguments:882        api_levels - The API levels for which the test should be skipped. If883            it is None, then the test will be skipped for all API levels.884        arch - A sequence of architecture names specifying the architectures885            for which a test is skipped. None means all architectures.886    """887    return skipTestIfFn(888        _skip_fn_for_android("skipping for android", api_levels, archs), bugnumber889    )890 891 892def skipUnlessAppleSilicon(func):893    """Decorate the item to skip tests unless running on Apple Silicon."""894 895    def not_apple_silicon():896        if platform.system() != "Darwin" or lldbplatformutil.getArchitecture() not in [897            "arm64",898            "arm64e",899        ]:900            return "Test only runs on Apple Silicon"901        return None902 903    return skipTestIfFn(not_apple_silicon)(func)904 905 906def skipUnlessSupportedTypeAttribute(attr):907    """Decorate the item to skip test unless Clang supports type __attribute__(attr)."""908 909    def compiler_doesnt_support_struct_attribute():910        compiler_path = lldbplatformutil.getCompiler()911        with temp_file.OnDiskTempFile() as f:912            cmd = [lldbplatformutil.getCompiler(), "-x", "c++", "-c", "-o", f.path, "-"]913            p = subprocess.Popen(914                cmd,915                stdin=subprocess.PIPE,916                stdout=subprocess.PIPE,917                stderr=subprocess.PIPE,918                universal_newlines=True,919            )920            stdout, stderr = p.communicate("struct __attribute__((%s)) Test {};" % attr)921            if attr in stderr:922                return "Compiler does not support attribute %s" % (attr)923            return None924 925    return skipTestIfFn(compiler_doesnt_support_struct_attribute)926 927 928def skipUnlessHasCallSiteInfo(func):929    """Decorate the function to skip testing unless call site info from clang is available."""930 931    def is_compiler_clang_with_call_site_info():932        compiler_path = lldbplatformutil.getCompiler()933        compiler = os.path.basename(compiler_path)934        if not compiler.startswith("clang"):935            return "Test requires clang as compiler"936 937        with temp_file.OnDiskTempFile() as f:938            cmd = (939                "echo 'int main() {}' | "940                "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.path)941            )942            if os.popen(cmd).close() is not None:943                return "Compiler can't compile with call site info enabled"944 945            with open(f.path, "r") as ir_output_file:946                buf = ir_output_file.read()947 948            if "DIFlagAllCallsDescribed" not in buf:949                return "Compiler did not introduce DIFlagAllCallsDescribed IR flag"950 951            return None952 953    return skipTestIfFn(is_compiler_clang_with_call_site_info)(func)954 955 956def skipUnlessThreadSanitizer(func):957    """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""958 959    def is_compiler_clang_with_thread_sanitizer():960        if is_running_under_asan():961            return "Thread sanitizer tests are disabled when runing under ASAN"962 963        compiler_path = lldbplatformutil.getCompiler()964        compiler = os.path.basename(compiler_path)965        if not compiler.startswith("clang"):966            return "Test requires clang as compiler"967        if lldbplatformutil.getPlatform() == "windows":968            return "TSAN tests not compatible with 'windows'"969        # rdar://28659145 - TSAN tests don't look like they're supported on i386970        if (971            lldbplatformutil.getArchitecture() == "i386"972            and platform.system() == "Darwin"973        ):974            return "TSAN tests not compatible with i386 targets"975        if not _compiler_supports(compiler_path, "-fsanitize=thread"):976            return "Compiler cannot compile with -fsanitize=thread"977        return None978 979    return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func)980 981 982def skipUnlessUndefinedBehaviorSanitizer(func):983    """Decorate the item to skip test unless -fsanitize=undefined is supported."""984 985    def is_compiler_clang_with_ubsan():986        if is_running_under_asan():987            return (988                "Undefined behavior sanitizer tests are disabled when runing under ASAN"989            )990 991        # We need to write out the object into a named temp file for inspection.992        outputf = temp_file.OnDiskTempFile()993 994        # Try to compile with ubsan turned on.995        if not _compiler_supports(996            lldbplatformutil.getCompiler(),997            "-fsanitize=undefined",998            "int main() { int x = 0; return x / x; }",999            outputf,1000        ):1001            return "Compiler cannot compile with -fsanitize=undefined"1002 1003        # Check that we actually see ubsan instrumentation in the binary.1004        cmd = "nm %s" % outputf.path1005        with os.popen(cmd) as nm_output:1006            if "___ubsan_handle_divrem_overflow" not in nm_output.read():1007                return "Division by zero instrumentation is missing"1008 1009        # Find the ubsan dylib.1010        # FIXME: This check should go away once compiler-rt gains support for __ubsan_on_report.1011        cmd = (1012            "%s -fsanitize=undefined -x c - -o - -### 2>&1"1013            % lldbplatformutil.getCompiler()1014        )1015        with os.popen(cmd) as cc_output:1016            driver_jobs = cc_output.read()1017            m = re.search(r'"([^"]+libclang_rt.ubsan_osx_dynamic.dylib)"', driver_jobs)1018            if not m:1019                return "Could not find the ubsan dylib used by the driver"1020            ubsan_dylib = m.group(1)1021 1022        # Check that the ubsan dylib has special monitor hooks.1023        cmd = "nm -gU %s" % ubsan_dylib1024        with os.popen(cmd) as nm_output:1025            syms = nm_output.read()1026            if "___ubsan_on_report" not in syms:1027                return "Missing ___ubsan_on_report"1028            if "___ubsan_get_current_report_data" not in syms:1029                return "Missing ___ubsan_get_current_report_data"1030 1031        # OK, this dylib + compiler works for us.1032        return None1033 1034    return skipTestIfFn(is_compiler_clang_with_ubsan)(func)1035 1036 1037def is_running_under_asan():1038    if "ASAN_OPTIONS" in os.environ:1039        return "ASAN unsupported"1040    return None1041 1042 1043def skipUnlessAddressSanitizer(func):1044    """Decorate the item to skip test unless Clang -fsanitize=thread is supported."""1045 1046    def is_compiler_with_address_sanitizer():1047        # Also don't run tests that use address sanitizer inside an1048        # address-sanitized LLDB. The tests don't support that1049        # configuration.1050        if is_running_under_asan():1051            return "Address sanitizer tests are disabled when runing under ASAN"1052 1053        if lldbplatformutil.getPlatform() == "windows":1054            return "ASAN tests not compatible with 'windows'"1055        if not _compiler_supports(lldbplatformutil.getCompiler(), "-fsanitize=address"):1056            return "Compiler cannot compile with -fsanitize=address"1057        return None1058 1059    return skipTestIfFn(is_compiler_with_address_sanitizer)(func)1060 1061 1062def skipUnlessBoundsSafety(func):1063    """Decorate the item to skip test unless Clang -fbounds-safety is supported."""1064 1065    def is_compiler_with_bounds_safety():1066        if not _compiler_supports(lldbplatformutil.getCompiler(), "-fbounds-safety"):1067            return "Compiler cannot compile with -fbounds-safety"1068        return None1069 1070    return skipTestIfFn(is_compiler_with_bounds_safety)(func)1071 1072def skipIfAsan(func):1073    """Skip this test if the environment is set up to run LLDB *itself* under ASAN."""1074    return skipTestIfFn(is_running_under_asan)(func)1075 1076 1077def skipUnlessAArch64MTELinuxCompiler(func):1078    """Decorate the item to skip test unless MTE is supported by the test compiler."""1079 1080    def is_toolchain_with_mte():1081        compiler_path = lldbplatformutil.getCompiler()1082        with temp_file.OnDiskTempFile() as f:1083            if lldbplatformutil.getPlatform() == "windows":1084                return "MTE tests are not compatible with 'windows'"1085 1086            cmd = f"{compiler_path} -x c -o {f.path} -"1087            if (1088                subprocess.run(1089                    cmd, shell=True, input="int main() {}".encode()1090                ).returncode1091                != 01092            ):1093                # Cannot compile at all, don't skip the test1094                # so that we report the broken compiler normally.1095                return None1096 1097            # We need the Linux headers and ACLE MTE intrinsics1098            test_src = """1099                #include <asm/hwcap.h>1100                #include <arm_acle.h>1101                #ifndef HWCAP2_MTE1102                #error1103                #endif1104                int main() {1105                    void* ptr = __arm_mte_create_random_tag((void*)(0), 0);1106                }"""1107            cmd = f"{compiler_path} -march=armv8.5-a+memtag -x c -o {f.path} -"1108            res = subprocess.run(cmd, shell=True, input=test_src.encode())1109            if res.returncode != 0:1110                return "Toolchain does not support MTE"1111            return None1112 1113    return skipTestIfFn(is_toolchain_with_mte)(func)1114 1115 1116def _get_bool_config(key, fail_value=True):1117    """1118    Returns the current LLDB's build config value.1119    :param key The key to lookup in LLDB's build configuration.1120    :param fail_value The error value to return when the key can't be found.1121           Defaults to true so that if an unknown key is lookup up we rather1122           enable more tests (that then fail) than silently skipping them.1123    """1124    config = lldb.SBDebugger.GetBuildConfiguration()1125    value_node = config.GetValueForKey(key)1126    return value_node.GetValueForKey("value").GetBooleanValue(fail_value)1127 1128 1129def _get_bool_config_skip_if_decorator(key):1130    have = _get_bool_config(key)1131    return unittest.skipIf(not have, "requires " + key)1132 1133 1134def skipIfCurlSupportMissing(func):1135    return _get_bool_config_skip_if_decorator("curl")(func)1136 1137 1138def skipIfCursesSupportMissing(func):1139    return _get_bool_config_skip_if_decorator("curses")(func)1140 1141 1142def skipIfXmlSupportMissing(func):1143    return _get_bool_config_skip_if_decorator("xml")(func)1144 1145 1146def skipIfEditlineSupportMissing(func):1147    return _get_bool_config_skip_if_decorator("editline")(func)1148 1149 1150def skipIfEditlineWideCharSupportMissing(func):1151    return _get_bool_config_skip_if_decorator("editline_wchar")(func)1152 1153 1154def skipIfFBSDVMCoreSupportMissing(func):1155    return _get_bool_config_skip_if_decorator("fbsdvmcore")(func)1156 1157 1158def skipIfLLVMTargetMissing(target):1159    config = lldb.SBDebugger.GetBuildConfiguration()1160    targets = config.GetValueForKey("targets").GetValueForKey("value")1161    found = False1162    for i in range(targets.GetSize()):1163        if targets.GetItemAtIndex(i).GetStringValue(99) == target:1164            found = True1165            break1166 1167    return unittest.skipIf(not found, "requires " + target)1168 1169 1170def skipUnlessFeature(cpu_feature: CPUFeature):1171    def hasFeature(test_case):1172        if not test_case.isSupported(cpu_feature):1173            return f"Unsupported CPU feature: {cpu_feature}"1174        return None1175 1176    return skipTestIfFn(hasFeature)1177 1178 1179def skipIfBuildType(types: list[str]):1180    """Skip tests if built in a specific CMAKE_BUILD_TYPE.1181 1182    Supported types include 'Release', 'RelWithDebInfo', 'Debug', 'MinSizeRel'.1183    """1184    types = [name.lower() for name in types]1185    return unittest.skipIf(1186        configuration.cmake_build_type is not None1187        and configuration.cmake_build_type.lower() in types,1188        "skip on {} build type(s)".format(", ".join(types)),1189    )1190