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