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