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