262 lines
6.4 KiB
Python
262 lines
6.4 KiB
Python
# -*- test-case-name: twisted.trial.test.test_tests -*-
|
|
# Copyright (c) Twisted Matrix Laboratories.
|
|
# See LICENSE for details.
|
|
|
|
"""
|
|
Definitions of test cases with various interesting error-related behaviors, to
|
|
be used by test modules to exercise different features of trial's test runner.
|
|
|
|
See the L{twisted.trial.test.test_tests} module docstring for details about how
|
|
this code is arranged.
|
|
|
|
Some of these tests are also used by L{twisted.trial._dist.test}.
|
|
"""
|
|
|
|
|
|
from unittest import skipIf
|
|
|
|
from twisted.internet import defer, protocol, reactor
|
|
from twisted.internet.task import deferLater
|
|
from twisted.trial import unittest, util
|
|
|
|
|
|
class FoolishError(Exception):
|
|
pass
|
|
|
|
|
|
class LargeError(Exception):
|
|
"""
|
|
An exception which has a string representation of at least a specified
|
|
number of characters.
|
|
"""
|
|
|
|
def __init__(self, minSize: int) -> None:
|
|
Exception.__init__(self)
|
|
self.minSize = minSize
|
|
|
|
def __str__(self):
|
|
large = "x" * self.minSize
|
|
return f"LargeError<I fail: {large}>"
|
|
|
|
|
|
class FailureInSetUpMixin:
|
|
def setUp(self):
|
|
raise FoolishError("I am a broken setUp method")
|
|
|
|
def test_noop(self):
|
|
pass
|
|
|
|
|
|
class SynchronousTestFailureInSetUp(FailureInSetUpMixin, unittest.SynchronousTestCase):
|
|
pass
|
|
|
|
|
|
class AsynchronousTestFailureInSetUp(FailureInSetUpMixin, unittest.TestCase):
|
|
pass
|
|
|
|
|
|
class FailureInTearDownMixin:
|
|
def tearDown(self):
|
|
raise FoolishError("I am a broken tearDown method")
|
|
|
|
def test_noop(self):
|
|
pass
|
|
|
|
|
|
class SynchronousTestFailureInTearDown(
|
|
FailureInTearDownMixin, unittest.SynchronousTestCase
|
|
):
|
|
pass
|
|
|
|
|
|
class AsynchronousTestFailureInTearDown(FailureInTearDownMixin, unittest.TestCase):
|
|
pass
|
|
|
|
|
|
class FailureButTearDownRunsMixin:
|
|
"""
|
|
A test fails, but its L{tearDown} still runs.
|
|
"""
|
|
|
|
tornDown = False
|
|
|
|
def tearDown(self):
|
|
self.tornDown = True
|
|
|
|
def test_fails(self):
|
|
"""
|
|
A test that fails.
|
|
"""
|
|
raise FoolishError("I am a broken test")
|
|
|
|
|
|
class SynchronousTestFailureButTearDownRuns(
|
|
FailureButTearDownRunsMixin, unittest.SynchronousTestCase
|
|
):
|
|
pass
|
|
|
|
|
|
class AsynchronousTestFailureButTearDownRuns(
|
|
FailureButTearDownRunsMixin, unittest.TestCase
|
|
):
|
|
pass
|
|
|
|
|
|
class TestRegularFail(unittest.SynchronousTestCase):
|
|
def test_fail(self):
|
|
self.fail("I fail")
|
|
|
|
def test_subfail(self):
|
|
self.subroutine()
|
|
|
|
def subroutine(self):
|
|
self.fail("I fail inside")
|
|
|
|
|
|
class TestAsynchronousFail(unittest.TestCase):
|
|
"""
|
|
Test failures for L{unittest.TestCase} based classes.
|
|
"""
|
|
|
|
text = "I fail"
|
|
|
|
def test_fail(self) -> defer.Deferred[None]:
|
|
"""
|
|
A test which fails in the callback of the returned L{defer.Deferred}.
|
|
"""
|
|
return deferLater(reactor, 0, self.fail, "I fail later") # type: ignore[arg-type]
|
|
|
|
def test_failGreaterThan64k(self) -> defer.Deferred[None]:
|
|
"""
|
|
A test which fails in the callback of the returned L{defer.Deferred}
|
|
with a very long string.
|
|
"""
|
|
return deferLater(reactor, 0, self.fail, "I fail later: " + "x" * 2**16) # type: ignore[arg-type]
|
|
|
|
def test_exception(self) -> None:
|
|
"""
|
|
A test which raises an exception synchronously.
|
|
"""
|
|
raise Exception(self.text)
|
|
|
|
def test_exceptionGreaterThan64k(self) -> None:
|
|
"""
|
|
A test which raises an exception with a long string representation
|
|
synchronously.
|
|
"""
|
|
raise LargeError(2**16)
|
|
|
|
def test_exceptionGreaterThan64kEncoded(self) -> None:
|
|
"""
|
|
A test which synchronously raises an exception with a long string
|
|
representation including non-ascii content.
|
|
"""
|
|
# The exception text itself is not greater than 64k but SNOWMAN
|
|
# encodes to 3 bytes with UTF-8 so the length of the UTF-8 encoding of
|
|
# the string representation of this exception will be greater than 2
|
|
# ** 16.
|
|
raise Exception("\N{SNOWMAN}" * 2**15)
|
|
|
|
|
|
class ErrorTest(unittest.SynchronousTestCase):
|
|
"""
|
|
A test case which has a L{test_foo} which will raise an error.
|
|
|
|
@ivar ran: boolean indicating whether L{test_foo} has been run.
|
|
"""
|
|
|
|
ran = False
|
|
|
|
def test_foo(self):
|
|
"""
|
|
Set C{self.ran} to True and raise a C{ZeroDivisionError}
|
|
"""
|
|
self.ran = True
|
|
1 / 0
|
|
|
|
|
|
@skipIf(True, "skipping this test")
|
|
class TestSkipTestCase(unittest.SynchronousTestCase):
|
|
pass
|
|
|
|
|
|
class DelayedCall(unittest.TestCase):
|
|
hiddenExceptionMsg = "something blew up"
|
|
|
|
def go(self):
|
|
raise RuntimeError(self.hiddenExceptionMsg)
|
|
|
|
def testHiddenException(self):
|
|
"""
|
|
What happens if an error is raised in a DelayedCall and an error is
|
|
also raised in the test?
|
|
|
|
L{test_reporter.ErrorReportingTests.testHiddenException} checks that
|
|
both errors get reported.
|
|
|
|
Note that this behaviour is deprecated. A B{real} test would return a
|
|
Deferred that got triggered by the callLater. This would guarantee the
|
|
delayed call error gets reported.
|
|
"""
|
|
reactor.callLater(0, self.go)
|
|
reactor.iterate(0.01)
|
|
self.fail("Deliberate failure to mask the hidden exception")
|
|
|
|
testHiddenException.suppress = [ # type: ignore[attr-defined]
|
|
util.suppress(
|
|
message=r"reactor\.iterate cannot be used.*", category=DeprecationWarning
|
|
)
|
|
]
|
|
|
|
|
|
class ReactorCleanupTests(unittest.TestCase):
|
|
def test_leftoverPendingCalls(self):
|
|
def _():
|
|
print("foo!")
|
|
|
|
reactor.callLater(10000.0, _)
|
|
|
|
|
|
class SocketOpenTest(unittest.TestCase):
|
|
def test_socketsLeftOpen(self):
|
|
f = protocol.Factory()
|
|
f.protocol = protocol.Protocol
|
|
reactor.listenTCP(0, f)
|
|
|
|
|
|
class TimingOutDeferred(unittest.TestCase):
|
|
def test_alpha(self):
|
|
pass
|
|
|
|
def test_deferredThatNeverFires(self):
|
|
self.methodCalled = True
|
|
d = defer.Deferred()
|
|
return d
|
|
|
|
def test_omega(self):
|
|
pass
|
|
|
|
|
|
def unexpectedException(self):
|
|
"""i will raise an unexpected exception...
|
|
... *CAUSE THAT'S THE KINDA GUY I AM*
|
|
|
|
>>> 1/0
|
|
"""
|
|
|
|
|
|
class EventuallyFailingTestCase(unittest.SynchronousTestCase):
|
|
"""
|
|
A test suite that fails after it is run a few times.
|
|
"""
|
|
|
|
n: int = 0
|
|
|
|
def test_it(self):
|
|
"""
|
|
Run successfully a few times and then fail forever after.
|
|
"""
|
|
self.n += 1
|
|
if self.n >= 5:
|
|
self.fail("eventually failing")
|