def test_unhandled_errors_do_not_cause_disconnection(self): self.patch(common.log, "debug") protocol = common.RPCProtocol() protocol.makeConnection(StringTransport()) # Ensure that the superclass dispatchCommand() will fail. dispatchCommand = self.patch(amp.AMP, "dispatchCommand") dispatchCommand.side_effect = always_fail_with(ZeroDivisionError()) # Push a command box into the protocol. seq = b"%d" % random.randrange(0, 2**32) cmd = factory.make_string().encode("ascii") box = amp.AmpBox(_ask=seq, _command=cmd) with TwistedLoggerFixture() as logger: protocol.ampBoxReceived(box) # The transport is still connected. self.expectThat(protocol.transport.disconnecting, Is(False)) # The error has been logged on the originating side of the AMP # session, along with an explanatory message. The message includes a # command reference. cmd_ref = common.make_command_ref(box) self.assertDocTestMatches( """\ Unhandled failure dispatching AMP command. This is probably a bug. Please ensure that this error is handled within application code or declared in the signature of the %s command. [%s] Traceback (most recent call last): ... """ % (cmd, cmd_ref), logger.output, ) # A simpler error message has been transmitted over the wire. It # includes the same command reference as logged locally. protocol.transport.io.seek(0) observed_boxes_sent = amp.parse(protocol.transport.io) expected_boxes_sent = [ amp.AmpBox( _error=seq, _error_code=amp.UNHANDLED_ERROR_CODE, _error_description=(b"Unknown Error [%s]" % cmd_ref.encode("ascii")), ) ] self.assertThat(observed_boxes_sent, Equals(expected_boxes_sent))
def test_unhandled_errors_logged_and_do_not_cause_disconnection(self): protocol = common.RPCProtocol() protocol.makeConnection(StringTransport()) # Poke a request into the dispatcher that will always fail. d = Deferred().addCallback(lambda _: 0 / 0) protocol._outstandingRequests[self.seq] = d # Push a box in response to the request. with TwistedLoggerFixture() as logger: protocol.ampBoxReceived(self.box) # The Deferred does not have a dangling error. self.assertThat(extract_result(d), Is(None)) # The transport is still connected. self.assertThat(protocol.transport.disconnecting, Is(False)) # The error has been logged. self.assertDocTestMatches( """\ Unhandled failure during AMP request. This is probably a bug. Please ensure that this error is handled within application code. Traceback (most recent call last): ... """, logger.output)
def test_onConnectionLost_fires_when_connection_is_lost(self): protocol = common.RPCProtocol() protocol.makeConnection(StringTransport()) protocol.connectionLost(connectionDone) self.assertThat(protocol.onConnectionLost, IsFiredDeferred())
def test_onConnectionMade_fires_when_connection_is_made(self): protocol = common.RPCProtocol() protocol.connectionMade() self.assertThat(protocol.onConnectionMade, IsFiredDeferred())
def test_init(self): protocol = common.RPCProtocol() self.assertThat(protocol.onConnectionMade, IsUnfiredDeferred()) self.assertThat(protocol.onConnectionLost, IsUnfiredDeferred()) self.assertThat(protocol, IsInstance(amp.AMP))