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