1from __future__ import absolute_import 2from __future__ import print_function 3 4# System modules 5from distutils.version import LooseVersion 6from functools import wraps 7import os 8import platform 9import re 10import sys 11import tempfile 12import subprocess 13 14# Third-party modules 15import six 16import unittest2 17 18# LLDB modules 19import lldb 20from . import configuration 21from . import test_categories 22from . import lldbtest_config 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 74_re_pattern_type = type(re.compile('')) 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, dwarf_version=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 (platform.mac_ver()[0] != "") and (_check_expected_version( 194 macos_version[0], 195 macos_version[1], 196 platform.mac_ver()[0]))) 197 skip_for_dwarf_version = (dwarf_version is None) or ( 198 _check_expected_version(dwarf_version[0], dwarf_version[1], 199 self.getDwarfVersion())) 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 (dwarf_version, skip_for_dwarf_version, "dwarf version")] 215 reasons = [] 216 final_skip_result = True 217 for this_condition in conditions: 218 final_skip_result = final_skip_result and this_condition[1] 219 if this_condition[0] is not None and this_condition[1]: 220 reasons.append(this_condition[2]) 221 reason_str = None 222 if final_skip_result: 223 mode_str = { 224 DecorateMode.Skip: "skipping", 225 DecorateMode.Xfail: "xfailing"}[mode] 226 if len(reasons) > 0: 227 reason_str = ",".join(reasons) 228 reason_str = "{} due to the following parameter(s): {}".format( 229 mode_str, reason_str) 230 else: 231 reason_str = "{} unconditionally" 232 if bugnumber is not None and not six.callable(bugnumber): 233 reason_str = reason_str + " [" + str(bugnumber) + "]" 234 return reason_str 235 236 if mode == DecorateMode.Skip: 237 return skipTestIfFn(fn, bugnumber) 238 elif mode == DecorateMode.Xfail: 239 return expectedFailure(fn, bugnumber) 240 else: 241 return None 242 243# provide a function to xfail on defined oslist, compiler version, and archs 244# if none is specified for any argument, that argument won't be checked and thus means for all 245# for example, 246# @expectedFailureAll, xfail for all platform/compiler/arch, 247# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture 248# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386 249 250 251def expectedFailureAll(bugnumber=None, 252 oslist=None, hostoslist=None, 253 compiler=None, compiler_version=None, 254 archs=None, triple=None, 255 debug_info=None, 256 swig_version=None, py_version=None, 257 macos_version=None, 258 remote=None, dwarf_version=None): 259 return _decorateTest(DecorateMode.Xfail, 260 bugnumber=bugnumber, 261 oslist=oslist, hostoslist=hostoslist, 262 compiler=compiler, compiler_version=compiler_version, 263 archs=archs, triple=triple, 264 debug_info=debug_info, 265 swig_version=swig_version, py_version=py_version, 266 macos_version=None, 267 remote=remote,dwarf_version=dwarf_version) 268 269 270# provide a function to skip on defined oslist, compiler version, and archs 271# if none is specified for any argument, that argument won't be checked and thus means for all 272# for example, 273# @skipIf, skip for all platform/compiler/arch, 274# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture 275# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 276def skipIf(bugnumber=None, 277 oslist=None, hostoslist=None, 278 compiler=None, compiler_version=None, 279 archs=None, triple=None, 280 debug_info=None, 281 swig_version=None, py_version=None, 282 macos_version=None, 283 remote=None, dwarf_version=None): 284 return _decorateTest(DecorateMode.Skip, 285 bugnumber=bugnumber, 286 oslist=oslist, hostoslist=hostoslist, 287 compiler=compiler, compiler_version=compiler_version, 288 archs=archs, triple=triple, 289 debug_info=debug_info, 290 swig_version=swig_version, py_version=py_version, 291 macos_version=macos_version, 292 remote=remote, dwarf_version=dwarf_version) 293 294 295def _skip_for_android(reason, api_levels, archs): 296 def impl(obj): 297 result = lldbplatformutil.match_android_device( 298 obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels) 299 return reason if result else None 300 return impl 301 302 303def add_test_categories(cat): 304 """Add test categories to a TestCase method""" 305 cat = test_categories.validate(cat, True) 306 307 def impl(func): 308 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 309 raise Exception( 310 "@add_test_categories can only be used to decorate a test method") 311 try: 312 if hasattr(func, "categories"): 313 cat.extend(func.categories) 314 setattr(func, "categories", cat) 315 except AttributeError: 316 raise Exception('Cannot assign categories to inline tests.') 317 318 return func 319 320 return impl 321 322 323def benchmarks_test(func): 324 """Decorate the item as a benchmarks test.""" 325 def should_skip_benchmarks_test(): 326 return "benchmarks test" 327 328 # Mark this function as such to separate them from the regular tests. 329 result = skipTestIfFn(should_skip_benchmarks_test)(func) 330 result.__benchmarks_test__ = True 331 return result 332 333 334def no_debug_info_test(func): 335 """Decorate the item as a test what don't use any debug info. If this annotation is specified 336 then the test runner won't generate a separate test for each debug info format. """ 337 if isinstance(func, type) and issubclass(func, unittest2.TestCase): 338 raise Exception( 339 "@no_debug_info_test can only be used to decorate a test method") 340 341 @wraps(func) 342 def wrapper(self, *args, **kwargs): 343 return func(self, *args, **kwargs) 344 345 # Mark this function as such to separate them from the regular tests. 346 wrapper.__no_debug_info_test__ = True 347 return wrapper 348 349def apple_simulator_test(platform): 350 """ 351 Decorate the test as a test requiring a simulator for a specific platform. 352 353 Consider that a simulator is available if you have the corresponding SDK installed. 354 The SDK identifiers for simulators are iphonesimulator, appletvsimulator, watchsimulator 355 """ 356 def should_skip_simulator_test(): 357 if lldbplatformutil.getHostPlatform() != 'darwin': 358 return "simulator tests are run only on darwin hosts" 359 try: 360 DEVNULL = open(os.devnull, 'w') 361 output = subprocess.check_output(["xcodebuild", "-showsdks"], stderr=DEVNULL).decode("utf-8") 362 if re.search('%ssimulator' % platform, output): 363 return None 364 else: 365 return "%s simulator is not supported on this system." % platform 366 except subprocess.CalledProcessError: 367 return "Simulators are unsupported on this system (xcodebuild failed)" 368 369 return skipTestIfFn(should_skip_simulator_test) 370 371 372def debugserver_test(func): 373 """Decorate the item as a debugserver test.""" 374 def should_skip_debugserver_test(): 375 return "debugserver tests" if configuration.dont_do_debugserver_test else None 376 return skipTestIfFn(should_skip_debugserver_test)(func) 377 378 379def llgs_test(func): 380 """Decorate the item as a lldb-server test.""" 381 def should_skip_llgs_tests(): 382 return "llgs tests" if configuration.dont_do_llgs_test else None 383 return skipTestIfFn(should_skip_llgs_tests)(func) 384 385 386def not_remote_testsuite_ready(func): 387 """Decorate the item as a test which is not ready yet for remote testsuite.""" 388 def is_remote(): 389 return "Not ready for remote testsuite" if lldb.remote_platform else None 390 return skipTestIfFn(is_remote)(func) 391 392 393def expectedFailureOS( 394 oslist, 395 bugnumber=None, 396 compilers=None, 397 debug_info=None, 398 archs=None): 399 return expectedFailureAll( 400 oslist=oslist, 401 bugnumber=bugnumber, 402 compiler=compilers, 403 archs=archs, 404 debug_info=debug_info) 405 406 407def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None): 408 # For legacy reasons, we support both "darwin" and "macosx" as OS X 409 # triples. 410 return expectedFailureOS( 411 lldbplatform.darwin_all, 412 bugnumber, 413 compilers, 414 debug_info=debug_info) 415 416 417def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None): 418 """ Mark a test as xfail for Android. 419 420 Arguments: 421 bugnumber - The LLVM pr associated with the problem. 422 api_levels - A sequence of numbers specifying the Android API levels 423 for which a test is expected to fail. None means all API level. 424 arch - A sequence of architecture names specifying the architectures 425 for which a test is expected to fail. None means all architectures. 426 """ 427 return expectedFailure( 428 _skip_for_android( 429 "xfailing on android", 430 api_levels, 431 archs), 432 bugnumber) 433 434 435def expectedFailureNetBSD(bugnumber=None): 436 return expectedFailureOS( 437 ['netbsd'], 438 bugnumber) 439 440# Flakey tests get two chances to run. If they fail the first time round, the result formatter 441# makes sure it is run one more time. 442 443 444def expectedFlakey(expected_fn, bugnumber=None): 445 def expectedFailure_impl(func): 446 @wraps(func) 447 def wrapper(*args, **kwargs): 448 self = args[0] 449 if expected_fn(self): 450 # Send event marking test as explicitly eligible for rerunning. 451 if configuration.results_formatter_object is not None: 452 # Mark this test as rerunnable. 453 configuration.results_formatter_object.handle_event( 454 EventBuilder.event_for_mark_test_rerun_eligible(self)) 455 func(*args, **kwargs) 456 return wrapper 457 # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) 458 # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called 459 # the first way, the first argument will be the actual function because decorators are 460 # weird like that. So this is basically a check that says "which syntax was the original 461 # function decorated with?" 462 if six.callable(bugnumber): 463 return expectedFailure_impl(bugnumber) 464 else: 465 return expectedFailure_impl 466 467 468def expectedFlakeyOS(oslist, bugnumber=None, compilers=None): 469 def fn(self): 470 return (self.getPlatform() in oslist and 471 self.expectedCompiler(compilers)) 472 return expectedFlakey(fn, bugnumber) 473 474 475def expectedFlakeyDarwin(bugnumber=None, compilers=None): 476 # For legacy reasons, we support both "darwin" and "macosx" as OS X 477 # triples. 478 return expectedFlakeyOS( 479 lldbplatformutil.getDarwinOSTriples(), 480 bugnumber, 481 compilers) 482 483 484def expectedFlakeyFreeBSD(bugnumber=None, compilers=None): 485 return expectedFlakeyOS(['freebsd'], bugnumber, compilers) 486 487 488def expectedFlakeyLinux(bugnumber=None, compilers=None): 489 return expectedFlakeyOS(['linux'], bugnumber, compilers) 490 491 492def expectedFlakeyNetBSD(bugnumber=None, compilers=None): 493 return expectedFlakeyOS(['netbsd'], bugnumber, compilers) 494 495 496def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None): 497 return expectedFlakey( 498 _skip_for_android( 499 "flakey on android", 500 api_levels, 501 archs), 502 bugnumber) 503 504def skipIfOutOfTreeDebugserver(func): 505 """Decorate the item to skip tests if using an out-of-tree debugserver.""" 506 def is_out_of_tree_debugserver(): 507 return "out-of-tree debugserver" if lldbtest_config.out_of_tree_debugserver else None 508 return skipTestIfFn(is_out_of_tree_debugserver)(func) 509 510def skipIfRemote(func): 511 """Decorate the item to skip tests if testing remotely.""" 512 def is_remote(): 513 return "skip on remote platform" if lldb.remote_platform else None 514 return skipTestIfFn(is_remote)(func) 515 516 517def skipIfNoSBHeaders(func): 518 """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers.""" 519 def are_sb_headers_missing(): 520 if lldb.remote_platform: 521 return "skip because SBHeaders tests make no sense remotely" 522 523 if lldbplatformutil.getHostPlatform() == 'darwin': 524 header = os.path.join( 525 os.environ["LLDB_LIB_DIR"], 526 'LLDB.framework', 527 'Versions', 528 'Current', 529 'Headers', 530 'LLDB.h') 531 if os.path.exists(header): 532 return None 533 534 header = os.path.join( 535 os.environ["LLDB_SRC"], 536 "include", 537 "lldb", 538 "API", 539 "LLDB.h") 540 if not os.path.exists(header): 541 return "skip because LLDB.h header not found" 542 return None 543 544 return skipTestIfFn(are_sb_headers_missing)(func) 545 546 547def skipIfiOSSimulator(func): 548 """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" 549 def is_ios_simulator(): 550 return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None 551 return skipTestIfFn(is_ios_simulator)(func) 552 553def skipIfiOS(func): 554 return skipIfPlatform(["ios"])(func) 555 556def skipIftvOS(func): 557 return skipIfPlatform(["tvos"])(func) 558 559def skipIfwatchOS(func): 560 return skipIfPlatform(["watchos"])(func) 561 562def skipIfbridgeOS(func): 563 return skipIfPlatform(["bridgeos"])(func) 564 565def skipIfDarwinEmbedded(func): 566 """Decorate the item to skip tests that should be skipped on Darwin armv7/arm64 targets.""" 567 return skipIfPlatform( 568 lldbplatform.translate( 569 lldbplatform.darwin_embedded))(func) 570 571def skipIfFreeBSD(func): 572 """Decorate the item to skip tests that should be skipped on FreeBSD.""" 573 return skipIfPlatform(["freebsd"])(func) 574 575 576def skipIfNetBSD(func): 577 """Decorate the item to skip tests that should be skipped on NetBSD.""" 578 return skipIfPlatform(["netbsd"])(func) 579 580 581def skipIfDarwin(func): 582 """Decorate the item to skip tests that should be skipped on Darwin.""" 583 return skipIfPlatform( 584 lldbplatform.translate( 585 lldbplatform.darwin_all))(func) 586 587 588def skipIfLinux(func): 589 """Decorate the item to skip tests that should be skipped on Linux.""" 590 return skipIfPlatform(["linux"])(func) 591 592 593def skipIfWindows(func): 594 """Decorate the item to skip tests that should be skipped on Windows.""" 595 return skipIfPlatform(["windows"])(func) 596 597def skipUnlessWindows(func): 598 """Decorate the item to skip tests that should be skipped on any non-Windows platform.""" 599 return skipUnlessPlatform(["windows"])(func) 600 601 602def skipUnlessDarwin(func): 603 """Decorate the item to skip tests that should be skipped on any non Darwin platform.""" 604 return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func) 605 606def skipUnlessTargetAndroid(func): 607 return unittest2.skipUnless(lldbplatformutil.target_is_android(), 608 "requires target to be Android")(func) 609 610 611def skipIfHostIncompatibleWithRemote(func): 612 """Decorate the item to skip tests if binaries built on this host are incompatible.""" 613 614 def is_host_incompatible_with_remote(self): 615 host_arch = self.getLldbArchitecture() 616 host_platform = lldbplatformutil.getHostPlatform() 617 target_arch = self.getArchitecture() 618 target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform() 619 if not (target_arch == 'x86_64' and host_arch == 620 'i386') and host_arch != target_arch: 621 return "skipping because target %s is not compatible with host architecture %s" % ( 622 target_arch, host_arch) 623 if target_platform != host_platform: 624 return "skipping because target is %s but host is %s" % ( 625 target_platform, host_platform) 626 if lldbplatformutil.match_android_device(target_arch): 627 return "skipping because target is android" 628 return None 629 return skipTestIfFn(is_host_incompatible_with_remote)(func) 630 631 632def skipIfPlatform(oslist): 633 """Decorate the item to skip tests if running on one of the listed platforms.""" 634 # This decorator cannot be ported to `skipIf` yet because it is used on entire 635 # classes, which `skipIf` explicitly forbids. 636 return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist, 637 "skip on %s" % (", ".join(oslist))) 638 639 640def skipUnlessPlatform(oslist): 641 """Decorate the item to skip tests unless running on one of the listed platforms.""" 642 # This decorator cannot be ported to `skipIf` yet because it is used on entire 643 # classes, which `skipIf` explicitly forbids. 644 return unittest2.skipUnless(lldbplatformutil.getPlatform() in oslist, 645 "requires one of %s" % (", ".join(oslist))) 646 647def skipUnlessArch(arch): 648 """Decorate the item to skip tests unless running on the specified architecture.""" 649 650 def arch_doesnt_match(self): 651 target_arch = self.getArchitecture() 652 if arch != target_arch: 653 return "Test only runs on " + arch + ", but target arch is " + target_arch 654 return None 655 656 return skipTestIfFn(arch_doesnt_match) 657 658def skipIfTargetAndroid(bugnumber=None, api_levels=None, archs=None): 659 """Decorator to skip tests when the target is Android. 660 661 Arguments: 662 api_levels - The API levels for which the test should be skipped. If 663 it is None, then the test will be skipped for all API levels. 664 arch - A sequence of architecture names specifying the architectures 665 for which a test is skipped. None means all architectures. 666 """ 667 return skipTestIfFn( 668 _skip_for_android( 669 "skipping for android", 670 api_levels, 671 archs), 672 bugnumber) 673 674def skipUnlessSupportedTypeAttribute(attr): 675 """Decorate the item to skip test unless Clang supports type __attribute__(attr).""" 676 def compiler_doesnt_support_struct_attribute(self): 677 compiler_path = self.getCompiler() 678 f = tempfile.NamedTemporaryFile() 679 cmd = [self.getCompiler(), "-x", "c++", "-c", "-o", f.name, "-"] 680 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) 681 stdout, stderr = p.communicate('struct __attribute__((%s)) Test {};'%attr) 682 if attr in stderr: 683 return "Compiler does not support attribute %s"%(attr) 684 return None 685 return skipTestIfFn(compiler_doesnt_support_struct_attribute) 686 687def skipUnlessHasCallSiteInfo(func): 688 """Decorate the function to skip testing unless call site info from clang is available.""" 689 690 def is_compiler_clang_with_call_site_info(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 696 f = tempfile.NamedTemporaryFile() 697 cmd = "echo 'int main() {}' | " \ 698 "%s -g -glldb -O1 -Xclang -femit-debug-entry-values -S -emit-llvm -x c -o %s -" % (compiler_path, f.name) 699 if os.popen(cmd).close() is not None: 700 return "Compiler can't compile with call site info enabled" 701 702 with open(f.name, 'r') as ir_output_file: 703 buf = ir_output_file.read() 704 705 if 'DIFlagAllCallsDescribed' not in buf: 706 return "Compiler did not introduce DIFlagAllCallsDescribed IR flag" 707 708 return None 709 return skipTestIfFn(is_compiler_clang_with_call_site_info)(func) 710 711def skipUnlessThreadSanitizer(func): 712 """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" 713 714 def is_compiler_clang_with_thread_sanitizer(self): 715 compiler_path = self.getCompiler() 716 compiler = os.path.basename(compiler_path) 717 if not compiler.startswith("clang"): 718 return "Test requires clang as compiler" 719 if lldbplatformutil.getPlatform() == 'windows': 720 return "TSAN tests not compatible with 'windows'" 721 # rdar://28659145 - TSAN tests don't look like they're supported on i386 722 if self.getArchitecture() == 'i386' and platform.system() == 'Darwin': 723 return "TSAN tests not compatible with i386 targets" 724 f = tempfile.NamedTemporaryFile() 725 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name) 726 if os.popen(cmd).close() is not None: 727 return None # The compiler cannot compile at all, let's *not* skip the test 728 cmd = "echo 'int main() {}' | %s -fsanitize=thread -x c -o %s -" % (compiler_path, f.name) 729 if os.popen(cmd).close() is not None: 730 return "Compiler cannot compile with -fsanitize=thread" 731 return None 732 return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func) 733 734def skipUnlessUndefinedBehaviorSanitizer(func): 735 """Decorate the item to skip test unless -fsanitize=undefined is supported.""" 736 737 def is_compiler_clang_with_ubsan(self): 738 # Write out a temp file which exhibits UB. 739 inputf = tempfile.NamedTemporaryFile(suffix='.c', mode='w') 740 inputf.write('int main() { int x = 0; return x / x; }\n') 741 inputf.flush() 742 743 # We need to write out the object into a named temp file for inspection. 744 outputf = tempfile.NamedTemporaryFile() 745 746 # Try to compile with ubsan turned on. 747 cmd = '%s -fsanitize=undefined %s -o %s' % (self.getCompiler(), inputf.name, outputf.name) 748 if os.popen(cmd).close() is not None: 749 return "Compiler cannot compile with -fsanitize=undefined" 750 751 # Check that we actually see ubsan instrumentation in the binary. 752 cmd = 'nm %s' % outputf.name 753 with os.popen(cmd) as nm_output: 754 if '___ubsan_handle_divrem_overflow' not in nm_output.read(): 755 return "Division by zero instrumentation is missing" 756 757 # Find the ubsan dylib. 758 # FIXME: This check should go away once compiler-rt gains support for __ubsan_on_report. 759 cmd = '%s -fsanitize=undefined -x c - -o - -### 2>&1' % self.getCompiler() 760 with os.popen(cmd) as cc_output: 761 driver_jobs = cc_output.read() 762 m = re.search(r'"([^"]+libclang_rt.ubsan_osx_dynamic.dylib)"', driver_jobs) 763 if not m: 764 return "Could not find the ubsan dylib used by the driver" 765 ubsan_dylib = m.group(1) 766 767 # Check that the ubsan dylib has special monitor hooks. 768 cmd = 'nm -gU %s' % ubsan_dylib 769 with os.popen(cmd) as nm_output: 770 syms = nm_output.read() 771 if '___ubsan_on_report' not in syms: 772 return "Missing ___ubsan_on_report" 773 if '___ubsan_get_current_report_data' not in syms: 774 return "Missing ___ubsan_get_current_report_data" 775 776 # OK, this dylib + compiler works for us. 777 return None 778 779 return skipTestIfFn(is_compiler_clang_with_ubsan)(func) 780 781def skipUnlessAddressSanitizer(func): 782 """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" 783 784 def is_compiler_with_address_sanitizer(self): 785 compiler_path = self.getCompiler() 786 compiler = os.path.basename(compiler_path) 787 f = tempfile.NamedTemporaryFile() 788 if lldbplatformutil.getPlatform() == 'windows': 789 return "ASAN tests not compatible with 'windows'" 790 cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name) 791 if os.popen(cmd).close() is not None: 792 return None # The compiler cannot compile at all, let's *not* skip the test 793 cmd = "echo 'int main() {}' | %s -fsanitize=address -x c -o %s -" % (compiler_path, f.name) 794 if os.popen(cmd).close() is not None: 795 return "Compiler cannot compile with -fsanitize=address" 796 return None 797 return skipTestIfFn(is_compiler_with_address_sanitizer)(func) 798 799def _get_bool_config_skip_if_decorator(key): 800 config = lldb.SBDebugger.GetBuildConfiguration() 801 value_node = config.GetValueForKey(key) 802 fail_value = True # More likely to notice if something goes wrong 803 have = value_node.GetValueForKey("value").GetBooleanValue(fail_value) 804 return unittest2.skipIf(not have, "requires " + key) 805 806def skipIfCursesSupportMissing(func): 807 return _get_bool_config_skip_if_decorator("curses")(func) 808 809def skipIfXmlSupportMissing(func): 810 return _get_bool_config_skip_if_decorator("xml")(func) 811 812def skipIfLLVMTargetMissing(target): 813 config = lldb.SBDebugger.GetBuildConfiguration() 814 targets = config.GetValueForKey("targets").GetValueForKey("value") 815 found = False 816 for i in range(targets.GetSize()): 817 if targets.GetItemAtIndex(i).GetStringValue(99) == target: 818 found = True 819 break 820 821 return unittest2.skipIf(not found, "requires " + target) 822 823# Call sysctl on darwin to see if a specified hardware feature is available on this machine. 824def skipUnlessFeature(feature): 825 def is_feature_enabled(self): 826 if platform.system() == 'Darwin': 827 try: 828 DEVNULL = open(os.devnull, 'w') 829 output = subprocess.check_output(["/usr/sbin/sysctl", feature], stderr=DEVNULL).decode("utf-8") 830 # If 'feature: 1' was output, then this feature is available and 831 # the test should not be skipped. 832 if re.match('%s: 1\s*' % feature, output): 833 return None 834 else: 835 return "%s is not supported on this system." % feature 836 except subprocess.CalledProcessError: 837 return "%s is not supported on this system." % feature 838 return skipTestIfFn(is_feature_enabled) 839 840def skipIfAsan(func): 841 """Skip this test if the environment is set up to run LLDB itself under ASAN.""" 842 def is_asan(): 843 if ('ASAN_OPTIONS' in os.environ): 844 return "ASAN unsupported" 845 return None 846 return skipTestIfFn(is_asan)(func) 847