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