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