<rdar://problem/12362092>
The decorators @expectedFailure (plain and special-case like i386, clang, ...) are modified to optionally take a bugnumber argument If such an argument is specified, the failure report (or unexpected success report) will include the information passed in as part of the message This is mostly useful for associating failures to issue IDs in issue management systems (e.g. the LLVM bugzilla) llvm-svn: 175942
This commit is contained in:
parent
942dbcc209
commit
e6cedc1296
|
|
@ -1459,14 +1459,14 @@ for ia in range(len(archs) if iterArchs else 1):
|
|||
else:
|
||||
failuresPerCategory[category] = 1
|
||||
|
||||
def addExpectedFailure(self, test, err):
|
||||
def addExpectedFailure(self, test, err, bugnumber):
|
||||
global sdir_has_content
|
||||
global parsable
|
||||
sdir_has_content = True
|
||||
super(LLDBTestResult, self).addExpectedFailure(test, err)
|
||||
super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber)
|
||||
method = getattr(test, "markExpectedFailure", None)
|
||||
if method:
|
||||
method()
|
||||
method(err, bugnumber)
|
||||
if parsable:
|
||||
self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
|
||||
|
||||
|
|
@ -1481,14 +1481,14 @@ for ia in range(len(archs) if iterArchs else 1):
|
|||
if parsable:
|
||||
self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason))
|
||||
|
||||
def addUnexpectedSuccess(self, test):
|
||||
def addUnexpectedSuccess(self, test, bugnumber):
|
||||
global sdir_has_content
|
||||
global parsable
|
||||
sdir_has_content = True
|
||||
super(LLDBTestResult, self).addUnexpectedSuccess(test)
|
||||
super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber)
|
||||
method = getattr(test, "markUnexpectedSuccess", None)
|
||||
if method:
|
||||
method()
|
||||
method(bugnumber)
|
||||
if parsable:
|
||||
self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
|
||||
|
||||
|
|
|
|||
|
|
@ -133,8 +133,7 @@ class FoundationTestCase2(TestBase):
|
|||
|
||||
self.runCmd("process continue")
|
||||
|
||||
@unittest2.expectedFailure
|
||||
# <rdar://problem/8741897> Expressions should support properties
|
||||
@unittest2.expectedFailure(8741897)
|
||||
def NSArray_expr(self):
|
||||
"""Test expression commands for NSArray."""
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
|
|
@ -160,8 +159,7 @@ class FoundationTestCase2(TestBase):
|
|||
patterns = ["\(int\) \$.* = 3"])
|
||||
self.runCmd("process continue")
|
||||
|
||||
@unittest2.expectedFailure
|
||||
# <rdar://problem/8741897> Expressions should support properties
|
||||
@unittest2.expectedFailure(8741897)
|
||||
def NSString_expr(self):
|
||||
"""Test expression commands for NSString."""
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
|
|
|
|||
|
|
@ -368,27 +368,41 @@ def dwarf_test(func):
|
|||
wrapper.__dwarf_test__ = True
|
||||
return wrapper
|
||||
|
||||
def expectedFailureCompiler(func, compiler):
|
||||
"""Decorate the item as an expectedFailure if the test compiler matches parameter compiler."""
|
||||
if isinstance(func, type) and issubclass(func, unittest2.TestCase):
|
||||
raise Exception("@expectedFailureClang can only be used to decorate a test method")
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
test_compiler = self.getCompiler()
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
if compiler in test_compiler:
|
||||
raise case._ExpectedFailure(sys.exc_info())
|
||||
else:
|
||||
raise
|
||||
|
||||
if compiler in test_compiler:
|
||||
raise case._UnexpectedSuccess
|
||||
return wrapper
|
||||
|
||||
def expectedFailureCompiler(bugnumber=None):
|
||||
if callable(bugnumber):
|
||||
@wraps(bugnumber)
|
||||
def expectedFailureCompiler_easy_wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
test_compiler = self.getCompiler()
|
||||
try:
|
||||
bugnumber(*args, **kwargs)
|
||||
except Exception:
|
||||
if compiler in test_compiler:
|
||||
raise _ExpectedFailure(sys.exc_info(),None)
|
||||
else:
|
||||
raise
|
||||
if compiler in test_compiler:
|
||||
raise case._UnexpectedSuccess(sys.exc_info(),None)
|
||||
return expectedFailureCompiler_easy_wrapper
|
||||
else:
|
||||
def expectedFailureCompiler_impl(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
test_compiler = self.getCompiler()
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
if compiler in test_compiler:
|
||||
raise _ExpectedFailure(sys.exc_info(),None)
|
||||
else:
|
||||
raise
|
||||
if compiler in test_compiler:
|
||||
raise case._UnexpectedSuccess(sys.exc_info(),None)
|
||||
return wrapper
|
||||
return expectedFailureCompiler_impl
|
||||
|
||||
def expectedFailureGcc(func):
|
||||
"""Decorate the item as a GCC only expectedFailure."""
|
||||
|
|
@ -402,47 +416,77 @@ def expectedFailureClang(func):
|
|||
raise Exception("@expectedFailureClang can only be used to decorate a test method")
|
||||
return expectedFailureCompiler(func, "clang")
|
||||
|
||||
def expectedFailurei386(func):
|
||||
"""Decorate the item as an i386 only expectedFailure."""
|
||||
if isinstance(func, type) and issubclass(func, unittest2.TestCase):
|
||||
raise Exception("@expectedFailurei386 can only be used to decorate a test method")
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
arch = self.getArchitecture()
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
if "i386" in arch:
|
||||
raise case._ExpectedFailure(sys.exc_info())
|
||||
else:
|
||||
raise
|
||||
def expectedFailurei386(bugnumber=None):
|
||||
if callable(bugnumber):
|
||||
@wraps(bugnumber)
|
||||
def expectedFailurei386_easy_wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
arch = self.getArchitecture()
|
||||
try:
|
||||
bugnumber(*args, **kwargs)
|
||||
except Exception:
|
||||
if "i386" in arch:
|
||||
raise _ExpectedFailure(sys.exc_info(),None)
|
||||
else:
|
||||
raise
|
||||
if "i386" in arch:
|
||||
raise case._UnexpectedSuccess(sys.exc_info(),None)
|
||||
return expectedFailurei386_easy_wrapper
|
||||
else:
|
||||
def expectedFailurei386_impl(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
arch = self.getArchitecture()
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
if "i386" in arch:
|
||||
raise _ExpectedFailure(sys.exc_info(),None)
|
||||
else:
|
||||
raise
|
||||
if "i386" in arch:
|
||||
raise case._UnexpectedSuccess(sys.exc_info(),None)
|
||||
return wrapper
|
||||
return expectedFailurei386_impl
|
||||
|
||||
if "i386" in arch:
|
||||
raise case._UnexpectedSuccess
|
||||
return wrapper
|
||||
|
||||
def expectedFailureLinux(func):
|
||||
"""Decorate the item as a Linux only expectedFailure."""
|
||||
if isinstance(func, type) and issubclass(func, unittest2.TestCase):
|
||||
raise Exception("@expectedFailureLinux can only be used to decorate a test method")
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
platform = sys.platform
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
if "linux" in platform:
|
||||
raise case._ExpectedFailure(sys.exc_info())
|
||||
else:
|
||||
raise
|
||||
|
||||
if "linux" in platform:
|
||||
raise case._UnexpectedSuccess
|
||||
return wrapper
|
||||
def expectedFailureLinux(bugnumber=None):
|
||||
if callable(bugnumber):
|
||||
@wraps(bugnumber)
|
||||
def expectedFailureLinux_easy_wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
platform = sys.platform
|
||||
try:
|
||||
bugnumber(*args, **kwargs)
|
||||
except Exception:
|
||||
if "linux" in platform:
|
||||
raise _ExpectedFailure(sys.exc_info(),None)
|
||||
else:
|
||||
raise
|
||||
if "linux" in platform:
|
||||
raise case._UnexpectedSuccess(sys.exc_info(),None)
|
||||
return expectedFailureLinux_easy_wrapper
|
||||
else:
|
||||
def expectedFailureLinux_impl(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
platform = sys.platform
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
if "linux" in platform:
|
||||
raise _ExpectedFailure(sys.exc_info(),None)
|
||||
else:
|
||||
raise
|
||||
if "linux" in platform:
|
||||
raise case._UnexpectedSuccess(sys.exc_info(),None)
|
||||
return wrapper
|
||||
return expectedFailureLinux_impl
|
||||
|
||||
def skipOnLinux(func):
|
||||
"""Decorate the item to skip tests that should be skipped on Linux."""
|
||||
|
|
@ -832,14 +876,17 @@ class Base(unittest2.TestCase):
|
|||
# Once by the Python unittest framework, and a second time by us.
|
||||
print >> sbuf, "FAIL"
|
||||
|
||||
def markExpectedFailure(self):
|
||||
def markExpectedFailure(self,err,bugnumber):
|
||||
"""Callback invoked when an expected failure/error occurred."""
|
||||
self.__expected__ = True
|
||||
with recording(self, False) as sbuf:
|
||||
# False because there's no need to write "expected failure" to the
|
||||
# stderr twice.
|
||||
# Once by the Python unittest framework, and a second time by us.
|
||||
print >> sbuf, "expected failure"
|
||||
if bugnumber == None:
|
||||
print >> sbuf, "expected failure"
|
||||
else:
|
||||
print >> sbuf, "expected failure (problem id:" + str(bugnumber) + ")"
|
||||
|
||||
def markSkippedTest(self):
|
||||
"""Callback invoked when a test is skipped."""
|
||||
|
|
@ -850,14 +897,17 @@ class Base(unittest2.TestCase):
|
|||
# Once by the Python unittest framework, and a second time by us.
|
||||
print >> sbuf, "skipped test"
|
||||
|
||||
def markUnexpectedSuccess(self):
|
||||
def markUnexpectedSuccess(self, bugnumber):
|
||||
"""Callback invoked when an unexpected success occurred."""
|
||||
self.__unexpected__ = True
|
||||
with recording(self, False) as sbuf:
|
||||
# False because there's no need to write "unexpected success" to the
|
||||
# stderr twice.
|
||||
# Once by the Python unittest framework, and a second time by us.
|
||||
print >> sbuf, "unexpected success"
|
||||
if bugnumber == None:
|
||||
print >> sbuf, "unexpected success"
|
||||
else:
|
||||
print >> sbuf, "unexpected success (problem id:" + str(bugnumber) + ")"
|
||||
|
||||
def dumpSessionInfo(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -36,16 +36,23 @@ class _ExpectedFailure(Exception):
|
|||
This is an implementation detail.
|
||||
"""
|
||||
|
||||
def __init__(self, exc_info):
|
||||
def __init__(self, exc_info, bugnumber=None):
|
||||
# can't use super because Python 2.4 exceptions are old style
|
||||
Exception.__init__(self)
|
||||
self.exc_info = exc_info
|
||||
self.bugnumber = bugnumber
|
||||
|
||||
class _UnexpectedSuccess(Exception):
|
||||
"""
|
||||
The test was supposed to fail, but it didn't!
|
||||
"""
|
||||
|
||||
def __init__(self, exc_info, bugnumber=None):
|
||||
# can't use super because Python 2.4 exceptions are old style
|
||||
Exception.__init__(self)
|
||||
self.exc_info = exc_info
|
||||
self.bugnumber = bugnumber
|
||||
|
||||
def _id(obj):
|
||||
return obj
|
||||
|
||||
|
|
@ -81,17 +88,27 @@ def skipUnless(condition, reason):
|
|||
return skip(reason)
|
||||
return _id
|
||||
|
||||
|
||||
def expectedFailure(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
raise _ExpectedFailure(sys.exc_info())
|
||||
raise _UnexpectedSuccess
|
||||
return wrapper
|
||||
|
||||
def expectedFailure(bugnumber=None):
|
||||
if callable(bugnumber):
|
||||
@wraps(bugnumber)
|
||||
def expectedFailure_easy_wrapper(*args, **kwargs):
|
||||
try:
|
||||
bugnumber(*args, **kwargs)
|
||||
except Exception:
|
||||
raise _ExpectedFailure(sys.exc_info(),None)
|
||||
raise _UnexpectedSuccess(sys.exc_info(),None)
|
||||
return expectedFailure_easy_wrapper
|
||||
else:
|
||||
def expectedFailure_impl(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except Exception:
|
||||
raise _ExpectedFailure(sys.exc_info(),bugnumber)
|
||||
raise _UnexpectedSuccess(sys.exc_info(),bugnumber)
|
||||
return wrapper
|
||||
return expectedFailure_impl
|
||||
|
||||
class _AssertRaisesContext(object):
|
||||
"""A context manager used to implement TestCase.assertRaises* methods."""
|
||||
|
|
@ -343,15 +360,15 @@ class TestCase(unittest.TestCase):
|
|||
except _ExpectedFailure, e:
|
||||
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
|
||||
if addExpectedFailure is not None:
|
||||
addExpectedFailure(self, e.exc_info)
|
||||
addExpectedFailure(self, e.exc_info, e.bugnumber)
|
||||
else:
|
||||
warnings.warn("Use of a TestResult without an addExpectedFailure method is deprecated",
|
||||
DeprecationWarning)
|
||||
result.addSuccess(self)
|
||||
except _UnexpectedSuccess:
|
||||
except _UnexpectedSuccess, x:
|
||||
addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
|
||||
if addUnexpectedSuccess is not None:
|
||||
addUnexpectedSuccess(self)
|
||||
addUnexpectedSuccess(self, x.bugnumber)
|
||||
else:
|
||||
warnings.warn("Use of a TestResult without an addUnexpectedSuccess method is deprecated",
|
||||
DeprecationWarning)
|
||||
|
|
|
|||
|
|
@ -123,13 +123,13 @@ class TestResult(unittest.TestResult):
|
|||
"""Called when a test is skipped."""
|
||||
self.skipped.append((test, reason))
|
||||
|
||||
def addExpectedFailure(self, test, err):
|
||||
def addExpectedFailure(self, test, err, bugnumber):
|
||||
"""Called when an expected failure/error occured."""
|
||||
self.expectedFailures.append(
|
||||
(test, self._exc_info_to_string(err, test)))
|
||||
|
||||
@failfast
|
||||
def addUnexpectedSuccess(self, test):
|
||||
def addUnexpectedSuccess(self, test, bugnumber):
|
||||
"""Called when a test was expected to fail, but succeed."""
|
||||
self.unexpectedSuccesses.append(test)
|
||||
|
||||
|
|
|
|||
|
|
@ -92,12 +92,12 @@ class TextTestResult(result.TestResult):
|
|||
super(TextTestResult, self).addSkip(test, reason)
|
||||
self.newTestResult(test,"s","skipped %r" % (reason,))
|
||||
|
||||
def addExpectedFailure(self, test, err):
|
||||
super(TextTestResult, self).addExpectedFailure(test, err)
|
||||
def addExpectedFailure(self, test, err, bugnumber):
|
||||
super(TextTestResult, self).addExpectedFailure(test, err, bugnumber)
|
||||
self.newTestResult(test,"x","expected failure")
|
||||
|
||||
def addUnexpectedSuccess(self, test):
|
||||
super(TextTestResult, self).addUnexpectedSuccess(test)
|
||||
def addUnexpectedSuccess(self, test, bugnumber):
|
||||
super(TextTestResult, self).addUnexpectedSuccess(test, bugnumber)
|
||||
self.newTestResult(test,"u","unexpected success")
|
||||
|
||||
def printErrors(self):
|
||||
|
|
|
|||
Loading…
Reference in New Issue