diff options
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test')
4 files changed, 122 insertions, 74 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py b/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py index e4bc08711f4..125ca7505fa 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py @@ -15,7 +15,8 @@ import lldbsuite.test.lldbutil as lldbutil def python_leaky_fd_version(test): import sys # Python random module leaks file descriptors on some versions. - return sys.version_info >= (2, 7, 8) and sys.version_info < (2, 7, 10) + return (sys.version_info >= (2, 7, 8) and sys.version_info < (2, 7, 10), + "Python random module leaks file descriptors in this python version") class AvoidsFdLeakTestCase(TestBase): diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py b/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py index 63d01c12ed4..aba8002ee38 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py @@ -60,7 +60,8 @@ class AssertingInferiorTestCase(TestBase): lldbutil.run_break_set_by_file_and_line (self, "main.c", line, num_expected_locations=1, loc_exact=True) def check_stop_reason(self): - if matchAndroid(api_levels=list(range(1, 16+1)))(self): + match_result, _ = matchAndroid(api_levels=list(range(1, 16+1)))(self) + if match_result: # On android until API-16 the abort() call ended in a sigsegv instead of in a sigabrt stop_reason = 'stop reason = signal SIGSEGV' else: diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py b/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py index c7abf346441..8c38f4c8bfd 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py @@ -16,7 +16,7 @@ class JITLoaderGDBTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipTestIfFn(lambda x: True, "llvm.org/pr24702", "Skipped because the test crashes the test runner") + @skipTestIfFn(lambda x: (True, "Skipped because the test crashes the test runner"), bugnumber="llvm.org/pr24702") @unittest2.expectedFailure("llvm.org/pr24702") def test_bogus_values(self): """Test that we handle inferior misusing the GDB JIT interface""" diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index c57279c8d02..0baad8aa7fd 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -509,6 +509,9 @@ def check_expected_version(comparison, expected, actual): # # Decorators for categorizing test cases. # +class DecorateMode: + Skip, Xfail = range(2) + from functools import wraps def add_test_categories(cat): @@ -600,7 +603,8 @@ def expectedFailure(expected_fn, bugnumber=None): def wrapper(*args, **kwargs): from unittest2 import case self = args[0] - if expected_fn(self): + xfail, reason = expected_fn(self) + if xfail: if configuration.results_formatter_object is not None: # Mark this test as expected to fail. configuration.results_formatter_object.handle_event( @@ -610,8 +614,11 @@ def expectedFailure(expected_fn, bugnumber=None): else: func(*args, **kwargs) return wrapper - # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments - # return decorator in this case, so it will be used to decorating original method + # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) + # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called + # the first way, the first argument will be the actual function because decorators are + # weird like that. So this is basically a check that says "which syntax was the original + # function decorated with?" if six.callable(bugnumber): return expectedFailure_impl(bugnumber) else: @@ -650,26 +657,21 @@ def matchArchitectures(archs, actual_arch): # @expectedFailureAll, xfail for all platform/compiler/arch, # @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture # @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386 -def expectedFailureAll(bugnumber=None, oslist=None, hostoslist=None, compiler=None, compiler_version=None, archs=None, triple=None, debug_info=None, swig_version=None, py_version=None): - def fn(self): - oslist_passes = check_list_or_lambda(oslist, self.getPlatform()) - hostoslist_passes = check_list_or_lambda(hostoslist, getHostPlatform()) - compiler_passes = check_list_or_lambda(self.getCompiler(), compiler) and self.expectedCompilerVersion(compiler_version) - arch_passes = check_list_or_lambda(archs, self.getArchitecture()) - triple_passes = triple is None or re.match(triple, lldb.DBG.GetSelectedPlatform().GetTriple()) - debug_info_passes = check_list_or_lambda(debug_info, self.debug_info) - swig_version_passes = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (check_expected_version(swig_version[0], swig_version[1], lldb.swig_version)) - py_version_passes = (py_version is None) or check_expected_version(py_version[0], py_version[1], sys.version_info) - - return (oslist_passes and - hostoslist_passes and - compiler_passes and - arch_passes and - triple_passes and - debug_info_passes and - swig_version_passes and - py_version_passes) - return expectedFailure(fn, bugnumber) +def expectedFailureAll(bugnumber=None, + oslist=None, hostoslist=None, + compiler=None, compiler_version=None, + archs=None, triple=None, + debug_info=None, + swig_version=None, py_version=None, + remote=None): + return decorateTest(DecorateMode.Xfail, + bugnumber=bugnumber, + oslist=oslist, hostoslist=hostoslist, + compiler=compiler, compiler_version=compiler_version, + archs=archs, triple=triple, + debug_info=debug_info, + swig_version=swig_version, py_version=py_version, + remote=remote) def expectedFailureDwarf(bugnumber=None): return expectedFailureAll(bugnumber=bugnumber, debug_info="dwarf") @@ -697,9 +699,7 @@ def expectedFailureIcc(bugnumber=None): return expectedFailureCompiler('icc', None, bugnumber) def expectedFailureArch(arch, bugnumber=None): - def fn(self): - return arch in self.getArchitecture() - return expectedFailure(fn, bugnumber) + return decorateTest(DecorateMode.Xfail, archs=arch, bugnumber=bugnumber) def expectedFailurei386(bugnumber=None): return expectedFailureArch('i386', bugnumber) @@ -708,18 +708,10 @@ def expectedFailurex86_64(bugnumber=None): return expectedFailureArch('x86_64', bugnumber) def expectedFailureOS(oslist, bugnumber=None, compilers=None, debug_info=None, archs=None): - def fn(self): - return (self.getPlatform() in oslist and - self.expectedCompiler(compilers) and - (archs is None or self.getArchitecture() in archs) and - (debug_info is None or self.debug_info in debug_info)) - return expectedFailure(fn, bugnumber) + return decorateTest(DecorateMode.Xfail, oslist=oslist, bugnumber=bugnumber, compiler=compilers, archs=archs, debug_info=debug_info) def expectedFailureHostOS(oslist, bugnumber=None, compilers=None): - def fn(self): - return (getHostPlatform() in oslist and - self.expectedCompiler(compilers)) - return expectedFailure(fn, bugnumber) + return decorateTest(DecorateMode.Xfail, hostoslist=oslist, bugnumber=bugnumber) def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None): # For legacy reasons, we support both "darwin" and "macosx" as OS X triples. @@ -743,12 +735,12 @@ def expectedFailureHostWindows(bugnumber=None, compilers=None): def matchAndroid(api_levels=None, archs=None): def match(self): if not target_is_android(): - return False + return (False, "target is not android") if archs is not None and self.getArchitecture() not in archs: - return False + return (False, "invalid architecture") if api_levels is not None and android_device_api() not in api_levels: - return False - return True + return (False, "invalid api level") + return (True, None) return match @@ -779,8 +771,11 @@ def expectedFlakey(expected_fn, bugnumber=None): EventBuilder.event_for_mark_test_rerun_eligible(self)) func(*args, **kwargs) return wrapper - # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments - # return decorator in this case, so it will be used to decorating original method + # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) + # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called + # the first way, the first argument will be the actual function because decorators are + # weird like that. So this is basically a check that says "which syntax was the original + # function decorated with?" if six.callable(bugnumber): return expectedFailure_impl(bugnumber) else: @@ -1072,30 +1067,74 @@ def skipUnlessPlatform(oslist): # @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 # TODO: refactor current code, to make skipIfxxx functions to call this function -def skipIf(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, debug_info=None, swig_version=None, py_version=None, remote=None): +def decorateTest(mode, + bugnumber=None, oslist=None, hostoslist=None, + compiler=None, compiler_version=None, + archs=None, triple=None, + debug_info=None, + swig_version=None, py_version=None, + remote=None): def fn(self): - oslist_passes = check_list_or_lambda(oslist, self.getPlatform()) - compiler_passes = check_list_or_lambda(self.getCompiler(), compiler) and self.expectedCompilerVersion(compiler_version) - arch_passes = check_list_or_lambda(archs, self.getArchitecture()) - debug_info_passes = check_list_or_lambda(debug_info, self.debug_info) - swig_version_passes = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (check_expected_version(swig_version[0], swig_version[1], lldb.swig_version)) - py_version_passes = (py_version is None) or check_expected_version(py_version[0], py_version[1], sys.version_info) - remote_passes = (remote is None) or (remote == (lldb.remote_platform is not None)) - - return (oslist_passes and - compiler_passes and - arch_passes and - debug_info_passes and - swig_version_passes and - py_version_passes and - remote_passes) - - local_vars = locals() - args = [x for x in inspect.getargspec(skipIf).args] - arg_vals = [eval(x, globals(), local_vars) for x in args] - args = [x for x in zip(args, arg_vals) if x[1] is not None] - reasons = ['%s=%s' % (x, str(y)) for (x,y) in args] - return skipTestIfFn(fn, bugnumber, skipReason='skipping because ' + ' && '.join(reasons)) + skip_for_os = check_list_or_lambda(oslist, self.getPlatform()) + skip_for_hostos = check_list_or_lambda(hostoslist, getHostPlatform()) + skip_for_compiler = check_list_or_lambda(self.getCompiler(), compiler) and self.expectedCompilerVersion(compiler_version) + skip_for_arch = check_list_or_lambda(archs, self.getArchitecture()) + skip_for_debug_info = check_list_or_lambda(debug_info, self.debug_info) + skip_for_triple = triple is None or re.match(triple, lldb.DBG.GetSelectedPlatform().GetTriple()) + skip_for_swig_version = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (check_expected_version(swig_version[0], swig_version[1], lldb.swig_version)) + skip_for_py_version = (py_version is None) or check_expected_version(py_version[0], py_version[1], sys.version_info) + skip_for_remote = (remote is None) or (remote == (lldb.remote_platform is not None)) + + # For the test to be skipped, all specified (e.g. not None) parameters must be True. + # An unspecified parameter means "any", so those are marked skip by default. And we skip + # the final test if all conditions are True. + conditions = [(oslist, skip_for_os, "target o/s"), + (hostoslist, skip_for_hostos, "host o/s"), + (compiler, skip_for_compiler, "compiler or version"), + (archs, skip_for_arch, "architecture"), + (debug_info, skip_for_debug_info, "debug info format"), + (triple, skip_for_triple, "target triple"), + (swig_version, skip_for_swig_version, "swig version"), + (py_version, skip_for_py_version, "python version"), + (remote, skip_for_remote, "platform locality (remote/local)")] + reasons = [] + final_skip_result = True + for this_condition in conditions: + final_skip_result = final_skip_result and this_condition[1] + if this_condition[0] is not None and this_condition[1]: + reasons.append(this_condition[2]) + reason_str = None + if final_skip_result: + mode_str = {DecorateMode.Skip : "skipping", DecorateMode.Xfail : "xfailing"}[mode] + if len(reasons) > 0: + reason_str = ",".join(reasons) + reason_str = "{} due to the following parameter(s): {}".format(mode_str, reason_str) + else: + reason_str = "{} unconditionally" + return (final_skip_result, reason_str) + + if mode == DecorateMode.Skip: + return skipTestIfFn(fn, bugnumber) + elif mode == DecorateMode.Xfail: + return expectedFailure(fn, bugnumber) + else: + return None + +def skipIf(bugnumber=None, + oslist=None, hostoslist=None, + compiler=None, compiler_version=None, + archs=None, triple=None, + debug_info=None, + swig_version=None, py_version=None, + remote=None): + return decorateTest(DecorateMode.Skip, + bugnumber=bugnumber, + oslist=oslist, hostoslist=hostoslist, + compiler=compiler, compiler_version=compiler_version, + archs=archs, triple=triple, + debug_info=debug_info, + swig_version=swig_version, py_version=py_version, + remote=remote) def skipIfDebugInfo(bugnumber=None, debug_info=None): return skipIf(bugnumber=bugnumber, debug_info=debug_info) @@ -1109,17 +1148,23 @@ def skipIfDwarf(bugnumber=None): def skipIfDsym(bugnumber=None): return skipIfDebugInfo(bugnumber, ["dsym"]) -def skipTestIfFn(expected_fn, bugnumber=None, skipReason=None): +def skipTestIfFn(expected_fn, bugnumber=None): def skipTestIfFn_impl(func): @wraps(func) def wrapper(*args, **kwargs): from unittest2 import case self = args[0] - if expected_fn(self): - self.skipTest(skipReason) + skip, reason = expected_fn(self) + if skip: + self.skipTest(reason) else: func(*args, **kwargs) return wrapper + + # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) + # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called + # the first way, the first argument will be the actual function because decorators are + # weird like that. So this is basically a check that says "how was the decorator used" if six.callable(bugnumber): return skipTestIfFn_impl(bugnumber) else: @@ -1186,9 +1231,10 @@ def skipIfTargetAndroid(api_levels=None, archs=None): def wrapper(*args, **kwargs): from unittest2 import case self = args[0] - if matchAndroid(api_levels, archs)(self): - self.skipTest("skiped on Android target with API %d and architecture %s" % - (android_device_api(), self.getArchitecture())) + skip_for_android, reason = matchAndroid(api_levels, archs)(self) + if skip_for_android: + self.skipTest("skiped on Android target with API %d and architecture %s. %s" % + (android_device_api(), self.getArchitecture(), reason)) func(*args, **kwargs) return wrapper return myImpl |