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