def test_doubleEncodingError(self): """ If it is not possible to encode a response to the request (for example, because L{xmlrpclib.dumps} raises an exception when encoding a L{Fault}) the exception which prevents the response from being generated is logged and the request object is finished anyway. """ logObserver = EventLoggingObserver() filtered = FilteringLogObserver( logObserver, [LogLevelFilterPredicate(defaultLogLevel=LogLevel.critical)]) globalLogPublisher.addObserver(filtered) self.addCleanup(lambda: globalLogPublisher.removeObserver(filtered)) d = self.proxy().callRemote("echo", "") # *Now* break xmlrpclib.dumps. Hopefully the client already used it. def fakeDumps(*args, **kwargs): raise RuntimeError("Cannot encode anything at all!") self.patch(xmlrpclib, "dumps", fakeDumps) # It doesn't matter how it fails, so long as it does. Also, it happens # to fail with an implementation detail exception right now, not # something suitable as part of a public interface. d = self.assertFailure(d, Exception) def cbFailed(ignored): # The fakeDumps exception should have been logged. self.assertEquals(1, len(logObserver)) self.assertIsInstance(logObserver[0]["log_failure"].value, RuntimeError) self.assertEqual(len(self.flushLoggedErrors(RuntimeError)), 1) d.addCallback(cbFailed) return d
def test_simpleFailureWithTraceback(self): """ L{renderElement} will render a traceback when rendering of the element fails and our site is configured to display tracebacks. """ logObserver = EventLoggingObserver.createWithCleanup( self, globalLogPublisher ) self.request.site.displayTracebacks = True element = FailingElement() d = self.request.notifyFinish() def check(_): self.assertEquals(1, len(logObserver)) f = logObserver[0]["log_failure"] self.assertIsInstance(f.value, FlattenerError) flushed = self.flushLoggedErrors(FlattenerError) self.assertEqual(len(flushed), 1) self.assertEqual( b"".join(self.request.written), b"<!DOCTYPE html>\n<p>I failed.</p>") self.assertTrue(self.request.finished) d.addCallback(check) renderElement(self.request, element, _failElement=TestFailureElement) return d
def test_unexpectedLoginError(self): """ Any unexpected failure from L{Portal.login} results in a 500 response code and causes the failure to be logged. """ logObserver = EventLoggingObserver.createWithCleanup( self, globalLogPublisher) class UnexpectedException(Exception): pass class BrokenChecker: credentialInterfaces = (IUsernamePassword, ) def requestAvatarId(self, credentials): raise UnexpectedException() self.portal.registerChecker(BrokenChecker()) self.credentialFactories.append(BasicCredentialFactory('example.com')) request = self.makeRequest([self.childName]) child = self._authorizedBasicLogin(request) request.render(child) self.assertEqual(request.responseCode, 500) self.assertEquals(1, len(logObserver)) self.assertIsInstance(logObserver[0]["log_failure"].value, UnexpectedException) self.assertEqual(len(self.flushLoggedErrors(UnexpectedException)), 1)
def test_unexpectedDecodeError(self): """ Any unexpected exception raised by the credential factory's C{decode} method results in a 500 response code and causes the exception to be logged. """ logObserver = EventLoggingObserver.createWithCleanup( self, globalLogPublisher) class UnexpectedException(Exception): pass class BadFactory: scheme = b'bad' def getChallenge(self, client): return {} def decode(self, response, request): raise UnexpectedException() self.credentialFactories.append(BadFactory()) request = self.makeRequest([self.childName]) request.requestHeaders.addRawHeader(b'authorization', b'Bad abc') child = getChildForRequest(self.wrapper, request) request.render(child) self.assertEqual(request.responseCode, 500) self.assertEquals(1, len(logObserver)) self.assertIsInstance(logObserver[0]["log_failure"].value, UnexpectedException) self.assertEqual(len(self.flushLoggedErrors(UnexpectedException)), 1)
def test_unknown_correlation_id(self): """ A warning is logged and the connection dropped when a response with an unknown correlation ID is received. """ events = EventLoggingObserver.createWithCleanup(self, globalLogPublisher) self.transport.bufferReceived(b'\0\0\0\x101234 more stuff..') self.assertTrue(self.transport.disconnecting) [event] = events self.assertEqual(LogLevel.warn, event['log_level']) self.assertEqual(self.peer, event['peer']) self.assertEqual(b'1234', event['correlation_id'])
def test_unknown_correlation_id(self): """ A warning is logged and the connection dropped when a response with an unknown correlation ID is received. """ events = EventLoggingObserver.createWithCleanup( self, globalLogPublisher) self.transport.bufferReceived(b'\0\0\0\x101234 more stuff..') self.assertTrue(self.transport.disconnecting) [event] = events self.assertEqual(LogLevel.warn, event['log_level']) self.assertEqual(self.peer, event['peer']) self.assertEqual(b'1234', event['correlation_id'])
def test_errors(self): """ Verify that for each way a method exposed via XML-RPC can fail, the correct 'Content-type' header is set in the response and that the client-side Deferred is errbacked with an appropriate C{Fault} instance. """ logObserver = EventLoggingObserver() filtered = FilteringLogObserver( logObserver, [LogLevelFilterPredicate(defaultLogLevel=LogLevel.critical)]) globalLogPublisher.addObserver(filtered) self.addCleanup(lambda: globalLogPublisher.removeObserver(filtered)) dl = [] for code, methodName in [ (666, "fail"), (666, "deferFail"), (12, "fault"), (23, "noSuchMethod"), (17, "deferFault"), (42, "SESSION_TEST"), ]: d = self.proxy().callRemote(methodName) d = self.assertFailure(d, xmlrpc.Fault) d.addCallback( lambda exc, code=code: self.assertEqual(exc.faultCode, code)) dl.append(d) d = defer.DeferredList(dl, fireOnOneErrback=True) def cb(ign): for factory in self.factories: self.assertEqual(factory.headers[b"content-type"], b"text/xml; charset=utf-8") self.assertEquals(2, len(logObserver)) f1 = logObserver[0]["log_failure"].value f2 = logObserver[1]["log_failure"].value if isinstance(f1, TestValueError): self.assertIsInstance(f2, TestRuntimeError) else: self.assertIsInstance(f1, TestRuntimeError) self.assertIsInstance(f2, TestValueError) self.flushLoggedErrors(TestRuntimeError, TestValueError) d.addCallback(cb) return d