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 inspect 8import os 9import platform 10import re 11import sys 12import tempfile 13 14# Third-party modules 15import six 16import unittest2 17 18# LLDB modules 19import use_lldb_suite 20 21import lldb 22from . import configuration 23from . import test_categories 24from lldbsuite.test_event.event_builder import EventBuilder 25from lldbsuite.support import funcutils 26from lldbsuite.test import lldbplatform 27from lldbsuite.test import lldbplatformutil 28 29 30class DecorateMode: 31 Skip, Xfail = range(2) 32 33 34# You can use no_match to reverse the test of the conditional that is used to match keyword 35# arguments in the skip / xfail decorators. If oslist=["windows", "linux"] skips windows 36# and linux, oslist=no_match(["windows", "linux"]) skips *unless* windows 37# or linux. 38class no_match: 39 40 def __init__(self, item): 41 self.item = item 42 43 44def _check_expected_version(comparison, expected, actual): 45 def fn_leq(x, y): return x <= y 46 47 def fn_less(x, y): return x < y 48 49 def fn_geq(x, y): return x >= y 50 51 def fn_greater(x, y): return x > y 52 53 def fn_eq(x, y): return x == y 54 55 def fn_neq(x, y): return x != y 56 57 op_lookup = { 58 "==": fn_eq, 59 "=": fn_eq, 60 "!=": fn_neq, 61 "<>": fn_neq, 62 ">": fn_greater, 63 "<": fn_less, 64 ">=": fn_geq, 65 "<=": fn_leq 66 } 67 expected_str = '.'.join([str(x) for x in expected]) 68 actual_str = '.'.join([str(x) for x in actual]) 69 70 return op_lookup[comparison]( 71 LooseVersion(actual_str), 72 LooseVersion(expected_str)) 73 74 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 expectedFailure(expected_fn, bugnumber=None): 91 def expectedFailure_impl(func): 92 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 93 raise Exception( 94 "Decorator can only be used to decorate a test method") 95 96 @wraps(func) 97 def wrapper(*args, **kwargs): 98 self = args[0] 99 if funcutils.requires_self(expected_fn): 100 xfail_reason = expected_fn(self) 101 else: 102 xfail_reason = expected_fn() 103 if xfail_reason is not None: 104 if configuration.results_formatter_object is not None: 105 # Mark this test as expected to fail. 106 configuration.results_formatter_object.handle_event( 107 EventBuilder.event_for_mark_test_expected_failure(self)) 108 xfail_func = unittest2.expectedFailure(func) 109 xfail_func(*args, **kwargs) 110 else: 111 func(*args, **kwargs) 112 return wrapper 113 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) 114 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called 115 # the first way, the first argument will be the actual function because decorators are 116 # weird like that. So this is basically a check that says "which syntax was the original 117 # function decorated with?" 118 if six.callable(bugnumber): 119 return expectedFailure_impl(bugnumber) 120 else: 121 return expectedFailure_impl 122 123 124def skipTestIfFn(expected_fn, bugnumber=None): 125 def skipTestIfFn_impl(func): 126 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 127 raise Exception( 128 "@skipTestIfFn can only be used to decorate a test method") 129 130 @wraps(func) 131 def wrapper(*args, **kwargs): 132 self = args[0] 133 if funcutils.requires_self(expected_fn): 134 reason = expected_fn(self) 135 else: 136 reason = expected_fn() 137 138 if reason is not None: 139 self.skipTest(reason) 140 else: 141 func(*args, **kwargs) 142 return wrapper 143 144 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) 145 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called 146 # the first way, the first argument will be the actual function because decorators are 147 # weird like that. So this is basically a check that says "how was the 148 # decorator used" 149 if six.callable(bugnumber): 150 return skipTestIfFn_impl(bugnumber) 151 else: 152 return skipTestIfFn_impl 153 154 155def _decorateTest(mode, 156 bugnumber=None, oslist=None, hostoslist=None, 157 compiler=None, compiler_version=None, 158 archs=None, triple=None, 159 debug_info=None, 160 swig_version=None, py_version=None, 161 macos_version=None, 162 remote=None): 163 def fn(self): 164 skip_for_os = _match_decorator_property( 165 lldbplatform.translate(oslist), self.getPlatform()) 166 skip_for_hostos = _match_decorator_property( 167 lldbplatform.translate(hostoslist), 168 lldbplatformutil.getHostPlatform()) 169 skip_for_compiler = _match_decorator_property( 170 compiler, self.getCompiler()) and self.expectedCompilerVersion(compiler_version) 171 skip_for_arch = _match_decorator_property( 172 archs, self.getArchitecture()) 173 skip_for_debug_info = _match_decorator_property( 174 debug_info, self.getDebugInfo()) 175 skip_for_triple = _match_decorator_property( 176 triple, lldb.DBG.GetSelectedPlatform().GetTriple()) 177 skip_for_remote = _match_decorator_property( 178 remote, lldb.remote_platform is not None) 179 180 skip_for_swig_version = ( 181 swig_version is None) or ( 182 not hasattr( 183 lldb, 184 'swig_version')) or ( 185 _check_expected_version( 186 swig_version[0], 187 swig_version[1], 188 lldb.swig_version)) 189 skip_for_py_version = ( 190 py_version is None) or _check_expected_version( 191 py_version[0], py_version[1], sys.version_info) 192 skip_for_macos_version = (macos_version is None) or ( 193 _check_expected_version( 194 macos_version[0], 195 macos_version[1], 196 platform.mac_ver()[0])) 197 198 # For the test to be skipped, all specified (e.g. not None) parameters must be True. 199 # An unspecified parameter means "any", so those are marked skip by default. And we skip 200 # the final test if all conditions are True. 201 conditions = [(oslist, skip_for_os, "target o/s"), 202 (hostoslist, skip_for_hostos, "host o/s"), 203 (compiler, skip_for_compiler, "compiler or version"), 204 (archs, skip_for_arch, "architecture"), 205 (debug_info, skip_for_debug_info, "debug info format"), 206 (triple, skip_for_triple, "target triple"), 207 (swig_version, skip_for_swig_version, "swig version"), 208 (py_version, skip_for_py_version, "python version"), 209 (macos_version, skip_for_macos_version, "macOS version"), 210 (remote, skip_for_remote, "platform locality (remote/local)")] 211 reasons = [] 212 final_skip_result = True 213 for this_condition in conditions: 214 final_skip_result = final_skip_result and this_condition[1] 215 if this_condition[0] is not None and this_condition[1]: 216 reasons.append(this_condition[2]) 217 reason_str = None 218 if final_skip_result: 219 mode_str = { 220 DecorateMode.Skip: "skipping", 221 DecorateMode.Xfail: "xfailing"}[mode] 222 if len(reasons) > 0: 223 reason_str = ",".join(reasons) 224 reason_str = "{} due to the following parameter(s): {}".format( 225 mode_str, reason_str) 226 else: 227 reason_str = "{} unconditionally" 228 if bugnumber is not None and not six.callable(bugnumber): 229 reason_str = reason_str + " [" + str(bugnumber) + "]" 230 return reason_str 231 232 if mode == DecorateMode.Skip: 233 return skipTestIfFn(fn, bugnumber) 234 elif mode == DecorateMode.Xfail: 235 return expectedFailure(fn, bugnumber) 236 else: 237 return None 238 239# provide a function to xfail on defined oslist, compiler version, and archs 240# if none is specified for any argument, that argument won't be checked and thus means for all 241# for example, 242# @expectedFailureAll, xfail for all platform/compiler/arch, 243# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture 244# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386 245 246 247def expectedFailureAll(bugnumber=None, 248 oslist=None, hostoslist=None, 249 compiler=None, compiler_version=None, 250 archs=None, triple=None, 251 debug_info=None, 252 swig_version=None, py_version=None, 253 macos_version=None, 254 remote=None): 255 return _decorateTest(DecorateMode.Xfail, 256 bugnumber=bugnumber, 257 oslist=oslist, hostoslist=hostoslist, 258 compiler=compiler, compiler_version=compiler_version, 259 archs=archs, triple=triple, 260 debug_info=debug_info, 261 swig_version=swig_version, py_version=py_version, 262 macos_version=None, 263 remote=remote) 264 265 266# provide a function to skip on defined oslist, compiler version, and archs 267# if none is specified for any argument, that argument won't be checked and thus means for all 268# for example, 269# @skipIf, skip for all platform/compiler/arch, 270# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture 271# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 272def skipIf(bugnumber=None, 273 oslist=None, hostoslist=None, 274 compiler=None, compiler_version=None, 275 archs=None, triple=None, 276 debug_info=None, 277 swig_version=None, py_version=None, 278 macos_version=None, 279 remote=None): 280 return _decorateTest(DecorateMode.Skip, 281 bugnumber=bugnumber, 282 oslist=oslist, hostoslist=hostoslist, 283 compiler=compiler, compiler_version=compiler_version, 284 archs=archs, triple=triple, 285 debug_info=debug_info, 286 swig_version=swig_version, py_version=py_version, 287 macos_version=macos_version, 288 remote=remote) 289 290 291def _skip_for_android(reason, api_levels, archs): 292 def impl(obj): 293 result = lldbplatformutil.match_android_device( 294 obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels) 295 return reason if result else None 296 return impl 297 298 299def add_test_categories(cat): 300 """Add test categories to a TestCase method""" 301 cat = test_categories.validate(cat, True) 302 303 def impl(func): 304 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 305 raise Exception( 306 "@add_test_categories can only be used to decorate a test method") 307 308 # Update or set the categories attribute. For instance methods, the 309 # attribute must be set on the actual function. 310 func_for_attr = func 311 if inspect.ismethod(func_for_attr): 312 func_for_attr = func.__func__ 313 if hasattr(func_for_attr, "categories"): 314 cat.extend(func_for_attr.categories) 315 setattr(func_for_attr, "categories", cat) 316 317 return func 318 319 return impl 320 321 322def benchmarks_test(func): 323 """Decorate the item as a benchmarks test.""" 324 def should_skip_benchmarks_test(): 325 return "benchmarks test" 326 327 # Mark this function as such to separate them from the regular tests. 328 result = skipTestIfFn(should_skip_benchmarks_test)(func) 329 result.__benchmarks_test__ = True 330 return result 331 332 333def no_debug_info_test(func): 334 """Decorate the item as a test what don't use any debug info. If this annotation is specified 335 then the test runner won't generate a separate test for each debug info format. """ 336 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 337 raise Exception( 338 "@no_debug_info_test can only be used to decorate a test method") 339 340 @wraps(func) 341 def wrapper(self, *args, **kwargs): 342 return func(self, *args, **kwargs) 343 344 # Mark this function as such to separate them from the regular tests. 345 wrapper.__no_debug_info_test__ = True 346 return wrapper 347 348 349def debugserver_test(func): 350 """Decorate the item as a debugserver test.""" 351 def should_skip_debugserver_test(): 352 return "debugserver tests" if configuration.dont_do_debugserver_test else None 353 return skipTestIfFn(should_skip_debugserver_test)(func) 354 355 356def llgs_test(func): 357 """Decorate the item as a lldb-server test.""" 358 def should_skip_llgs_tests(): 359 return "llgs tests" if configuration.dont_do_llgs_test else None 360 return skipTestIfFn(should_skip_llgs_tests)(func) 361 362 363def not_remote_testsuite_ready(func): 364 """Decorate the item as a test which is not ready yet for remote testsuite.""" 365 def is_remote(): 366 return "Not ready for remote testsuite" if lldb.remote_platform else None 367 return skipTestIfFn(is_remote)(func) 368 369 370def expectedFailureOS( 371 oslist, 372 bugnumber=None, 373 compilers=None, 374 debug_info=None, 375 archs=None): 376 return expectedFailureAll( 377 oslist=oslist, 378 bugnumber=bugnumber, 379 compiler=compilers, 380 archs=archs, 381 debug_info=debug_info) 382 383 384def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None): 385 # For legacy reasons, we support both "darwin" and "macosx" as OS X 386 # triples. 387 return expectedFailureOS( 388 lldbplatform.darwin_all, 389 bugnumber, 390 compilers, 391 debug_info=debug_info) 392 393 394def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None): 395 """ Mark a test as xfail for Android. 396 397 Arguments: 398 bugnumber - The LLVM pr associated with the problem. 399 api_levels - A sequence of numbers specifying the Android API levels 400 for which a test is expected to fail. None means all API level. 401 arch - A sequence of architecture names specifying the architectures 402 for which a test is expected to fail. None means all architectures. 403 """ 404 return expectedFailure( 405 _skip_for_android( 406 "xfailing on android", 407 api_levels, 408 archs), 409 bugnumber) 410 411# Flakey tests get two chances to run. If they fail the first time round, the result formatter 412# makes sure it is run one more time. 413 414 415def expectedFlakey(expected_fn, bugnumber=None): 416 def expectedFailure_impl(func): 417 @wraps(func) 418 def wrapper(*args, **kwargs): 419 self = args[0] 420 if expected_fn(self): 421 # Send event marking test as explicitly eligible for rerunning. 422 if configuration.results_formatter_object is not None: 423 # Mark this test as rerunnable. 424 configuration.results_formatter_object.handle_event( 425 EventBuilder.event_for_mark_test_rerun_eligible(self)) 426 func(*args, **kwargs) 427 return wrapper 428 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) 429 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called 430 # the first way, the first argument will be the actual function because decorators are 431 # weird like that. So this is basically a check that says "which syntax was the original 432 # function decorated with?" 433 if six.callable(bugnumber): 434 return expectedFailure_impl(bugnumber) 435 else: 436 return expectedFailure_impl 437 438 439def expectedFlakeyDwarf(bugnumber=None): 440 def fn(self): 441 return self.getDebugInfo() == "dwarf" 442 return expectedFlakey(fn, bugnumber) 443 444 445def expectedFlakeyDsym(bugnumber=None): 446 def fn(self): 447 return self.getDebugInfo() == "dwarf" 448 return expectedFlakey(fn, bugnumber) 449 450 451def expectedFlakeyOS(oslist, bugnumber=None, compilers=None): 452 def fn(self): 453 return (self.getPlatform() in oslist and 454 self.expectedCompiler(compilers)) 455 return expectedFlakey(fn, bugnumber) 456 457 458def expectedFlakeyDarwin(bugnumber=None, compilers=None): 459 # For legacy reasons, we support both "darwin" and "macosx" as OS X 460 # triples. 461 return expectedFlakeyOS( 462 lldbplatformutil.getDarwinOSTriples(), 463 bugnumber, 464 compilers) 465 466 467def expectedFlakeyFreeBSD(bugnumber=None, compilers=None): 468 return expectedFlakeyOS(['freebsd'], bugnumber, compilers) 469 470 471def expectedFlakeyLinux(bugnumber=None, compilers=None): 472 return expectedFlakeyOS(['linux'], bugnumber, compilers) 473 474 475def expectedFlakeyNetBSD(bugnumber=None, compilers=None): 476 return expectedFlakeyOS(['netbsd'], bugnumber, compilers) 477 478 479def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None): 480 if compiler_version is None: 481 compiler_version = ['=', None] 482 483 def fn(self): 484 return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version) 485 return expectedFlakey(fn, bugnumber) 486 487# @expectedFlakeyClang('bugnumber', ['<=', '3.4']) 488 489 490def expectedFlakeyClang(bugnumber=None, compiler_version=None): 491 return expectedFlakeyCompiler('clang', compiler_version, bugnumber) 492 493# @expectedFlakeyGcc('bugnumber', ['<=', '3.4']) 494 495 496def expectedFlakeyGcc(bugnumber=None, compiler_version=None): 497 return expectedFlakeyCompiler('gcc', compiler_version, bugnumber) 498 499 500def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None): 501 return expectedFlakey( 502 _skip_for_android( 503 "flakey on android", 504 api_levels, 505 archs), 506 bugnumber) 507 508 509def skipIfRemote(func): 510 """Decorate the item to skip tests if testing remotely.""" 511 def is_remote(): 512 return "skip on remote platform" if lldb.remote_platform else None 513 return skipTestIfFn(is_remote)(func) 514 515 516def skipIfNoSBHeaders(func): 517 """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers.""" 518 def are_sb_headers_missing(): 519 if lldbplatformutil.getHostPlatform() == 'darwin': 520 header = os.path.join( 521 os.environ["LLDB_LIB_DIR"], 522 'LLDB.framework', 523 'Versions', 524 'Current', 525 'Headers', 526 'LLDB.h') 527 if os.path.exists(header): 528 return None 529 530 header = os.path.join( 531 os.environ["LLDB_SRC"], 532 "include", 533 "lldb", 534 "API", 535 "LLDB.h") 536 if not os.path.exists(header): 537 return "skip because LLDB.h header not found" 538 return None 539 540 return skipTestIfFn(are_sb_headers_missing)(func) 541 542 543def skipIfiOSSimulator(func): 544 """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" 545 def is_ios_simulator(): 546 return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None 547 return skipTestIfFn(is_ios_simulator)(func) 548 549def skipIfiOS(func): 550 return skipIfPlatform(["ios"])(func) 551 552def skipIftvOS(func): 553 return skipIfPlatform(["tvos"])(func) 554 555def skipIfwatchOS(func): 556 return skipIfPlatform(["watchos"])(func) 557 558def skipIfbridgeOS(func): 559 return skipIfPlatform(["bridgeos"])(func) 560 561def skipIfDarwinEmbedded(func): 562 """Decorate the item to skip tests that should be skipped on Darwin armv7/arm64 targets.""" 563 return skipIfPlatform( 564 lldbplatform.translate( 565 lldbplatform.darwin_embedded))(func) 566 567def skipIfFreeBSD(func): 568 """Decorate the item to skip tests that should be skipped on FreeBSD.""" 569 return skipIfPlatform(["freebsd"])(func) 570 571 572def skipIfNetBSD(func): 573 """Decorate the item to skip tests that should be skipped on NetBSD.""" 574 return skipIfPlatform(["netbsd"])(func) 575 576 577def skipIfDarwin(func): 578 """Decorate the item to skip tests that should be skipped on Darwin.""" 579 return skipIfPlatform( 580 lldbplatform.translate( 581 lldbplatform.darwin_all))(func) 582 583 584def skipIfLinux(func): 585 """Decorate the item to skip tests that should be skipped on Linux.""" 586 return skipIfPlatform(["linux"])(func) 587 588 589def skipIfWindows(func): 590 """Decorate the item to skip tests that should be skipped on Windows.""" 591 return skipIfPlatform(["windows"])(func) 592 593 594def skipUnlessWindows(func): 595 """Decorate the item to skip tests that should be skipped on any non-Windows platform.""" 596 return skipUnlessPlatform(["windows"])(func) 597 598 599def skipUnlessDarwin(func): 600 """Decorate the item to skip tests that should be skipped on any non Darwin platform.""" 601 return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func) 602 603 604def skipUnlessGoInstalled(func): 605 """Decorate the item to skip tests when no Go compiler is available.""" 606 607 def is_go_missing(self): 608 compiler = self.getGoCompilerVersion() 609 if not compiler: 610 return "skipping because go compiler not found" 611 match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler) 612 if not match_version: 613 # Couldn't determine version. 614 return "skipping because go version could not be parsed out of {}".format( 615 compiler) 616 else: 617 min_strict_version = StrictVersion("1.4.0") 618 compiler_strict_version = StrictVersion(match_version.group(1)) 619 if compiler_strict_version < min_strict_version: 620 return "skipping because available version ({}) does not meet minimum required version ({})".format( 621 compiler_strict_version, min_strict_version) 622 return None 623 return skipTestIfFn(is_go_missing)(func) 624 625 626def skipIfHostIncompatibleWithRemote(func): 627 """Decorate the item to skip tests if binaries built on this host are incompatible.""" 628 629 def is_host_incompatible_with_remote(self): 630 host_arch = self.getLldbArchitecture() 631 host_platform = lldbplatformutil.getHostPlatform() 632 target_arch = self.getArchitecture() 633 target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform() 634 if not (target_arch == 'x86_64' and host_arch == 635 'i386') and host_arch != target_arch: 636 return "skipping because target %s is not compatible with host architecture %s" % ( 637 target_arch, host_arch) 638 if target_platform != host_platform: 639 return "skipping because target is %s but host is %s" % ( 640 target_platform, host_platform) 641 if lldbplatformutil.match_android_device(target_arch): 642 return "skipping because target is android" 643 return None 644 return skipTestIfFn(is_host_incompatible_with_remote)(func) 645 646 647def skipIfPlatform(oslist): 648 """Decorate the item to skip tests if running on one of the listed platforms.""" 649 # This decorator cannot be ported to `skipIf` yet because it is used on entire 650 # classes, which `skipIf` explicitly forbids. 651 return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist, 652 "skip on %s" % (", ".join(oslist))) 653 654 655def skipUnlessPlatform(oslist): 656 """Decorate the item to skip tests unless running on one of the listed platforms.""" 657 # This decorator cannot be ported to `skipIf` yet because it is used on entire 658 # classes, which `skipIf` explicitly forbids. 659 return unittest2.skipUnless(lldbplatformutil.getPlatform() in oslist, 660 "requires one of %s" % (", ".join(oslist))) 661 662 663def skipIfTargetAndroid(api_levels=None, archs=None): 664 """Decorator to skip tests when the target is Android. 665 666 Arguments: 667 api_levels - The API levels for which the test should be skipped. If 668 it is None, then the test will be skipped for all API levels. 669 arch - A sequence of architecture names specifying the architectures 670 for which a test is skipped. None means all architectures. 671 """ 672 return skipTestIfFn( 673 _skip_for_android( 674 "skipping for android", 675 api_levels, 676 archs)) 677 678 679def skipUnlessThreadSanitizer(func): 680 """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" 681 682 def is_compiler_clang_with_thread_sanitizer(self): 683 compiler_path = self.getCompiler() 684 compiler = os.path.basename(compiler_path) 685 if not compiler.startswith("clang"): 686 return "Test requires clang as compiler" 687 if lldbplatformutil.getPlatform() == 'windows': 688 return "TSAN tests not compatible with 'windows'" 689 # rdar://28659145 - TSAN tests don't look like they're supported on i386 690 if self.getArchitecture() == 'i386' and platform.system() == 'Darwin': 691 return "TSAN tests not compatible with i386 targets" 692 f = tempfile.NamedTemporaryFile() 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=thread -x c -o %s -" % (compiler_path, f.name) 697 if os.popen(cmd).close() is not None: 698 return "Compiler cannot compile with -fsanitize=thread" 699 return None 700 return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func) 701 702def skipUnlessUndefinedBehaviorSanitizer(func): 703 """Decorate the item to skip test unless -fsanitize=undefined is supported.""" 704 705 def is_compiler_clang_with_ubsan(self): 706 # Write out a temp file which exhibits UB. 707 inputf = tempfile.NamedTemporaryFile(suffix='.c') 708 inputf.write('int main() { int x = 0; return x / x; }\n') 709 inputf.flush() 710 711 # We need to write out the object into a named temp file for inspection. 712 outputf = tempfile.NamedTemporaryFile() 713 714 # Try to compile with ubsan turned on. 715 cmd = '%s -fsanitize=undefined %s -o %s' % (self.getCompiler(), inputf.name, outputf.name) 716 if os.popen(cmd).close() is not None: 717 return "Compiler cannot compile with -fsanitize=undefined" 718 719 # Check that we actually see ubsan instrumentation in the binary. 720 cmd = 'nm %s' % outputf.name 721 with os.popen(cmd) as nm_output: 722 if '___ubsan_handle_divrem_overflow' not in nm_output.read(): 723 return "Division by zero instrumentation is missing" 724 725 # Find the ubsan dylib. 726 # FIXME: This check should go away once compiler-rt gains support for __ubsan_on_report. 727 cmd = '%s -fsanitize=undefined -x c - -o - -### 2>&1' % self.getCompiler() 728 with os.popen(cmd) as cc_output: 729 driver_jobs = cc_output.read() 730 m = re.search(r'"([^"]+libclang_rt.ubsan_osx_dynamic.dylib)"', driver_jobs) 731 if not m: 732 return "Could not find the ubsan dylib used by the driver" 733 ubsan_dylib = m.group(1) 734 735 # Check that the ubsan dylib has special monitor hooks. 736 cmd = 'nm -gU %s' % ubsan_dylib 737 with os.popen(cmd) as nm_output: 738 syms = nm_output.read() 739 if '___ubsan_on_report' not in syms: 740 return "Missing ___ubsan_on_report" 741 if '___ubsan_get_current_report_data' not in syms: 742 return "Missing ___ubsan_get_current_report_data" 743 744 # OK, this dylib + compiler works for us. 745 return None 746 747 return skipTestIfFn(is_compiler_clang_with_ubsan)(func) 748 749def skipUnlessAddressSanitizer(func): 750 """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" 751 752 def is_compiler_with_address_sanitizer(self): 753 compiler_path = self.getCompiler() 754 compiler = os.path.basename(compiler_path) 755 f = tempfile.NamedTemporaryFile() 756 if lldbplatformutil.getPlatform() == 'windows': 757 return "ASAN tests not compatible with 'windows'" 758 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name) 759 if os.popen(cmd).close() is not None: 760 return None # The compiler cannot compile at all, let's *not* skip the test 761 cmd = "echo 'int main() {}' | %s -fsanitize=address -x c -o %s -" % (compiler_path, f.name) 762 if os.popen(cmd).close() is not None: 763 return "Compiler cannot compile with -fsanitize=address" 764 return None 765 return skipTestIfFn(is_compiler_with_address_sanitizer)(func) 766