def test_abortClosesConnection(self):
"""
L{HTTP11ClientProtocol.abort} will tell the transport to close its
connection when it is invoked, and returns a C{Deferred} that fires
when the connection is lost.
"""
transport = StringTransport()
protocol = HTTP11ClientProtocol()
protocol.makeConnection(transport)
r1 = []
r2 = []
protocol.abort().addCallback(r1.append)
protocol.abort().addCallback(r2.append)
self.assertEqual((r1, r2), ([], []))
self.assertTrue(transport.disconnecting)
# Disconnect protocol, the Deferreds will fire:
protocol.connectionLost(Failure(ConnectionDone()))
self.assertEqual(r1, [None])
self.assertEqual(r2, [None])
python类ConnectionDone()的实例源码
def _disconnectSelectable(self, selectable, why, isRead, faildict={
error.ConnectionDone: failure.Failure(error.ConnectionDone()),
error.ConnectionLost: failure.Failure(error.ConnectionLost())
}):
"""
Utility function for disconnecting a selectable.
Supports half-close notification, isRead should be boolean indicating
whether error resulted from doRead().
"""
self.removeReader(selectable)
f = faildict.get(why.__class__)
if f:
if (isRead and why.__class__ == error.ConnectionDone
and IHalfCloseableDescriptor.providedBy(selectable)):
selectable.readConnectionLost(f)
else:
self.removeWriter(selectable)
selectable.connectionLost(f)
else:
self.removeWriter(selectable)
selectable.connectionLost(failure.Failure(why))
def test_closePortInProtocolFactory(self):
"""
A port created with L{IReactorTCP.listenTCP} can be connected to with
L{IReactorTCP.connectTCP}.
"""
f = ClosingFactory()
port = reactor.listenTCP(0, f, interface="127.0.0.1")
f.port = port
self.addCleanup(f.cleanUp)
portNumber = port.getHost().port
clientF = MyClientFactory()
reactor.connectTCP("127.0.0.1", portNumber, clientF)
def check(x):
self.assertTrue(clientF.protocol.made)
self.assertTrue(port.disconnected)
clientF.lostReason.trap(error.ConnectionDone)
return clientF.deferred.addCallback(check)
def test_timeOut(self):
"""
Test the timeout on outgoing requests: when timeout is detected, all
current commands fail with a L{TimeoutError}, and the connection is
closed.
"""
d1 = self.proto.get(b"foo")
d2 = self.proto.get(b"bar")
d3 = Deferred()
self.proto.connectionLost = d3.callback
self.clock.advance(self.proto.persistentTimeOut)
self.assertFailure(d1, TimeoutError)
self.assertFailure(d2, TimeoutError)
def checkMessage(error):
self.assertEqual(str(error), "Connection timeout")
d1.addCallback(checkMessage)
self.assertFailure(d3, ConnectionDone)
return gatherResults([d1, d2, d3])
def test_connectionLost(self):
"""
When disconnection occurs while commands are still outstanding, the
commands fail.
"""
d1 = self.proto.get(b"foo")
d2 = self.proto.get(b"bar")
self.transport.loseConnection()
done = DeferredList([d1, d2], consumeErrors=True)
def checkFailures(results):
for success, result in results:
self.assertFalse(success)
result.trap(ConnectionDone)
return done.addCallback(checkFailures)
def test_processEnded(self):
"""
L{LocalWorker.processEnded} calls C{connectionLost} on itself and on
the L{AMP} protocol.
"""
class FakeStream(object):
callNumber = 0
def close(self):
self.callNumber += 1
transport = FakeTransport()
protocol = FakeAMProtocol()
localWorker = LocalWorker(protocol, '.', 'test.log')
localWorker.makeConnection(transport)
localWorker._outLog = FakeStream()
localWorker.processEnded(Failure(CONNECTION_DONE))
self.assertEqual(localWorker._outLog.callNumber, 1)
self.assertIdentical(None, protocol.transport)
return self.assertFailure(localWorker.endDeferred, ConnectionDone)
def _processConnectionError(self, connector, err):
self.currentProtocol = None
if (self.retries < 0) and (not self.sendFinished):
log.msg("SMTP Client retrying server. Retry: %s" % -self.retries)
# Rewind the file in case part of it was read while attempting to
# send the message.
self.file.seek(0, 0)
connector.connect()
self.retries += 1
elif not self.sendFinished:
# If we were unable to communicate with the SMTP server a ConnectionDone will be
# returned. We want a more clear error message for debugging
if err.check(error.ConnectionDone):
err.value = SMTPConnectError(-1, "Unable to connect to server.")
self.result.errback(err.value)
def testPathelogicalScatteringOfLiterals(self):
self.server.checker.addUser(b'testuser', b'password-test')
transport = StringTransport()
self.server.makeConnection(transport)
transport.clear()
self.server.dataReceived(b"01 LOGIN {8}\r\n")
self.assertEqual(transport.value(), b"+ Ready for 8 octets of text\r\n")
transport.clear()
self.server.dataReceived(b"testuser {13}\r\n")
self.assertEqual(transport.value(), b"+ Ready for 13 octets of text\r\n")
transport.clear()
self.server.dataReceived(b"password-test\r\n")
self.assertEqual(transport.value(), b"01 OK LOGIN succeeded\r\n")
self.assertEqual(self.server.state, 'auth')
self.server.connectionLost(error.ConnectionDone("Connection done."))
def test_fetchWithPartialValidArgument(self):
"""
If by any chance, extra bytes got appended at the end of a valid
FETCH arguments, the client should get a BAD - arguments invalid
response.
See U{RFC 3501<http://tools.ietf.org/html/rfc3501#section-6.4.5>},
section 6.4.5,
"""
# We need to clear out the welcome message.
self.transport.clear()
# Let's send out the faulty command.
self.server.dataReceived(b"0001 FETCH 1 FULLL\r\n")
expected = b"0001 BAD Illegal syntax: Invalid Argument\r\n"
self.assertEqual(self.transport.value(), expected)
self.transport.clear()
self.server.connectionLost(error.ConnectionDone("Connection closed"))
def test_connectionLost_clientClose(self):
'''If connectionLost is called because the client closed the
connection, then this connection has disappeared suddenly.
Consequently, the protocol's terminationDeferred errbacks with
the provided reason, the timeout clock is stopped, and the
session machine learns about the lost connection.
'''
erroredDeferred = self.protocol.terminationDeferred
def trapConnectionDone(failure):
failure.trap(error.ConnectionDone)
erroredDeferred.addErrback(trapConnectionDone)
self.protocol.connectionLost(connectionDone)
self.assertEqual(self.timeoutClockRecorder.stopCalls, 1)
self.assertEqual(self.sessionMachineRecorder.connectionsLostReasons,
[connectionDone])
self.assertIsNone(self.protocol.sessionMachine)
return erroredDeferred
def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log,
faildict={
error.ConnectionDone: failure.Failure(error.ConnectionDone()),
error.ConnectionLost: failure.Failure(error.ConnectionLost())
}):
why = None
inRead = False
if event & POLL_DISCONNECTED and not (event & POLLIN):
why = main.CONNECTION_LOST
else:
try:
if event & POLLIN:
why = selectable.doRead()
inRead = True
if not why and event & POLLOUT:
why = selectable.doWrite()
inRead = False
if not selectable.fileno() == fd:
why = error.ConnectionFdescWentAway('Filedescriptor went away')
inRead = False
except:
log.deferr()
why = sys.exc_info()[1]
if why:
self._disconnectSelectable(selectable, why, inRead)
def closed(self):
self._protocolInstance.connectionLost(error.ConnectionDone())
def testNotifyFinishConnectionLost(self):
d = DummyChannel()
d.transport = DummyChannel.TCP()
request = server.Request(d, 1)
finished = request.notifyFinish()
request.connectionLost(error.ConnectionDone("Connection done"))
return self.assertFailure(finished, error.ConnectionDone)
def _doReadOrWrite(self, source, condition, faildict={
error.ConnectionDone: failure.Failure(error.ConnectionDone()),
error.ConnectionLost: failure.Failure(error.ConnectionLost()),
}):
why = None
didRead = None
if condition & POLL_DISCONNECTED and \
not (condition & gobject.IO_IN):
why = main.CONNECTION_LOST
else:
try:
if condition & gobject.IO_IN:
why = source.doRead()
didRead = source.doRead
if not why and condition & gobject.IO_OUT:
# if doRead caused connectionLost, don't call doWrite
# if doRead is doWrite, don't call it again.
if not source.disconnected and source.doWrite != didRead:
why = source.doWrite()
didRead = source.doWrite # if failed it was in write
except:
why = sys.exc_info()[1]
log.msg('Error In %s' % source)
log.deferr()
if why:
self._disconnectSelectable(source, why, didRead == source.doRead)
def connectionLost(self, reason):
reason.trap(error.ConnectionDone)
def testClosePortInProtocolFactory(self):
f = ClosingFactory()
port = reactor.listenTCP(0, f, interface="127.0.0.1")
self.n = port.getHost().port
self.ports.append(port)
f.port = port
clientF = MyClientFactory()
reactor.connectTCP("127.0.0.1", self.n, clientF)
def check(x):
self.assert_(clientF.protocol.made)
self.assert_(port.disconnected)
clientF.lostReason.trap(error.ConnectionDone)
return clientF.deferred.addCallback(check)
def _trapCnxDone(self, obj):
getattr(obj, 'trap', lambda x: None)(error.ConnectionDone)
def testPASV(self):
# Login
yield defer.waitForDeferred(self._anonymousLogin())
# Issue a PASV command, and extract the host and port from the response
pasvCmd = defer.waitForDeferred(self.client.queueStringCommand('PASV'))
yield pasvCmd
responseLines = pasvCmd.getResult()
host, port = ftp.decodeHostPort(responseLines[-1][4:])
# Make sure the server is listening on the port it claims to be
self.assertEqual(port, self.serverProtocol.dtpPort.getHost().port)
# Semi-reasonable way to force cleanup
self.serverProtocol.connectionLost(error.ConnectionDone())
def test_passiveRETR(self):
"""
Test the RETR command in passive mode: get a file and verify its
content.
L{ftp.FTPClient.retrieveFile} should return a Deferred which fires
with the protocol instance passed to it after the download has
completed.
(XXX - This API should be based on producers and consumers)
"""
def cbRetr(res, proto):
self.assertEquals(proto.buffer, 'x' * 1000)
def cbConnect(host, port, factory):
self.assertEquals(host, '127.0.0.1')
self.assertEquals(port, 12345)
proto = factory.buildProtocol((host, port))
proto.makeConnection(proto_helpers.StringTransport())
self.client.lineReceived(
'150 File status okay; about to open data connection.')
proto.dataReceived("x" * 1000)
proto.connectionLost(failure.Failure(error.ConnectionDone("")))
self.client.connectFactory = cbConnect
self._testLogin()
proto = _BufferingProtocol()
d = self.client.retrieveFile("spam", proto)
d.addCallback(cbRetr, proto)
self.assertEquals(self.transport.value(), 'PASV\r\n')
self.transport.clear()
self.client.lineReceived('227 Entering Passive Mode (%s).' %
(ftp.encodeHostPort('127.0.0.1', 12345),))
self.assertEquals(self.transport.value(), 'RETR spam\r\n')
self.transport.clear()
self.client.lineReceived('226 Transfer Complete.')
return d
def test_RETR(self):
"""
Test the RETR command in non-passive mode.
Like L{test_passiveRETR} but in the configuration where the server
establishes the data connection to the client, rather than the other
way around.
"""
self.client.passive = False
def generatePort(portCmd):
portCmd.text = 'PORT %s' % (ftp.encodeHostPort('127.0.0.1', 9876),)
portCmd.protocol.makeConnection(proto_helpers.StringTransport())
portCmd.protocol.dataReceived("x" * 1000)
portCmd.protocol.connectionLost(
failure.Failure(error.ConnectionDone("")))
def cbRetr(res, proto):
self.assertEquals(proto.buffer, 'x' * 1000)
self.client.generatePortCommand = generatePort
self._testLogin()
proto = _BufferingProtocol()
d = self.client.retrieveFile("spam", proto)
d.addCallback(cbRetr, proto)
self.assertEquals(self.transport.value(), 'PORT %s\r\n' %
(ftp.encodeHostPort('127.0.0.1', 9876),))
self.transport.clear()
self.client.lineReceived('200 PORT OK')
self.assertEquals(self.transport.value(), 'RETR spam\r\n')
self.transport.clear()
self.client.lineReceived('226 Transfer Complete.')
return d