Index: packages/Python/lldbsuite/support/funcutils.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/support/funcutils.py @@ -0,0 +1,16 @@ +from __future__ import print_function +from __future__ import absolute_import + +# System modules +import inspect + +# Third-party modules + +# LLDB modules + +def requires_self(func): + func_argc = len(inspect.getargspec(func).args) + if func_argc == 0 or (getattr(func,'im_self', None) is not None) or (hasattr(func, '__self__')): + return False + else: + return True Index: packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py =================================================================== --- packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py +++ packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py @@ -6,8 +6,9 @@ import os, re +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil import subprocess class SBBreakpointCallbackCase(TestBase): Index: packages/Python/lldbsuite/test/decorators.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/decorators.py @@ -0,0 +1,220 @@ +from __future__ import print_function +from __future__ import absolute_import + +# System modules +from distutils.version import LooseVersion +from functools import wraps +import re +import sys + +# Third-party modules +import six +import unittest2 + +# LLDB modules +import use_lldb_suite + +import lldb +from . import configuration +from .result_formatter import EventBuilder +from lldbsuite.support import funcutils +from lldbsuite.test import lldbplatformutil + +class DecorateMode: + Skip, Xfail = range(2) + + +def _check_expected_version(comparison, expected, actual): + def fn_leq(x,y): return x <= y + def fn_less(x,y): return x < y + def fn_geq(x,y): return x >= y + def fn_greater(x,y): return x > y + def fn_eq(x,y): return x == y + def fn_neq(x,y): return x != y + + op_lookup = { + "==": fn_eq, + "=": fn_eq, + "!=": fn_neq, + "<>": fn_neq, + ">": fn_greater, + "<": fn_less, + ">=": fn_geq, + "<=": fn_leq + } + expected_str = '.'.join([str(x) for x in expected]) + actual_str = '.'.join([str(x) for x in actual]) + + return op_lookup[comparison](LooseVersion(actual_str), LooseVersion(expected_str)) + +def _check_list_or_lambda(list_or_lambda, value): + if six.callable(list_or_lambda): + return list_or_lambda(value) + elif isinstance(list_or_lambda, list): + for item in list_or_lambda: + if value in item: + return True + return False + elif isinstance(list_or_lambda, str): + return value is None or value in list_or_lambda + else: + return list_or_lambda is None or value is None or list_or_lambda == value + +def expectedFailure(expected_fn, bugnumber=None): + def expectedFailure_impl(func): + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("Decorator can only be used to decorate a test method") + @wraps(func) + def wrapper(*args, **kwargs): + from unittest2 import case + self = args[0] + if funcutils.requires_self(expected_fn): + xfail_reason = expected_fn(self) + else: + xfail_reason = expected_fn() + if xfail_reason is not None: + if configuration.results_formatter_object is not None: + # Mark this test as expected to fail. + configuration.results_formatter_object.handle_event( + EventBuilder.event_for_mark_test_expected_failure(self)) + xfail_func = unittest2.expectedFailure(func) + xfail_func(*args, **kwargs) + 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 "which syntax was the original + # function decorated with?" + if six.callable(bugnumber): + return expectedFailure_impl(bugnumber) + else: + return expectedFailure_impl + +def skipTestIfFn(expected_fn, bugnumber=None): + def skipTestIfFn_impl(func): + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("@skipTestIfFn can only be used to decorate a test method") + + @wraps(func) + def wrapper(*args, **kwargs): + from unittest2 import case + self = args[0] + if funcutils.requires_self(expected_fn): + reason = expected_fn(self) + else: + reason = expected_fn() + + if reason is not None: + 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: + return skipTestIfFn_impl + +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): + skip_for_os = _check_list_or_lambda(oslist, self.getPlatform()) + skip_for_hostos = _check_list_or_lambda(hostoslist, lldbplatformutil.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 reason_str + + if mode == DecorateMode.Skip: + return skipTestIfFn(fn, bugnumber) + elif mode == DecorateMode.Xfail: + return expectedFailure(fn, bugnumber) + else: + return None + +# provide a function to xfail on defined oslist, compiler version, and archs +# if none is specified for any argument, that argument won't be checked and thus means for all +# for example, +# @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, + 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) + + +# provide a function to skip on defined oslist, compiler version, and archs +# if none is specified for any argument, that argument won't be checked and thus means for all +# for example, +# @skipIf, skip for all platform/compiler/arch, +# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture +# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 +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) Index: packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py =================================================================== --- packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py +++ packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py @@ -3,8 +3,9 @@ import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCharTestCase(TestBase): Index: packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py =================================================================== --- packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py +++ packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py @@ -1,6 +1,10 @@ +from __future__ import print_function + + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestMacros(TestBase): Index: packages/Python/lldbsuite/test/expression_command/persist_objc_pointeetype/TestPersistObjCPointeeType.py =================================================================== --- packages/Python/lldbsuite/test/expression_command/persist_objc_pointeetype/TestPersistObjCPointeeType.py +++ packages/Python/lldbsuite/test/expression_command/persist_objc_pointeetype/TestPersistObjCPointeeType.py @@ -7,8 +7,9 @@ import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class PersistObjCPointeeType(TestBase): Index: packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py +++ packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py @@ -8,8 +8,9 @@ import os import lldb +from lldbsuite.test import lldbutil from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * def python_leaky_fd_version(test): Index: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py +++ packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py @@ -8,8 +8,9 @@ import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BreakpointLocationsTestCase(TestBase): Index: packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py +++ packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py @@ -6,8 +6,9 @@ import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DebugBreakTestCase(TestBase): Index: packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py +++ packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py @@ -8,8 +8,9 @@ import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class VectorTypesFormattingTestCase(TestBase): Index: packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py +++ packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py @@ -2,13 +2,12 @@ from __future__ import print_function - - import unittest2 import os import lldb +from lldbsuite.test import lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil import re Index: packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py +++ packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py @@ -9,8 +9,9 @@ import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently class LoadUnloadTestCase(TestBase): Index: packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py +++ packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py @@ -9,8 +9,9 @@ import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ReturnValueTestCase(TestBase): Index: packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py +++ packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py @@ -17,8 +17,9 @@ import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipIfWindows class ConcurrentEventsTestCase(TestBase): Index: packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py +++ packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py @@ -8,8 +8,9 @@ import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CreateDuringStepTestCase(TestBase): Index: packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py +++ packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py @@ -9,8 +9,9 @@ import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class HelloWatchLocationTestCase(TestBase): Index: packages/Python/lldbsuite/test/lang/c/const_variables/TestConstVariables.py =================================================================== --- packages/Python/lldbsuite/test/lang/c/const_variables/TestConstVariables.py +++ packages/Python/lldbsuite/test/lang/c/const_variables/TestConstVariables.py @@ -6,8 +6,9 @@ import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ConstVariableTestCase(TestBase): Index: packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py =================================================================== --- packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py +++ packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py @@ -3,8 +3,9 @@ from __future__ import print_function +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class GlobalVariablesTestCase(TestBase): Index: packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py =================================================================== --- packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py +++ packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py @@ -6,8 +6,9 @@ import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class RegisterVariableTestCase(TestBase): Index: packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py =================================================================== --- packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py +++ packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py @@ -6,8 +6,9 @@ import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TypedefTestCase(TestBase): Index: packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py =================================================================== --- packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py +++ packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py @@ -2,8 +2,9 @@ Tests that auto types work """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CPPAutoTestCase(TestBase): Index: packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py =================================================================== --- packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py +++ packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py @@ -1,6 +1,7 @@ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestWithLimitDebugInfo(TestBase): Index: packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py =================================================================== --- packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py +++ packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py @@ -7,8 +7,9 @@ import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil def Msg(expr, val): return "'expression %s' matches the output (from compiled code): %s" % (expr, val) Index: packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py =================================================================== --- packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py +++ packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py @@ -6,13 +6,14 @@ import unittest2 import os, time -import lldb import platform -import lldbsuite.test.lldbutil as lldbutil from distutils.version import StrictVersion +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCNewSyntaxTestCase(TestBase): Index: packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py =================================================================== --- packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py +++ packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py @@ -9,8 +9,9 @@ import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BuiltinTrapTestCase(TestBase): Index: packages/Python/lldbsuite/test/lldbplatformutil.py =================================================================== --- packages/Python/lldbsuite/test/lldbplatformutil.py +++ packages/Python/lldbsuite/test/lldbplatformutil.py @@ -6,6 +6,7 @@ # System modules import re import subprocess +import sys # Third-party modules from six.moves.urllib import parse as urlparse @@ -85,3 +86,19 @@ if android_device_api() >= 16: dictionary["PIE"] = 1 return dictionary + +def getHostPlatform(): + """Returns the host platform running the test suite.""" + # Attempts to return a platform name matching a target Triple platform. + if sys.platform.startswith('linux'): + return 'linux' + elif sys.platform.startswith('win32'): + return 'windows' + elif sys.platform.startswith('darwin'): + return 'darwin' + elif sys.platform.startswith('freebsd'): + return 'freebsd' + elif sys.platform.startswith('netbsd'): + return 'netbsd' + else: + return sys.platform Index: packages/Python/lldbsuite/test/lldbtest.py =================================================================== --- packages/Python/lldbsuite/test/lldbtest.py +++ packages/Python/lldbsuite/test/lldbtest.py @@ -37,7 +37,6 @@ # System modules import abc import collections -from distutils.version import LooseVersion import gc import glob import inspect @@ -60,11 +59,13 @@ import use_lldb_suite import lldb from . import configuration +from . import decorators from . import lldbplatformutil from . import lldbtest_config from . import lldbutil from . import test_categories from lldbsuite.support import encoded_file +from lldbsuite.support import funcutils from .result_formatter import EventBuilder @@ -440,43 +441,9 @@ return __import__("builder_netbsd") return __import__("builder_" + sys.platform) -def does_function_require_self(func): - import inspect - func_argc = len(inspect.getargspec(func).args) - if func_argc == 0 or (getattr(func,'im_self',None) is not None) or (hasattr(func, '__self__')): - return False - else: - return True - -def check_expected_version(comparison, expected, actual): - def fn_leq(x,y): return x <= y - def fn_less(x,y): return x < y - def fn_geq(x,y): return x >= y - def fn_greater(x,y): return x > y - def fn_eq(x,y): return x == y - def fn_neq(x,y): return x != y - - op_lookup = { - "==": fn_eq, - "=": fn_eq, - "!=": fn_neq, - "<>": fn_neq, - ">": fn_greater, - "<": fn_less, - ">=": fn_geq, - "<=": fn_leq - } - expected_str = '.'.join([str(x) for x in expected]) - actual_str = '.'.join([str(x) for x in actual]) - - return op_lookup[comparison](LooseVersion(actual_str), LooseVersion(expected_str)) - # # Decorators for categorizing test cases. # -class DecorateMode: - Skip, Xfail = range(2) - from functools import wraps def skip_for_android(reason, api_levels, archs): @@ -504,7 +471,7 @@ return "benchmarks test" # Mark this function as such to separate them from the regular tests. - result = skipTestIfFn(should_skip_benchmarks_test)(func) + result = decorators.skipTestIfFn(should_skip_benchmarks_test)(func) result.__benchmarks_test__ = True return result @@ -525,48 +492,19 @@ """Decorate the item as a debugserver test.""" def should_skip_debugserver_test(): return "debugserver tests" if configuration.dont_do_debugserver_test else None - return skipTestIfFn(should_skip_debugserver_test)(func) + return decorators.skipTestIfFn(should_skip_debugserver_test)(func) def llgs_test(func): """Decorate the item as a lldb-server test.""" def should_skip_llgs_tests(): return "llgs tests" if configuration.dont_do_llgs_test else None - return skipTestIfFn(should_skip_llgs_tests)(func) + return decorators.skipTestIfFn(should_skip_llgs_tests)(func) def not_remote_testsuite_ready(func): """Decorate the item as a test which is not ready yet for remote testsuite.""" def is_remote(): return "Not ready for remote testsuite" if lldb.remote_platform else None - return skipTestIfFn(is_remote)(func) - -def expectedFailure(expected_fn, bugnumber=None): - def expectedFailure_impl(func): - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("Decorator can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - xfail_reason = expected_fn(self) - if xfail_reason is not None: - if configuration.results_formatter_object is not None: - # Mark this test as expected to fail. - configuration.results_formatter_object.handle_event( - EventBuilder.event_for_mark_test_expected_failure(self)) - xfail_func = unittest2.expectedFailure(func) - xfail_func(*args, **kwargs) - 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 "which syntax was the original - # function decorated with?" - if six.callable(bugnumber): - return expectedFailure_impl(bugnumber) - else: - return expectedFailure_impl + return decorators.skipTestIfFn(is_remote)(func) # You can also pass not_in(list) to reverse the sense of the test for the arguments that # are simple lists, namely oslist, compiler, and debug_info. @@ -574,19 +512,6 @@ def not_in(iterable): return lambda x : x not in iterable -def check_list_or_lambda(list_or_lambda, value): - if six.callable(list_or_lambda): - return list_or_lambda(value) - elif isinstance(list_or_lambda, list): - for item in list_or_lambda: - if value in item: - return True - return False - elif isinstance(list_or_lambda, str): - return value is None or value in list_or_lambda - else: - return list_or_lambda is None or value is None or list_or_lambda == value - def matchArchitectures(archs, actual_arch): retype = type(re.compile('hello, world')) list_passes = isinstance(archs, list) and actual_arch in archs @@ -595,41 +520,19 @@ return (list_passes or basestring_passes or regex_passes) -# provide a function to xfail on defined oslist, compiler version, and archs -# if none is specified for any argument, that argument won't be checked and thus means for all -# for example, -# @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, - 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") + return decorators.expectedFailureAll(bugnumber=bugnumber, debug_info="dwarf") def expectedFailureDwo(bugnumber=None): - return expectedFailureAll(bugnumber=bugnumber, debug_info="dwo") + return decorators.expectedFailureAll(bugnumber=bugnumber, debug_info="dwo") def expectedFailureDsym(bugnumber=None): - return expectedFailureAll(bugnumber=bugnumber, debug_info="dsym") + return decorators.expectedFailureAll(bugnumber=bugnumber, debug_info="dsym") def expectedFailureCompiler(compiler, compiler_version=None, bugnumber=None): if compiler_version is None: compiler_version=['=', None] - return expectedFailureAll(bugnumber=bugnumber, compiler=compiler, compiler_version=compiler_version) + return decorators.expectedFailureAll(bugnumber=bugnumber, compiler=compiler, compiler_version=compiler_version) # to XFAIL a specific clang versions, try this # @expectedFailureClang('bugnumber', ['<=', '3.4']) @@ -643,7 +546,7 @@ return expectedFailureCompiler('icc', None, bugnumber) def expectedFailureArch(arch, bugnumber=None): - return decorateTest(DecorateMode.Xfail, archs=arch, bugnumber=bugnumber) + return decorators.expectedFailureAll(archs=arch, bugnumber=bugnumber) def expectedFailurei386(bugnumber=None): return expectedFailureArch('i386', bugnumber) @@ -652,10 +555,10 @@ return expectedFailureArch('x86_64', bugnumber) def expectedFailureOS(oslist, bugnumber=None, compilers=None, debug_info=None, archs=None): - return decorateTest(DecorateMode.Xfail, oslist=oslist, bugnumber=bugnumber, compiler=compilers, archs=archs, debug_info=debug_info) + return decorators.expectedFailureAll(oslist=oslist, bugnumber=bugnumber, compiler=compilers, archs=archs, debug_info=debug_info) def expectedFailureHostOS(oslist, bugnumber=None, compilers=None): - return decorateTest(DecorateMode.Xfail, hostoslist=oslist, bugnumber=bugnumber) + return decorators.expectedFailureAll(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. @@ -686,7 +589,7 @@ arch - A sequence of architecture names specifying the architectures for which a test is expected to fail. None means all architectures. """ - return expectedFailure(skip_for_android("xfailing on android", api_levels, archs), bugnumber) + return decorators.expectedFailure(skip_for_android("xfailing on android", api_levels, archs), bugnumber) # Flakey tests get two chances to run. If they fail the first time round, the result formatter # makes sure it is run one more time. @@ -764,13 +667,25 @@ """Decorate the item to skip tests if testing remotely.""" def is_remote(): return "skip on remote platform" if lldb.remote_platform else None - return skipTestIfFn(is_remote)(func) + return decorators.skipTestIfFn(is_remote)(func) + +def skipUnlessListedRemote(remote_list=None): + def is_remote_unlisted(self): + if remote_list and lldb.remote_platform: + triple = self.dbg.GetSelectedPlatform().GetTriple() + for r in remote_list: + if r in triple: + return None + return "skipping because remote is not listed" + else: + return None + return decorators.skipTestIfFn(is_remote_unlisted) def skipIfRemoteDueToDeadlock(func): """Decorate the item to skip tests if testing remotely due to the test deadlocking.""" def is_remote(): return "skip on remote platform (deadlocks)" if lldb.remote_platform else None - return skipTestIfFn(is_remote)(func) + return decorators.skipTestIfFn(is_remote)(func) def skipIfNoSBHeaders(func): """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers.""" @@ -784,13 +699,13 @@ return "skip because LLDB.h header not found" return None - return skipTestIfFn(are_sb_headers_missing)(func) + return decorators.skipTestIfFn(are_sb_headers_missing)(func) def skipIfiOSSimulator(func): """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" def is_ios_simulator(): return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None - return skipTestIfFn(is_ios_simulator)(func) + return decorators.skipTestIfFn(is_ios_simulator)(func) def skipIfFreeBSD(func): """Decorate the item to skip tests that should be skipped on FreeBSD.""" @@ -849,7 +764,7 @@ return "skipping because available version ({}) does not meet minimum required version ({})".format( compiler_strict_version, min_strict_version) return None - return skipTestIfFn(is_go_missing)(func) + return decorators.skipTestIfFn(is_go_missing)(func) def getPlatform(): """Returns the target platform which the tests are running on.""" @@ -860,22 +775,6 @@ platform = 'netbsd' return platform -def getHostPlatform(): - """Returns the host platform running the test suite.""" - # Attempts to return a platform name matching a target Triple platform. - if sys.platform.startswith('linux'): - return 'linux' - elif sys.platform.startswith('win32'): - return 'windows' - elif sys.platform.startswith('darwin'): - return 'darwin' - elif sys.platform.startswith('freebsd'): - return 'freebsd' - elif sys.platform.startswith('netbsd'): - return 'netbsd' - else: - return sys.platform - def platformIsDarwin(): """Returns true if the OS triple for the selected platform is any valid apple OS""" return getPlatform() in getDarwinOSTriples() @@ -884,7 +783,7 @@ """Decorate the item to skip tests if binaries built on this host are incompatible.""" def is_host_incompatible_with_remote(self): host_arch = self.getLldbArchitecture() - host_platform = getHostPlatform() + host_platform = lldbplatformutil.getHostPlatform() target_arch = self.getArchitecture() target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform() if not (target_arch == 'x86_64' and host_arch == 'i386') and host_arch != target_arch: @@ -892,15 +791,15 @@ elif target_platform != host_platform: return "skipping because target is %s but host is %s" % (target_platform, host_platform) return None - return skipTestIfFn(is_host_incompatible_with_remote)(func) + return decorators.skipTestIfFn(is_host_incompatible_with_remote)(func) def skipIfHostPlatform(oslist): """Decorate the item to skip tests if running on one of the listed host platforms.""" - return skipIf(hostoslist=oslist) + return decorators.skipIf(hostoslist=oslist) def skipUnlessHostPlatform(oslist): """Decorate the item to skip tests unless running on one of the listed host platforms.""" - return skipIf(hostoslist=not_in(oslist)) + return decorators.skipIf(hostoslist=not_in(oslist)) def skipUnlessArch(archs): """Decorate the item to skip tests unless running on one of the listed architectures.""" @@ -935,85 +834,9 @@ return unittest2.skipUnless(getPlatform() in oslist, "requires on of %s" % (", ".join(oslist))) -# provide a function to skip on defined oslist, compiler version, and archs -# if none is specified for any argument, that argument won't be checked and thus means for all -# for example, -# @skipIf, skip for all platform/compiler/arch, -# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture -# @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 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): - 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 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) + return decorators.skipIf(bugnumber=bugnumber, debug_info=debug_info) def skipIfDWO(bugnumber=None): return skipIfDebugInfo(bugnumber, ["dwo"]) @@ -1024,45 +847,17 @@ def skipIfDsym(bugnumber=None): return skipIfDebugInfo(bugnumber, ["dsym"]) -def skipTestIfFn(expected_fn, bugnumber=None): - def skipTestIfFn_impl(func): - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipTestIfFn can only be used to decorate a test method") - - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - if does_function_require_self(expected_fn): - reason = expected_fn(self) - else: - reason = expected_fn() - if reason is not None: - 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: - return skipTestIfFn_impl - def skipIfGcc(func): """Decorate the item to skip tests that should be skipped if building with gcc .""" - return skipIf(compiler="gcc")(func) + return decorators.skipIf(compiler="gcc")(func) def skipIfIcc(func): """Decorate the item to skip tests that should be skipped if building with icc .""" - return skipIf(compiler="icc")(func) + return decorators.skipIf(compiler="icc")(func) def skipIfi386(func): """Decorate the item to skip tests that should be skipped if building 32-bit.""" - return skipIf(archs="i386")(func) + return decorators.skipIf(archs="i386")(func) def skipIfTargetAndroid(api_levels=None, archs=None): """Decorator to skip tests when the target is Android. @@ -1073,14 +868,14 @@ arch - A sequence of architecture names specifying the architectures for which a test is skipped. None means all architectures. """ - return skipTestIfFn(skip_for_android("skipping for android", api_levels, archs)) + return decorators.skipTestIfFn(skip_for_android("skipping for android", api_levels, archs)) def skipUnlessCompilerRt(func): """Decorate the item to skip tests if testing remotely.""" def is_compiler_rt_missing(): compilerRtPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "llvm","projects","compiler-rt") return "compiler-rt not found" if not os.path.exists(compilerRtPath) else None - return skipTestIfFn(is_compiler_rt_missing)(func) + return decorators.skipTestIfFn(is_compiler_rt_missing)(func) class _PlatformContext(object): """Value object class which contains platform-specific options.""" @@ -1509,7 +1304,7 @@ for hook in reversed(self.hooks): with recording(self, traceAlways) as sbuf: print("Executing tearDown hook:", getsource_if_available(hook), file=sbuf) - if does_function_require_self(hook): + if funcutils.requires_self(hook): hook(self) else: hook() # try the plain call and hope it works Index: packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py =================================================================== --- packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py +++ packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py @@ -18,8 +18,9 @@ import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class APIDefaultConstructorTestCase(TestBase): Index: packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py =================================================================== --- packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py +++ packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py @@ -9,8 +9,9 @@ import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class Disassemble_VST1_64(TestBase): Index: packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py =================================================================== --- packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py +++ packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py @@ -9,7 +9,9 @@ import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ThreadsStackTracesTestCase(TestBase): Index: packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py =================================================================== --- packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py +++ packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py @@ -9,7 +9,9 @@ import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil from lldbsuite.test.lldbutil import symbol_type_to_str class ModuleAndSectionAPIsTestCase(TestBase): Index: packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py =================================================================== --- packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py +++ packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py @@ -10,8 +10,9 @@ import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ValueAsLinkedListTestCase(TestBase): Index: packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py =================================================================== --- packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py +++ packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py @@ -9,8 +9,9 @@ import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TargetWatchAddressAPITestCase(TestBase): Index: packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py +++ packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py @@ -1,8 +1,9 @@ from __future__ import print_function import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestPlatformProcessConnect(gdbremote_testcase.GdbRemoteTestCaseBase): mydir = TestBase.compute_mydir(__file__)