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