def _bail(self): from twisted.internet import reactor, utils d = defer.Deferred() reactor.addSystemEventTrigger('after', 'shutdown', lambda: d.callback(None)) reactor.fireSystemEvent('shutdown') # radix's suggestion treactor = interfaces.IReactorThreads(reactor, None) if treactor is not None: treactor.suggestThreadPoolSize(0) utils.suppressWarnings(lambda: util.wait(d), (['ignore', 'Do NOT use wait.*'], {}))
def _bail(self): from twisted.internet import reactor, utils d = defer.Deferred() reactor.addSystemEventTrigger('after', 'shutdown', lambda: d.callback(None)) reactor.fireSystemEvent('shutdown') # radix's suggestion treactor = interfaces.IReactorThreads(reactor, None) if treactor is not None: treactor.suggestThreadPoolSize(0) # As long as TestCase does crap stuff with the reactor we need to # manually shutdown the reactor here, and that requires util.wait # :( # so that the shutdown event completes utils.suppressWarnings(lambda: util.wait(d), (['ignore', 'Do NOT use wait.*'], {}))
def _run(self, methodName, result): from twisted.internet import reactor timeout = self.getTimeout() def onTimeout(d): e = defer.TimeoutError("%r (%s) still running at %s secs" % (self, methodName, timeout)) f = failure.Failure(e) # try to errback the deferred that the test returns (for no gorram # reason) (see issue1005 and test_errorPropagation in # test_deferred) try: d.errback(f) except defer.AlreadyCalledError: # if the deferred has been called already but the *back chain # is still unfinished, crash the reactor and report timeout # error ourself. reactor.crash() self._timedOut = True # see self._wait todo = self.getTodo() if todo is not None and todo.expected(f): result.addExpectedFailure(self, f, todo) else: result.addError(self, f) onTimeout = utils.suppressWarnings( onTimeout, util.suppress(category=DeprecationWarning)) method = getattr(self, methodName) d = defer.maybeDeferred( utils.runWithWarningsSuppressed, self._getSuppress(), method) call = reactor.callLater(timeout, onTimeout, d) d.addBoth(lambda x : call.active() and call.cancel() or x) return d
def test_suppressWarnings(self): """ L{utils.suppressWarnings} decorates a function so that the given warnings are suppressed. """ result = [] def showwarning(self, *a, **kw): result.append((a, kw)) self.patch(warnings, "showwarning", showwarning) def f(msg): warnings.warn(msg) g = utils.suppressWarnings( f, (('ignore', ), dict(message="This is message"))) # Start off with a sanity check - calling the original function # should emit the warning. f("Sanity check message") self.assertEqual(len(result), 1) # Now that that's out of the way, call the wrapped function, and # make sure no new warnings show up. g("This is message") self.assertEqual(len(result), 1) # Finally, emit another warning which should not be ignored, and # make sure it is not. g("Unignored message") self.assertEqual(len(result), 2)
class TestTreeReporter(unittest.TestCase): def setUp(self): from twisted.trial.test import sample self.test = sample.FooTest('test_foo') self.stream = StringIO.StringIO() self.result = reporter.TreeReporter(self.stream) self.result._colorizer = MockColorizer(self.stream) self.log = self.result._colorizer.log def makeError(self): try: 1 / 0 except ZeroDivisionError: f = failure.Failure() return f def test_cleanupError(self): """ Run cleanupErrors and check that the output is correct, and colored correctly. """ f = self.makeError() self.result.cleanupErrors(f) color, text = self.log[0] self.assertEqual(color.strip(), self.result.ERROR) self.assertEqual(text.strip(), 'cleanup errors') color, text = self.log[1] self.assertEqual(color.strip(), self.result.ERROR) self.assertEqual(text.strip(), '[ERROR]') test_cleanupError = suppressWarnings( test_cleanupError, util.suppress(category=reporter.BrokenTestCaseWarning))
def test_suppressWarnings(self): """ L{utils.suppressWarnings} decorates a function so that the given warnings are suppressed. """ result = [] def showwarning(self, *a, **kw): result.append((a, kw)) self.patch(warnings, "showwarning", showwarning) def f(msg): warnings.warn(msg) g = utils.suppressWarnings(f, (('ignore',), dict(message="This is message"))) # Start off with a sanity check - calling the original function # should emit the warning. f("Sanity check message") self.assertEqual(len(result), 1) # Now that that's out of the way, call the wrapped function, and # make sure no new warnings show up. g("This is message") self.assertEqual(len(result), 1) # Finally, emit another warning which should not be ignored, and # make sure it is not. g("Unignored message") self.assertEqual(len(result), 2)
def _run(self, methodName, result): # Difference from unittest.TestCase: we use maybe_deferred_with_noncleaning_failure in order to avoid having # t.i.defer mangle our locals and globals timeout = self.getTimeout() def onTimeout(d): e = defer.TimeoutError("%r (%s) still running at %s secs" % (self, methodName, timeout)) f = failure.Failure(e) # try to errback the deferred that the test returns (for no gorram # reason) (see issue1005 and test_errorPropagation in # test_deferred) try: d.errback(f) except defer.AlreadyCalledError: # if the deferred has been called already but the *back chain # is still unfinished, crash the reactor and report timeout # error ourself. # reactor.crash() # TODO: decide what to do wrt timeouts -- Njal self._timedOut = True # see self._wait todo = self.getTodo() if todo is not None and todo.expected(f): result.addExpectedFailure(self, f, todo) else: result.addError(self, f) onTimeout = utils.suppressWarnings( onTimeout, util.suppress(category=DeprecationWarning)) method = getattr(self, methodName) d = status_util.maybe_deferred_with_noncleaning_failure(utils.runWithWarningsSuppressed, self.getSuppress(), method) call = reactor.callLater(timeout, onTimeout, d) d.addBoth(lambda x : call.active() and call.cancel() or x) return d
def _run(self, methodName, result): from twisted.internet import reactor timeout = self.getTimeout() def onTimeout(d): e = defer.TimeoutError("%r (%s) still running at %s secs" % (self, methodName, timeout)) f = failure.Failure(e) # try to errback the deferred that the test returns (for no gorram # reason) (see issue1005 and test_errorPropagation in # test_deferred) try: d.errback(f) except defer.AlreadyCalledError: # if the deferred has been called already but the *back chain # is still unfinished, crash the reactor and report timeout # error ourself. reactor.crash() self._timedOut = True # see self._wait todo = self.getTodo() if todo is not None and todo.expected(f): result.addExpectedFailure(self, f, todo) else: result.addError(self, f) onTimeout = utils.suppressWarnings( onTimeout, util.suppress(category=DeprecationWarning)) method = getattr(self, methodName) d = defer.maybeDeferred(utils.runWithWarningsSuppressed, self._getSuppress(), method) call = reactor.callLater(timeout, onTimeout, d) d.addBoth(lambda x: call.active() and call.cancel() or x) return d
class AuthorizationTestCase(unittest.TestCase): def setUp(self): self.proxy = sip.RegisterProxy(host="intarweb.us") self.proxy.authorizers = self.proxy.authorizers.copy() self.proxy.authorizers['digest'] = FakeDigestAuthorizer() self.registry = FakeRegistry("intarweb.us") self.proxy.registry = self.proxy.locator = self.registry self.transport = proto_helpers.FakeDatagramTransport() self.proxy.transport = self.transport r = TestRealm() p = cred.portal.Portal(r) c = cred.checkers.InMemoryUsernamePasswordDatabaseDontUse() c.addUser('*****@*****.**', 'password') p.registerChecker(c) self.proxy.portal = p setUp = utils.suppressWarnings( setUp, util.suppress( category=DeprecationWarning, message=r'twisted.protocols.sip.DigestAuthorizer was deprecated')) def tearDown(self): for d, uri in self.registry.users.values(): d.cancel() del self.proxy def testChallenge(self): self.proxy.datagramReceived(registerRequest, ("127.0.0.1", 5632)) self.assertEqual(self.transport.written[-1], ((challengeResponse, ("127.0.0.1", 5632)))) self.transport.written = [] self.proxy.datagramReceived(authRequest, ("127.0.0.1", 5632)) self.assertEqual(self.transport.written[-1], ((okResponse, ("127.0.0.1", 5632)))) testChallenge.suppress = [ util.suppress( category=DeprecationWarning, message=r'twisted.protocols.sip.DigestAuthorizer was deprecated'), util.suppress( category=DeprecationWarning, message=r'twisted.protocols.sip.DigestedCredentials was deprecated' ), util.suppress( category=DeprecationWarning, message=r'twisted.protocols.sip.DigestCalcHA1 was deprecated'), util.suppress( category=DeprecationWarning, message=r'twisted.protocols.sip.DigestCalcResponse was deprecated') ]
def testSuppressWarnings(self): def f(msg): warnings.warn(msg) g = utils.suppressWarnings(f, (('ignore',), dict(message="This is message"))) f("Sanity check message") self.assertEquals(len(self.warnings), 1) g("This is message") self.assertEquals(len(self.warnings), 1) g("Unignored message") self.assertEquals(len(self.warnings), 2)
def test_twoWaitImplementations(self): tc = TestMktemp('test_name') tc._timedOut = False # whitebox d = defer.Deferred() def _runsInsideWait(r): d = defer.Deferred() self.assertRaises(util.WaitIsNotReentrantError, util.wait, d) d.addCallback(utils.suppressWarnings(_runsInsideWait, *suppress)) reactor.callLater(0, d.callback, 'yo') tc._wait(d)
def test_twoWaitImplementations(self): # If this test times out, then wait is being re-entered. tc = TestMktemp('test_name') tc._timedOut = False # whitebox d = defer.Deferred() def _runsInsideWait(r): d = defer.Deferred() self.assertRaises(util.WaitIsNotReentrantError, util.wait, d) d.addCallback(utils.suppressWarnings(_runsInsideWait, *suppress)) reactor.callLater(0, d.callback, 'yo') tc._wait(d)
def testSuppressWarnings(self): def f(msg): warnings.warn(msg) g = utils.suppressWarnings(f, (('ignore',), dict(message="This is message"))) # Start off with a sanity check - calling the original function # should emit the warning. f("Sanity check message") self.assertEquals(len(self.warnings), 1) # Now that that's out of the way, call the wrapped function, and # make sure no new warnings show up. g("This is message") self.assertEquals(len(self.warnings), 1) # Finally, emit another warning which should not be ignored, and # make sure it is not. g("Unignored message") self.assertEquals(len(self.warnings), 2)
class LiveTest(unittest.TestCase): def setUp(self): self.proxy = sip.RegisterProxy(host="127.0.0.1") self.registry = sip.InMemoryRegistry("bell.example.com") self.proxy.registry = self.proxy.locator = self.registry self.serverPort = reactor.listenUDP(0, self.proxy, interface="127.0.0.1") self.client = Client() self.clientPort = reactor.listenUDP(0, self.client, interface="127.0.0.1") self.serverAddress = (self.serverPort.getHost().host, self.serverPort.getHost().port) setUp = utils.suppressWarnings( setUp, util.suppress( category=DeprecationWarning, message=r'twisted.protocols.sip.DigestAuthorizer was deprecated')) def tearDown(self): for d, uri in self.registry.users.values(): d.cancel() d1 = defer.maybeDeferred(self.clientPort.stopListening) d2 = defer.maybeDeferred(self.serverPort.stopListening) return defer.gatherResults([d1, d2]) def testRegister(self): p = self.clientPort.getHost().port r = sip.Request("REGISTER", "sip:bell.example.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "sip:[email protected]:%d" % p) r.addHeader("via", sip.Via("127.0.0.1", port=p).toString()) self.client.sendMessage( sip.URL(host="127.0.0.1", port=self.serverAddress[1]), r) d = self.client.deferred def check(received): self.assertEqual(len(received), 1) r = received[0] self.assertEqual(r.code, 200) d.addCallback(check) return d def test_amoralRPort(self): """ rport is allowed without a value, apparently because server implementors might be too stupid to check the received port against 5060 and see if they're equal, and because client implementors might be too stupid to bind to port 5060, or set a value on the rport parameter they send if they bind to another port. """ p = self.clientPort.getHost().port r = sip.Request("REGISTER", "sip:bell.example.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "sip:[email protected]:%d" % p) r.addHeader("via", sip.Via("127.0.0.1", port=p, rport=True).toString()) warnings = self.flushWarnings( offendingFunctions=[self.test_amoralRPort]) self.assertEqual(len(warnings), 1) self.assertEqual(warnings[0]['message'], 'rport=True is deprecated since Twisted 9.0.') self.assertEqual(warnings[0]['category'], DeprecationWarning) self.client.sendMessage( sip.URL(host="127.0.0.1", port=self.serverAddress[1]), r) d = self.client.deferred def check(received): self.assertEqual(len(received), 1) r = received[0] self.assertEqual(r.code, 200) d.addCallback(check) return d
class RegistrationTestCase(unittest.TestCase): def setUp(self): self.proxy = sip.RegisterProxy(host="127.0.0.1") self.registry = sip.InMemoryRegistry("bell.example.com") self.proxy.registry = self.proxy.locator = self.registry self.sent = [] self.proxy.sendMessage = lambda dest, msg: self.sent.append( (dest, msg)) setUp = utils.suppressWarnings( setUp, util.suppress( category=DeprecationWarning, message=r'twisted.protocols.sip.DigestAuthorizer was deprecated')) def tearDown(self): for d, uri in self.registry.users.values(): d.cancel() del self.proxy def register(self): r = sip.Request("REGISTER", "sip:bell.example.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "sip:[email protected]:1234") r.addHeader("via", sip.Via("client.com").toString()) self.proxy.datagramReceived(r.toString(), ("client.com", 5060)) def unregister(self): r = sip.Request("REGISTER", "sip:bell.example.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "*") r.addHeader("via", sip.Via("client.com").toString()) r.addHeader("expires", "0") self.proxy.datagramReceived(r.toString(), ("client.com", 5060)) def testRegister(self): self.register() dest, m = self.sent[0] self.assertEqual((dest.host, dest.port), ("client.com", 5060)) self.assertEqual(m.code, 200) self.assertEqual(m.headers["via"], ["SIP/2.0/UDP client.com:5060"]) self.assertEqual(m.headers["to"], ["sip:[email protected]"]) self.assertEqual(m.headers["contact"], ["sip:[email protected]:5060"]) self.failUnless( int(m.headers["expires"][0]) in (3600, 3601, 3599, 3598)) self.assertEqual(len(self.registry.users), 1) dc, uri = self.registry.users["joe"] self.assertEqual(uri.toString(), "sip:[email protected]:5060") d = self.proxy.locator.getAddress( sip.URL(username="******", host="bell.example.com")) d.addCallback(lambda desturl: (desturl.host, desturl.port)) d.addCallback(self.assertEqual, ('client.com', 5060)) return d def testUnregister(self): self.register() self.unregister() dest, m = self.sent[1] self.assertEqual((dest.host, dest.port), ("client.com", 5060)) self.assertEqual(m.code, 200) self.assertEqual(m.headers["via"], ["SIP/2.0/UDP client.com:5060"]) self.assertEqual(m.headers["to"], ["sip:[email protected]"]) self.assertEqual(m.headers["contact"], ["sip:[email protected]:5060"]) self.assertEqual(m.headers["expires"], ["0"]) self.assertEqual(self.registry.users, {}) def addPortal(self): r = TestRealm() p = cred.portal.Portal(r) c = cred.checkers.InMemoryUsernamePasswordDatabaseDontUse() c.addUser('[email protected]', 'passXword') p.registerChecker(c) self.proxy.portal = p def testFailedAuthentication(self): self.addPortal() self.register() self.assertEqual(len(self.registry.users), 0) self.assertEqual(len(self.sent), 1) dest, m = self.sent[0] self.assertEqual(m.code, 401) def test_basicAuthentication(self): """ Test that registration with basic authentication succeeds. """ self.addPortal() self.proxy.authorizers = self.proxy.authorizers.copy() self.proxy.authorizers['basic'] = sip.BasicAuthorizer() warnings = self.flushWarnings( offendingFunctions=[self.test_basicAuthentication]) self.assertEqual(len(warnings), 1) self.assertEqual( warnings[0]['message'], "twisted.protocols.sip.BasicAuthorizer was deprecated in " "Twisted 9.0.0") self.assertEqual(warnings[0]['category'], DeprecationWarning) r = sip.Request("REGISTER", "sip:bell.example.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "sip:[email protected]:1234") r.addHeader("via", sip.Via("client.com").toString()) r.addHeader("authorization", "Basic " + "userXname:passXword".encode('base64')) self.proxy.datagramReceived(r.toString(), ("client.com", 5060)) self.assertEqual(len(self.registry.users), 1) self.assertEqual(len(self.sent), 1) dest, m = self.sent[0] self.assertEqual(m.code, 200) def test_failedBasicAuthentication(self): """ Failed registration with basic authentication results in an unauthorized error response. """ self.addPortal() self.proxy.authorizers = self.proxy.authorizers.copy() self.proxy.authorizers['basic'] = sip.BasicAuthorizer() warnings = self.flushWarnings( offendingFunctions=[self.test_failedBasicAuthentication]) self.assertEqual(len(warnings), 1) self.assertEqual( warnings[0]['message'], "twisted.protocols.sip.BasicAuthorizer was deprecated in " "Twisted 9.0.0") self.assertEqual(warnings[0]['category'], DeprecationWarning) r = sip.Request("REGISTER", "sip:bell.example.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "sip:[email protected]:1234") r.addHeader("via", sip.Via("client.com").toString()) r.addHeader("authorization", "Basic " + "userXname:password".encode('base64')) self.proxy.datagramReceived(r.toString(), ("client.com", 5060)) self.assertEqual(len(self.registry.users), 0) self.assertEqual(len(self.sent), 1) dest, m = self.sent[0] self.assertEqual(m.code, 401) def testWrongDomainRegister(self): r = sip.Request("REGISTER", "sip:wrong.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "sip:[email protected]:1234") r.addHeader("via", sip.Via("client.com").toString()) self.proxy.datagramReceived(r.toString(), ("client.com", 5060)) self.assertEqual(len(self.sent), 0) def testWrongToDomainRegister(self): r = sip.Request("REGISTER", "sip:bell.example.com") r.addHeader("to", "sip:[email protected]") r.addHeader("contact", "sip:[email protected]:1234") r.addHeader("via", sip.Via("client.com").toString()) self.proxy.datagramReceived(r.toString(), ("client.com", 5060)) self.assertEqual(len(self.sent), 0) def testWrongDomainLookup(self): self.register() url = sip.URL(username="******", host="foo.com") d = self.proxy.locator.getAddress(url) self.assertFailure(d, LookupError) return d def testNoContactLookup(self): self.register() url = sip.URL(username="******", host="bell.example.com") d = self.proxy.locator.getAddress(url) self.assertFailure(d, LookupError) return d
class TestTreeReporter(unittest.TestCase): def setUp(self): from twisted.trial.test import sample self.test = sample.FooTest('test_foo') self.stream = StringIO.StringIO() self.result = reporter.TreeReporter(self.stream) self.result._colorizer = MockColorizer(self.stream) self.log = self.result._colorizer.log def makeError(self): try: 1 / 0 except ZeroDivisionError: f = Failure() return f def test_cleanupError(self): """ Run cleanupErrors and check that the output is correct, and colored correctly. """ f = self.makeError() self.result.cleanupErrors(f) color, text = self.log[0] self.assertEqual(color.strip(), self.result.ERROR) self.assertEqual(text.strip(), 'cleanup errors') color, text = self.log[1] self.assertEqual(color.strip(), self.result.ERROR) self.assertEqual(text.strip(), '[ERROR]') test_cleanupError = suppressWarnings( test_cleanupError, util.suppress(category=reporter.BrokenTestCaseWarning), util.suppress(category=DeprecationWarning)) def test_upDownError(self): """ Run upDownError and check that the output is correct and colored correctly. """ self.result.upDownError("method", None, None, False) color, text = self.log[0] self.assertEqual(color.strip(), self.result.ERROR) self.assertEqual(text.strip(), 'method') test_upDownError = suppressWarnings( test_upDownError, util.suppress(category=DeprecationWarning, message="upDownError is deprecated in Twisted 8.0.")) def test_summaryColoredSuccess(self): """ The summary in case of success should have a good count of successes and be colored properly. """ self.result.addSuccess(self.test) self.result.done() self.assertEquals(self.log[1], (self.result.SUCCESS, 'PASSED')) self.assertEquals(self.stream.getvalue().splitlines()[-1].strip(), "(successes=1)") def test_summaryColoredFailure(self): """ The summary in case of failure should have a good count of errors and be colored properly. """ try: raise RuntimeError('foo') except RuntimeError, excValue: self.result.addError(self, sys.exc_info()) self.result.done() self.assertEquals(self.log[1], (self.result.FAILURE, 'FAILED')) self.assertEquals(self.stream.getvalue().splitlines()[-1].strip(), "(errors=1)")
def _wait(self, d, running=_wait_is_running): """Take a Deferred that only ever callbacks. Block until it happens. """ if running: raise RuntimeError("_wait is not reentrant") from twisted.internet import reactor results = [] def append(any): if results is not None: results.append(any) def crash(ign): if results is not None: reactor.crash() crash = utils.suppressWarnings( crash, util.suppress(message=r'reactor\.crash cannot be used.*', category=DeprecationWarning)) def stop(): reactor.crash() stop = utils.suppressWarnings( stop, util.suppress(message=r'reactor\.crash cannot be used.*', category=DeprecationWarning)) running.append(None) try: d.addBoth(append) if results: # d might have already been fired, in which case append is # called synchronously. Avoid any reactor stuff. return d.addBoth(crash) reactor.stop = stop try: reactor.run() finally: del reactor.stop # If the reactor was crashed elsewhere due to a timeout, hopefully # that crasher also reported an error. Just return. # _timedOut is most likely to be set when d has fired but hasn't # completed its callback chain (see self._run) if results or self._timedOut: #defined in run() and _run() return # If the timeout didn't happen, and we didn't get a result or # a failure, then the user probably aborted the test, so let's # just raise KeyboardInterrupt. # FIXME: imagine this: # web/test/test_webclient.py: # exc = self.assertRaises(error.Error, wait, method(url)) # # wait() will raise KeyboardInterrupt, and assertRaises will # swallow it. Therefore, wait() raising KeyboardInterrupt is # insufficient to stop trial. A suggested solution is to have # this code set a "stop trial" flag, or otherwise notify trial # that it should really try to stop as soon as possible. raise KeyboardInterrupt() finally: results = None running.pop()
def _wait(self, d, running=_wait_is_running): """Take a Deferred that only ever callbacks. Block until it happens.""" if running: raise RuntimeError("_wait is not reentrant") from twisted.internet import reactor results = [] def append(any): if results is not None: results.append(any) def crash(ign): if results is not None: reactor.crash() crash = utils.suppressWarnings( crash, util.suppress( message=r"reactor\.crash cannot be used.*", category=DeprecationWarning ), ) def stop(): reactor.crash() stop = utils.suppressWarnings( stop, util.suppress( message=r"reactor\.crash cannot be used.*", category=DeprecationWarning ), ) running.append(None) try: d.addBoth(append) if results: # d might have already been fired, in which case append is # called synchronously. Avoid any reactor stuff. return d.addBoth(crash) reactor.stop = stop try: reactor.run() finally: del reactor.stop # If the reactor was crashed elsewhere due to a timeout, hopefully # that crasher also reported an error. Just return. # _timedOut is most likely to be set when d has fired but hasn't # completed its callback chain (see self._run) if results or self._timedOut: # defined in run() and _run() return # If the timeout didn't happen, and we didn't get a result or # a failure, then the user probably aborted the test, so let's # just raise KeyboardInterrupt. # FIXME: imagine this: # web/test/test_webclient.py: # exc = self.assertRaises(error.Error, wait, method(url)) # # wait() will raise KeyboardInterrupt, and assertRaises will # swallow it. Therefore, wait() raising KeyboardInterrupt is # insufficient to stop trial. A suggested solution is to have # this code set a "stop trial" flag, or otherwise notify trial # that it should really try to stop as soon as possible. raise KeyboardInterrupt() finally: results = None running.pop()
class _Janitor(object): """ The guy that cleans up after you. @ivar test: The L{TestCase} to report errors about. @ivar result: The L{IReporter} to report errors to. @ivar reactor: The reactor to use. If None, the global reactor will be used. """ def __init__(self, test, result, reactor=None): """ @param test: See L{_Janitor.test}. @param result: See L{_Janitor.result}. @param reactor: See L{_Janitor.reactor}. """ self.test = test self.result = result self.reactor = reactor def postCaseCleanup(self): """ Called by L{unittest.TestCase} after a test to catch any logged errors or pending L{DelayedCall}s. """ calls = self._cleanPending() if calls: aggregate = DirtyReactorAggregateError(calls) self.result.addError(self.test, Failure(aggregate)) return False return True def postClassCleanup(self): """ Called by L{unittest.TestCase} after the last test in a C{TestCase} subclass. Ensures the reactor is clean by murdering the threadpool, catching any pending L{DelayedCall}s, open sockets etc. """ selectables = self._cleanReactor() calls = self._cleanPending() if selectables or calls: aggregate = DirtyReactorAggregateError(calls, selectables) self.result.addError(self.test, Failure(aggregate)) self._cleanThreads() def _getReactor(self): """ Get either the passed-in reactor or the global reactor. """ if self.reactor is not None: reactor = self.reactor else: from twisted.internet import reactor return reactor def _cleanPending(self): """ Cancel all pending calls and return their string representations. """ reactor = self._getReactor() # flush short-range timers reactor.iterate(0) reactor.iterate(0) delayedCallStrings = [] for p in reactor.getDelayedCalls(): if p.active(): delayedString = str(p) p.cancel() else: print "WEIRDNESS! pending timed call not active!" delayedCallStrings.append(delayedString) return delayedCallStrings _cleanPending = utils.suppressWarnings( _cleanPending, (('ignore', ), { 'category': DeprecationWarning, 'message': r'reactor\.iterate cannot be used.*' })) def _cleanThreads(self): reactor = self._getReactor() if interfaces.IReactorThreads.providedBy(reactor): if reactor.threadpool is not None: # Stop the threadpool now so that a new one is created. # This improves test isolation somewhat (although this is a # post class cleanup hook, so it's only isolating classes # from each other, not methods from each other). reactor._stopThreadPool() def _cleanReactor(self): """ Remove all selectables from the reactor, kill any of them that were processes, and return their string representation. """ reactor = self._getReactor() selectableStrings = [] for sel in reactor.removeAll(): if interfaces.IProcessTransport.providedBy(sel): sel.signalProcess('KILL') selectableStrings.append(repr(sel)) return selectableStrings
svr = pb.BrokerFactory(pb.AuthRoot(auth)) s = svr.buildProtocol(('127.0.0.1',)) s.copyTags = {} cio = StringIO() sio = StringIO() c.makeConnection(protocol.FileWrapper(cio)) s.makeConnection(protocol.FileWrapper(sio)) pump = IOPump(c, s, cio, sio) # Challenge-response authentication: pump.flush() return c, s, pump connectedServerAndClient = suppressWarnings( connectedServerAndClient, _authorizerSuppress, _appSuppress, _identitySuppress, _credServiceSuppress, _pbServerFactorySuppress, ) class SimpleRemote(pb.Referenceable): def remote_thunk(self, arg): self.arg = arg return arg + 1 def remote_knuth(self, arg): raise Exception() class NestedRemote(pb.Referenceable): def remote_getSimple(self): return SimpleRemote()
class ConnectionTestCase(unittest.TestCase): def setUp(self): self.refs = [] # these will be .broker.transport.loseConnection()'ed c = pb.Broker() auth = authorizer.DefaultAuthorizer() appl = Application("pb-test") auth.setServiceCollection(appl) ident = identity.Identity("guest", authorizer=auth) ident.setPassword("guest") svc = DummyService("test", appl, authorizer=auth) ident.addKeyForPerspective(svc.getPerspectiveNamed("any")) auth.addIdentity(ident) ident2 = identity.Identity("foo", authorizer=auth) ident2.setPassword("foo") ident2.addKeyForPerspective(svc.getPerspectiveNamed("foo")) auth.addIdentity(ident2) self.svr = pb.BrokerFactory(pb.AuthRoot(auth)) self.port = reactor.listenTCP(0, self.svr, interface="127.0.0.1") self.portno = self.port.getHost().port setUp = suppressWarnings(setUp, _authorizerSuppress, _appSuppress, _identitySuppress, _credServiceSuppress, _loginBackendSuppress) def tearDown(self): for r in self.refs: r.broker.transport.loseConnection() return self.port.stopListening() def addRef(self, ref): self.refs.append(ref) return ref def _checkRootObject(self, root): d = root.callRemote("username", "guest") d.addCallback(self._checkRootObject_2) return d def _checkRootObject_2(self, challenge): self.assertEquals(len(challenge), 2) self.assert_(isinstance(challenge[1], pb.RemoteReference)) def _checkIsRemoteReference(self, r): self.assert_(isinstance(r, pb.RemoteReference)) return r # tests for *really* deprecated APIs: def testGetObjectAt(self): d = pb.getObjectAt("127.0.0.1", self.portno) d.addCallback(self.addRef) d.addCallback(self._checkRootObject) return d testGetObjectAt.suppress = [_pbClientFactorySuppress] def testConnect(self): d = pb.connect("127.0.0.1", self.portno, "guest", "guest", "test", perspectiveName="any") d.addCallback(self.addRef) d.addCallback(self._checkIsRemoteReference) return d testConnect.suppress = [ _pbClientFactorySuppress, _pbServerFactorySuppress, _loginBackendSuppress, _perspectiveSuppress ] def testIdentityConnector(self): dl = [] iConnector = pb.IdentityConnector("127.0.0.1", self.portno, "guest", "guest") d1 = iConnector.requestService("test", perspectiveName="any") d1.addCallback(self._checkIsRemoteReference) dl.append(d1) d2 = iConnector.requestService("test", perspectiveName="any") d2.addCallback(self._checkIsRemoteReference) dl.append(d2) d3 = defer.DeferredList(dl) d3.addCallback(lambda res: iConnector.disconnect()) return d3 testIdentityConnector.suppress = [ _pbServerFactorySuppress, _pbClientFactorySuppress, _perspectiveSuppress ] # tests for new, shiny API, although getPerspective stuff is also # deprecated: def testGoodGetObject(self): # we test getting both before and after connection factory = pb.PBClientFactory() d = factory.getRootObject() reactor.connectTCP("127.0.0.1", self.portno, factory) d.addCallback(self.addRef) d.addCallback(self._checkRootObject) d.addCallback(self._testGoodGetObject_1, factory) return d def _testGoodGetObject_1(self, res, factory): d = factory.getRootObject() d.addCallback(self.addRef) d.addCallback(self._checkRootObject) return d def testGoodPerspective(self): # we test getting both before and after connection factory = pb.PBClientFactory() d = factory.getPerspective("guest", "guest", "test", perspectiveName="any") reactor.connectTCP("127.0.0.1", self.portno, factory) d.addCallback(self.addRef) d.addCallback(self._checkIsRemoteReference) d.addCallback(self._testGoodPerspective_1, factory) return d def _testGoodPerspective_1(self, res, factory): d = factory.getPerspective("guest", "guest", "test", perspectiveName="any") d.addCallback(self.addRef) d.addCallback(self._checkIsRemoteReference) return d testGoodPerspective.suppress = [ _perspectiveSuppress, _loginBackendSuppress ] def testGoodFailedConnect(self): factory = pb.PBClientFactory() d = factory.getPerspective("guest", "guest", "test", perspectiveName="any") reactor.connectTCP("127.0.0.1", 69, factory) return self.assertFailure(d, error.ConnectError) testGoodFailedConnect.suppress = [_loginBackendSuppress] def testDisconnect(self): factory = pb.PBClientFactory() d = factory.getPerspective("guest", "guest", "test", perspectiveName="any") reactor.connectTCP("127.0.0.1", self.portno, factory) d.addCallback(self._testDisconnect_1, factory) return d def _testDisconnect_1(self, p, factory): d = p.callRemote("getDummyViewPoint") # just to check it's working d.addCallback(self._testDisconnect_2, p, factory) return d def _testDisconnect_2(self, res, p, factory): factory.disconnect() d = defer.Deferred() # TODO: clunky, but it works # XXX no it doesn't, it's a race-condition. This should be using # notifyOnDisconnect to be *sure* it's gone. reactor.callLater(0.1, d.callback, p) #reactor.iterate(); reactor.iterate(); reactor.iterate() d.addCallback(self._testDisconnect_3) return d def _testDisconnect_3(self, p): self.assertRaises(pb.DeadReferenceError, p.callRemote, "getDummyViewPoint") testDisconnect.suppress = [_perspectiveSuppress, _loginBackendSuppress] def testEmptyPerspective(self): factory = pb.PBClientFactory() d = factory.getPerspective("foo", "foo", "test") reactor.connectTCP("127.0.0.1", self.portno, factory) d.addCallback(self._checkIsRemoteReference) d.addCallback(self.addRef) return d testEmptyPerspective.suppress = [ _perspectiveSuppress, _loginBackendSuppress, _pbServerFactorySuppress ] def testReconnect(self): factory = ReconnectOnce() l = [] d1 = defer.Deferred() def disconnected(p): d2 = factory.getPerspective("guest", "guest", "test", perspectiveName="any") d2.addCallback(d1.callback) d = factory.getPerspective("guest", "guest", "test", perspectiveName="any") reactor.connectTCP("127.0.0.1", self.portno, factory) d.addCallback(self._checkIsRemoteReference) d.addCallback(lambda p: p.notifyOnDisconnect(disconnected)) d.addCallback(lambda res: factory.disconnect()) d1.addCallback(self._checkIsRemoteReference) d1.addCallback(lambda res: factory.disconnect()) return d1 testReconnect.suppress = [ _pbServerFactorySuppress, _loginBackendSuppress, _perspectiveSuppress ] def testImmediateClose(self): cc = protocol.ClientCreator(reactor, protocol.Protocol) d = cc.connectTCP("127.0.0.1", self.portno) d.addCallback(lambda p: p.transport.loseConnection()) d = defer.Deferred() # clunky, but it works reactor.callLater(0.1, d.callback, None) return d
class _Janitor(object): logErrCheck = True cleanPending = cleanThreads = cleanReactor = True def postCaseCleanup(self): return self._dispatch('cleanPending') def postClassCleanup(self): return self._dispatch('cleanReactor', 'cleanPending', 'cleanThreads') def _dispatch(self, *attrs): for attr in attrs: getattr(self, "do_%s" % attr)() def do_cleanPending(cls): # don't import reactor when module is loaded from twisted.internet import reactor # flush short-range timers reactor.iterate(0) reactor.iterate(0) pending = reactor.getDelayedCalls() if pending: s = PENDING_TIMED_CALLS_MSG for p in pending: s += " %s\n" % (p, ) if p.active(): p.cancel() # delete the rest else: print "WEIRNESS! pending timed call not active+!" raise PendingTimedCallsError(s) do_cleanPending = utils.suppressWarnings( do_cleanPending, (('ignore', ), { 'category': DeprecationWarning, 'message': r'reactor\.iterate cannot be used.*' })) do_cleanPending = classmethod(do_cleanPending) def do_cleanThreads(cls): from twisted.internet import reactor if interfaces.IReactorThreads.providedBy(reactor): reactor.suggestThreadPoolSize(0) if hasattr(reactor, 'threadpool') and reactor.threadpool: reactor.threadpool.stop() reactor.threadpool = None # *Put it back* and *start it up again*. The # reactor's threadpool is *private*: we cannot just # rape it and walk away. reactor.threadpool = threadpool.ThreadPool(0, 10) reactor.threadpool.start() do_cleanThreads = classmethod(do_cleanThreads) def do_cleanReactor(cls): s = [] from twisted.internet import reactor removedSelectables = reactor.removeAll() if removedSelectables: s.append(DIRTY_REACTOR_MSG) for sel in removedSelectables: if interfaces.IProcessTransport.providedBy(sel): sel.signalProcess('KILL') s.append(repr(sel)) if s: raise DirtyReactorError(' '.join(s)) do_cleanReactor = classmethod(do_cleanReactor) def doGcCollect(cls): gc.collect()
s.copyTags = {} cio = StringIO() sio = StringIO() c.makeConnection(protocol.FileWrapper(cio)) s.makeConnection(protocol.FileWrapper(sio)) pump = IOPump(c, s, cio, sio) # Challenge-response authentication: pump.flush() return c, s, pump connectedServerAndClient = suppressWarnings( connectedServerAndClient, _authorizerSuppress, _appSuppress, _identitySuppress, _credServiceSuppress, _pbServerFactorySuppress, ) class SimpleRemote(pb.Referenceable): def remote_thunk(self, arg): self.arg = arg return arg + 1 def remote_knuth(self, arg): raise Exception() class NestedRemote(pb.Referenceable):