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