1from __future__ import absolute_import 2from __future__ import print_function 3 4# System modules 5from distutils.version import LooseVersion, StrictVersion 6from functools import wraps 7import os 8import platform 9import re 10import sys 11import tempfile 12 13# Third-party modules 14import six 15import unittest2 16 17# LLDB modules 18import use_lldb_suite 19 20import lldb 21from . import configuration 22from . import test_categories 23from lldbsuite.test_event.event_builder import EventBuilder 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 74def _match_decorator_property(expected, actual): 75 if actual is None or expected is None: 76 return True 77 78 if isinstance(expected, no_match): 79 return not _match_decorator_property(expected.item, actual) 80 elif isinstance(expected, (re._pattern_type,) + six.string_types): 81 return re.search(expected, actual) is not None 82 elif hasattr(expected, "__iter__"): 83 return any([x is not None and _match_decorator_property(x, actual) 84 for x in expected]) 85 else: 86 return expected == actual 87 88 89def expectedFailure(expected_fn, bugnumber=None): 90 def expectedFailure_impl(func): 91 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 92 raise Exception( 93 "Decorator can only be used to decorate a test method") 94 95 @wraps(func) 96 def wrapper(*args, **kwargs): 97 self = args[0] 98 if funcutils.requires_self(expected_fn): 99 xfail_reason = expected_fn(self) 100 else: 101 xfail_reason = expected_fn() 102 if xfail_reason is not None: 103 if configuration.results_formatter_object is not None: 104 # Mark this test as expected to fail. 105 configuration.results_formatter_object.handle_event( 106 EventBuilder.event_for_mark_test_expected_failure(self)) 107 xfail_func = unittest2.expectedFailure(func) 108 xfail_func(*args, **kwargs) 109 else: 110 func(*args, **kwargs) 111 return wrapper 112 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) 113 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called 114 # the first way, the first argument will be the actual function because decorators are 115 # weird like that. So this is basically a check that says "which syntax was the original 116 # function decorated with?" 117 if six.callable(bugnumber): 118 return expectedFailure_impl(bugnumber) 119 else: 120 return expectedFailure_impl 121 122 123def skipTestIfFn(expected_fn, bugnumber=None): 124 def skipTestIfFn_impl(func): 125 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 126 raise Exception( 127 "@skipTestIfFn can only be used to decorate a test method") 128 129 @wraps(func) 130 def wrapper(*args, **kwargs): 131 self = args[0] 132 if funcutils.requires_self(expected_fn): 133 reason = expected_fn(self) 134 else: 135 reason = expected_fn() 136 137 if reason is not None: 138 self.skipTest(reason) 139 else: 140 func(*args, **kwargs) 141 return wrapper 142 143 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) 144 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called 145 # the first way, the first argument will be the actual function because decorators are 146 # weird like that. So this is basically a check that says "how was the 147 # decorator used" 148 if six.callable(bugnumber): 149 return skipTestIfFn_impl(bugnumber) 150 else: 151 return skipTestIfFn_impl 152 153 154def _decorateTest(mode, 155 bugnumber=None, oslist=None, hostoslist=None, 156 compiler=None, compiler_version=None, 157 archs=None, triple=None, 158 debug_info=None, 159 swig_version=None, py_version=None, 160 macos_version=None, 161 remote=None): 162 def fn(self): 163 skip_for_os = _match_decorator_property( 164 lldbplatform.translate(oslist), self.getPlatform()) 165 skip_for_hostos = _match_decorator_property( 166 lldbplatform.translate(hostoslist), 167 lldbplatformutil.getHostPlatform()) 168 skip_for_compiler = _match_decorator_property( 169 compiler, self.getCompiler()) and self.expectedCompilerVersion(compiler_version) 170 skip_for_arch = _match_decorator_property( 171 archs, self.getArchitecture()) 172 skip_for_debug_info = _match_decorator_property( 173 debug_info, self.debug_info) 174 skip_for_triple = _match_decorator_property( 175 triple, lldb.DBG.GetSelectedPlatform().GetTriple()) 176 skip_for_remote = _match_decorator_property( 177 remote, lldb.remote_platform is not None) 178 179 skip_for_swig_version = ( 180 swig_version is None) or ( 181 not hasattr( 182 lldb, 183 'swig_version')) or ( 184 _check_expected_version( 185 swig_version[0], 186 swig_version[1], 187 lldb.swig_version)) 188 skip_for_py_version = ( 189 py_version is None) or _check_expected_version( 190 py_version[0], py_version[1], sys.version_info) 191 skip_for_macos_version = (macos_version is None) or ( 192 _check_expected_version( 193 macos_version[0], 194 macos_version[1], 195 platform.mac_ver()[0])) 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 reasons = [] 211 final_skip_result = True 212 for this_condition in conditions: 213 final_skip_result = final_skip_result and this_condition[1] 214 if this_condition[0] is not None and this_condition[1]: 215 reasons.append(this_condition[2]) 216 reason_str = None 217 if final_skip_result: 218 mode_str = { 219 DecorateMode.Skip: "skipping", 220 DecorateMode.Xfail: "xfailing"}[mode] 221 if len(reasons) > 0: 222 reason_str = ",".join(reasons) 223 reason_str = "{} due to the following parameter(s): {}".format( 224 mode_str, reason_str) 225 else: 226 reason_str = "{} unconditionally" 227 if bugnumber is not None and not six.callable(bugnumber): 228 reason_str = reason_str + " [" + str(bugnumber) + "]" 229 return reason_str 230 231 if mode == DecorateMode.Skip: 232 return skipTestIfFn(fn, bugnumber) 233 elif mode == DecorateMode.Xfail: 234 return expectedFailure(fn, bugnumber) 235 else: 236 return None 237 238# provide a function to xfail on defined oslist, compiler version, and archs 239# if none is specified for any argument, that argument won't be checked and thus means for all 240# for example, 241# @expectedFailureAll, xfail for all platform/compiler/arch, 242# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture 243# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386 244 245 246def expectedFailureAll(bugnumber=None, 247 oslist=None, hostoslist=None, 248 compiler=None, compiler_version=None, 249 archs=None, triple=None, 250 debug_info=None, 251 swig_version=None, py_version=None, 252 macos_version=None, 253 remote=None): 254 return _decorateTest(DecorateMode.Xfail, 255 bugnumber=bugnumber, 256 oslist=oslist, hostoslist=hostoslist, 257 compiler=compiler, compiler_version=compiler_version, 258 archs=archs, triple=triple, 259 debug_info=debug_info, 260 swig_version=swig_version, py_version=py_version, 261 macos_version=None, 262 remote=remote) 263 264 265# provide a function to skip 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# @skipIf, skip for all platform/compiler/arch, 269# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture 270# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 271def skipIf(bugnumber=None, 272 oslist=None, hostoslist=None, 273 compiler=None, compiler_version=None, 274 archs=None, triple=None, 275 debug_info=None, 276 swig_version=None, py_version=None, 277 macos_version=None, 278 remote=None): 279 return _decorateTest(DecorateMode.Skip, 280 bugnumber=bugnumber, 281 oslist=oslist, hostoslist=hostoslist, 282 compiler=compiler, compiler_version=compiler_version, 283 archs=archs, triple=triple, 284 debug_info=debug_info, 285 swig_version=swig_version, py_version=py_version, 286 macos_version=macos_version, 287 remote=remote) 288 289 290def _skip_for_android(reason, api_levels, archs): 291 def impl(obj): 292 result = lldbplatformutil.match_android_device( 293 obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels) 294 return reason if result else None 295 return impl 296 297 298def add_test_categories(cat): 299 """Add test categories to a TestCase method""" 300 cat = test_categories.validate(cat, True) 301 302 def impl(func): 303 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 304 raise Exception( 305 "@add_test_categories can only be used to decorate a test method") 306 if hasattr(func, "categories"): 307 cat.extend(func.categories) 308 func.categories = cat 309 return func 310 311 return impl 312 313 314def benchmarks_test(func): 315 """Decorate the item as a benchmarks test.""" 316 def should_skip_benchmarks_test(): 317 return "benchmarks test" 318 319 # Mark this function as such to separate them from the regular tests. 320 result = skipTestIfFn(should_skip_benchmarks_test)(func) 321 result.__benchmarks_test__ = True 322 return result 323 324 325def no_debug_info_test(func): 326 """Decorate the item as a test what don't use any debug info. If this annotation is specified 327 then the test runner won't generate a separate test for each debug info format. """ 328 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 329 raise Exception( 330 "@no_debug_info_test can only be used to decorate a test method") 331 332 @wraps(func) 333 def wrapper(self, *args, **kwargs): 334 return func(self, *args, **kwargs) 335 336 # Mark this function as such to separate them from the regular tests. 337 wrapper.__no_debug_info_test__ = True 338 return wrapper 339 340 341def debugserver_test(func): 342 """Decorate the item as a debugserver test.""" 343 def should_skip_debugserver_test(): 344 return "debugserver tests" if configuration.dont_do_debugserver_test else None 345 return skipTestIfFn(should_skip_debugserver_test)(func) 346 347 348def llgs_test(func): 349 """Decorate the item as a lldb-server test.""" 350 def should_skip_llgs_tests(): 351 return "llgs tests" if configuration.dont_do_llgs_test else None 352 return skipTestIfFn(should_skip_llgs_tests)(func) 353 354 355def not_remote_testsuite_ready(func): 356 """Decorate the item as a test which is not ready yet for remote testsuite.""" 357 def is_remote(): 358 return "Not ready for remote testsuite" if lldb.remote_platform else None 359 return skipTestIfFn(is_remote)(func) 360 361 362def expectedFailureOS( 363 oslist, 364 bugnumber=None, 365 compilers=None, 366 debug_info=None, 367 archs=None): 368 return expectedFailureAll( 369 oslist=oslist, 370 bugnumber=bugnumber, 371 compiler=compilers, 372 archs=archs, 373 debug_info=debug_info) 374 375 376def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None): 377 # For legacy reasons, we support both "darwin" and "macosx" as OS X 378 # triples. 379 return expectedFailureOS( 380 lldbplatform.darwin_all, 381 bugnumber, 382 compilers, 383 debug_info=debug_info) 384 385 386def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None): 387 """ Mark a test as xfail for Android. 388 389 Arguments: 390 bugnumber - The LLVM pr associated with the problem. 391 api_levels - A sequence of numbers specifying the Android API levels 392 for which a test is expected to fail. None means all API level. 393 arch - A sequence of architecture names specifying the architectures 394 for which a test is expected to fail. None means all architectures. 395 """ 396 return expectedFailure( 397 _skip_for_android( 398 "xfailing on android", 399 api_levels, 400 archs), 401 bugnumber) 402 403# Flakey tests get two chances to run. If they fail the first time round, the result formatter 404# makes sure it is run one more time. 405 406 407def expectedFlakey(expected_fn, bugnumber=None): 408 def expectedFailure_impl(func): 409 @wraps(func) 410 def wrapper(*args, **kwargs): 411 self = args[0] 412 if expected_fn(self): 413 # Send event marking test as explicitly eligible for rerunning. 414 if configuration.results_formatter_object is not None: 415 # Mark this test as rerunnable. 416 configuration.results_formatter_object.handle_event( 417 EventBuilder.event_for_mark_test_rerun_eligible(self)) 418 func(*args, **kwargs) 419 return wrapper 420 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) 421 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called 422 # the first way, the first argument will be the actual function because decorators are 423 # weird like that. So this is basically a check that says "which syntax was the original 424 # function decorated with?" 425 if six.callable(bugnumber): 426 return expectedFailure_impl(bugnumber) 427 else: 428 return expectedFailure_impl 429 430 431def expectedFlakeyDwarf(bugnumber=None): 432 def fn(self): 433 return self.debug_info == "dwarf" 434 return expectedFlakey(fn, bugnumber) 435 436 437def expectedFlakeyDsym(bugnumber=None): 438 def fn(self): 439 return self.debug_info == "dwarf" 440 return expectedFlakey(fn, bugnumber) 441 442 443def expectedFlakeyOS(oslist, bugnumber=None, compilers=None): 444 def fn(self): 445 return (self.getPlatform() in oslist and 446 self.expectedCompiler(compilers)) 447 return expectedFlakey(fn, bugnumber) 448 449 450def expectedFlakeyDarwin(bugnumber=None, compilers=None): 451 # For legacy reasons, we support both "darwin" and "macosx" as OS X 452 # triples. 453 return expectedFlakeyOS( 454 lldbplatformutil.getDarwinOSTriples(), 455 bugnumber, 456 compilers) 457 458 459def expectedFlakeyFreeBSD(bugnumber=None, compilers=None): 460 return expectedFlakeyOS(['freebsd'], bugnumber, compilers) 461 462 463def expectedFlakeyLinux(bugnumber=None, compilers=None): 464 return expectedFlakeyOS(['linux'], bugnumber, compilers) 465 466 467def expectedFlakeyNetBSD(bugnumber=None, compilers=None): 468 return expectedFlakeyOS(['netbsd'], bugnumber, compilers) 469 470 471def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None): 472 if compiler_version is None: 473 compiler_version = ['=', None] 474 475 def fn(self): 476 return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version) 477 return expectedFlakey(fn, bugnumber) 478 479# @expectedFlakeyClang('bugnumber', ['<=', '3.4']) 480 481 482def expectedFlakeyClang(bugnumber=None, compiler_version=None): 483 return expectedFlakeyCompiler('clang', compiler_version, bugnumber) 484 485# @expectedFlakeyGcc('bugnumber', ['<=', '3.4']) 486 487 488def expectedFlakeyGcc(bugnumber=None, compiler_version=None): 489 return expectedFlakeyCompiler('gcc', compiler_version, bugnumber) 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 500 501def skipIfRemote(func): 502 """Decorate the item to skip tests if testing remotely.""" 503 def is_remote(): 504 return "skip on remote platform" if lldb.remote_platform else None 505 return skipTestIfFn(is_remote)(func) 506 507 508def skipIfRemoteDueToDeadlock(func): 509 """Decorate the item to skip tests if testing remotely due to the test deadlocking.""" 510 def is_remote(): 511 return "skip on remote platform (deadlocks)" if lldb.remote_platform else None 512 return skipTestIfFn(is_remote)(func) 513 514 515def skipIfNoSBHeaders(func): 516 """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers.""" 517 def are_sb_headers_missing(): 518 if lldbplatformutil.getHostPlatform() == 'darwin': 519 header = os.path.join( 520 os.environ["LLDB_LIB_DIR"], 521 'LLDB.framework', 522 'Versions', 523 'Current', 524 'Headers', 525 'LLDB.h') 526 if os.path.exists(header): 527 return None 528 529 header = os.path.join( 530 os.environ["LLDB_SRC"], 531 "include", 532 "lldb", 533 "API", 534 "LLDB.h") 535 if not os.path.exists(header): 536 return "skip because LLDB.h header not found" 537 return None 538 539 return skipTestIfFn(are_sb_headers_missing)(func) 540 541 542def skipIfiOSSimulator(func): 543 """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" 544 def is_ios_simulator(): 545 return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None 546 return skipTestIfFn(is_ios_simulator)(func) 547 548 549def skipIfFreeBSD(func): 550 """Decorate the item to skip tests that should be skipped on FreeBSD.""" 551 return skipIfPlatform(["freebsd"])(func) 552 553 554def skipIfNetBSD(func): 555 """Decorate the item to skip tests that should be skipped on NetBSD.""" 556 return skipIfPlatform(["netbsd"])(func) 557 558 559def skipIfDarwin(func): 560 """Decorate the item to skip tests that should be skipped on Darwin.""" 561 return skipIfPlatform( 562 lldbplatform.translate( 563 lldbplatform.darwin_all))(func) 564 565 566def skipIfLinux(func): 567 """Decorate the item to skip tests that should be skipped on Linux.""" 568 return skipIfPlatform(["linux"])(func) 569 570 571def skipIfWindows(func): 572 """Decorate the item to skip tests that should be skipped on Windows.""" 573 return skipIfPlatform(["windows"])(func) 574 575 576def skipUnlessWindows(func): 577 """Decorate the item to skip tests that should be skipped on any non-Windows platform.""" 578 return skipUnlessPlatform(["windows"])(func) 579 580 581def skipUnlessDarwin(func): 582 """Decorate the item to skip tests that should be skipped on any non Darwin platform.""" 583 return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func) 584 585 586def skipUnlessGoInstalled(func): 587 """Decorate the item to skip tests when no Go compiler is available.""" 588 589 def is_go_missing(self): 590 compiler = self.getGoCompilerVersion() 591 if not compiler: 592 return "skipping because go compiler not found" 593 match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler) 594 if not match_version: 595 # Couldn't determine version. 596 return "skipping because go version could not be parsed out of {}".format( 597 compiler) 598 else: 599 min_strict_version = StrictVersion("1.4.0") 600 compiler_strict_version = StrictVersion(match_version.group(1)) 601 if compiler_strict_version < min_strict_version: 602 return "skipping because available version ({}) does not meet minimum required version ({})".format( 603 compiler_strict_version, min_strict_version) 604 return None 605 return skipTestIfFn(is_go_missing)(func) 606 607 608def skipIfHostIncompatibleWithRemote(func): 609 """Decorate the item to skip tests if binaries built on this host are incompatible.""" 610 611 def is_host_incompatible_with_remote(self): 612 host_arch = self.getLldbArchitecture() 613 host_platform = lldbplatformutil.getHostPlatform() 614 target_arch = self.getArchitecture() 615 target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform() 616 if not (target_arch == 'x86_64' and host_arch == 617 'i386') and host_arch != target_arch: 618 return "skipping because target %s is not compatible with host architecture %s" % ( 619 target_arch, host_arch) 620 if target_platform != host_platform: 621 return "skipping because target is %s but host is %s" % ( 622 target_platform, host_platform) 623 if lldbplatformutil.match_android_device(target_arch): 624 return "skipping because target is android" 625 return None 626 return skipTestIfFn(is_host_incompatible_with_remote)(func) 627 628 629def skipIfPlatform(oslist): 630 """Decorate the item to skip tests if running on one of the listed platforms.""" 631 # This decorator cannot be ported to `skipIf` yet because it is used on entire 632 # classes, which `skipIf` explicitly forbids. 633 return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist, 634 "skip on %s" % (", ".join(oslist))) 635 636 637def skipUnlessPlatform(oslist): 638 """Decorate the item to skip tests unless running on one of the listed platforms.""" 639 # This decorator cannot be ported to `skipIf` yet because it is used on entire 640 # classes, which `skipIf` explicitly forbids. 641 return unittest2.skipUnless(lldbplatformutil.getPlatform() in oslist, 642 "requires one of %s" % (", ".join(oslist))) 643 644 645def skipIfTargetAndroid(api_levels=None, archs=None): 646 """Decorator to skip tests when the target is Android. 647 648 Arguments: 649 api_levels - The API levels for which the test should be skipped. If 650 it is None, then the test will be skipped for all API levels. 651 arch - A sequence of architecture names specifying the architectures 652 for which a test is skipped. None means all architectures. 653 """ 654 return skipTestIfFn( 655 _skip_for_android( 656 "skipping for android", 657 api_levels, 658 archs)) 659 660 661def skipUnlessThreadSanitizer(func): 662 """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" 663 664 def is_compiler_clang_with_thread_sanitizer(self): 665 compiler_path = self.getCompiler() 666 compiler = os.path.basename(compiler_path) 667 if not compiler.startswith("clang"): 668 return "Test requires clang as compiler" 669 if lldbplatformutil.getPlatform() == 'windows': 670 return "TSAN tests not compatible with 'windows'" 671 # rdar://28659145 - TSAN tests don't look like they're supported on i386 672 if self.getArchitecture() == 'i386' and platform.system() == 'Darwin': 673 return "TSAN tests not compatible with i386 targets" 674 f = tempfile.NamedTemporaryFile() 675 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name) 676 if os.popen(cmd).close() is not None: 677 return None # The compiler cannot compile at all, let's *not* skip the test 678 cmd = "echo 'int main() {}' | %s -fsanitize=thread -x c -o %s -" % (compiler_path, f.name) 679 if os.popen(cmd).close() is not None: 680 return "Compiler cannot compile with -fsanitize=thread" 681 return None 682 return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func) 683 684def skipUnlessAddressSanitizer(func): 685 """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" 686 687 def is_compiler_with_address_sanitizer(self): 688 compiler_path = self.getCompiler() 689 compiler = os.path.basename(compiler_path) 690 f = tempfile.NamedTemporaryFile() 691 if lldbplatformutil.getPlatform() == 'windows': 692 return "ASAN tests not compatible with 'windows'" 693 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name) 694 if os.popen(cmd).close() is not None: 695 return None # The compiler cannot compile at all, let's *not* skip the test 696 cmd = "echo 'int main() {}' | %s -fsanitize=address -x c -o %s -" % (compiler_path, f.name) 697 if os.popen(cmd).close() is not None: 698 return "Compiler cannot compile with -fsanitize=address" 699 return None 700 return skipTestIfFn(is_compiler_with_address_sanitizer)(func) 701