def test_addresses(self): """ A client's transport's C{getHost} and C{getPeer} return L{IPv4Address} instances which give the dotted-quad string form of the local and remote endpoints of the connection respectively. """ host, port = findFreePort() reactor = self.buildReactor() server = reactor.listenTCP( 0, serverFactoryFor(Protocol), interface=host) serverAddress = server.getHost() addresses = {'host': None, 'peer': None} class CheckAddress(Protocol): def makeConnection(self, transport): addresses['host'] = transport.getHost() addresses['peer'] = transport.getPeer() reactor.stop() clientFactory = Stop(reactor) clientFactory.protocol = CheckAddress reactor.connectTCP( 'localhost', server.getHost().port, clientFactory, bindAddress=('127.0.0.1', port)) reactor.installResolver(FakeResolver({'localhost': '127.0.0.1'})) self.runReactor(reactor) self.assertEqual( addresses['host'], IPv4Address('TCP', '127.0.0.1', port)) self.assertEqual( addresses['peer'], IPv4Address('TCP', '127.0.0.1', serverAddress.port))
def test_unregisterProducerAfterDisconnect(self): """ If a producer is unregistered from a L{ITCPTransport} provider after the transport has been disconnected (by the peer) and after L{ITCPTransport.loseConnection} has been called, the transport is not re-added to the reactor as a writer as would be necessary if the transport were still connected. """ reactor = self.buildReactor() port = reactor.listenTCP(0, serverFactoryFor(ClosingProtocol)) finished = Deferred() finished.addErrback(log.err) finished.addCallback(lambda ign: reactor.stop()) writing = [] class ClientProtocol(Protocol): """ Protocol to connect, register a producer, try to lose the connection, wait for the server to disconnect from us, and then unregister the producer. """ def connectionMade(self): log.msg("ClientProtocol.connectionMade") self.transport.registerProducer( _SimplePullProducer(self.transport), False) self.transport.loseConnection() def connectionLost(self, reason): log.msg("ClientProtocol.connectionLost") self.unregister() writing.append(self.transport in _getWriters(reactor)) finished.callback(None) def unregister(self): log.msg("ClientProtocol unregister") self.transport.unregisterProducer() clientFactory = ClientFactory() clientFactory.protocol = ClientProtocol reactor.connectTCP('127.0.0.1', port.getHost().port, clientFactory) self.runReactor(reactor) self.assertFalse( writing[0], "Transport was writing after unregisterProducer.")
def test_connectEvent(self): """ This test checks that we correctly get notifications event for a client. This ought to prevent a regression under Windows using the GTK2 reactor. See #3925. """ reactor = self.buildReactor() server = reactor.listenTCP(0, serverFactoryFor(Protocol)) connected = [] class CheckConnection(Protocol): def connectionMade(self): connected.append(self) reactor.stop() clientFactory = Stop(reactor) clientFactory.protocol = CheckConnection reactor.connectTCP( '127.0.0.1', server.getHost().port, clientFactory) reactor.run() self.assertTrue(connected)
def test_disconnectWhileProducing(self): """ If L{ITCPTransport.loseConnection} is called while a producer is registered with the transport, the connection is closed after the producer is unregistered. """ reactor = self.buildReactor() # XXX For some reason, pyobject/pygtk will not deliver the close # notification that should happen after the unregisterProducer call in # this test. The selectable is in the write notification set, but no # notification ever arrives. skippedReactors = ["Glib2Reactor", "Gtk2Reactor"] reactorClassName = reactor.__class__.__name__ if reactorClassName in skippedReactors and platform.isWindows(): raise SkipTest( "A pygobject/pygtk bug disables this functionality on Windows.") class Producer: def resumeProducing(self): log.msg("Producer.resumeProducing") port = reactor.listenTCP(0, serverFactoryFor(Protocol)) finished = Deferred() finished.addErrback(log.err) finished.addCallback(lambda ign: reactor.stop()) class ClientProtocol(Protocol): """ Protocol to connect, register a producer, try to lose the connection, unregister the producer, and wait for the connection to actually be lost. """ def connectionMade(self): log.msg("ClientProtocol.connectionMade") self.transport.registerProducer(Producer(), False) self.transport.loseConnection() # Let the reactor tick over, in case synchronously calling # loseConnection and then unregisterProducer is the same as # synchronously calling unregisterProducer and then # loseConnection (as it is in several reactors). reactor.callLater(0, reactor.callLater, 0, self.unregister) def unregister(self): log.msg("ClientProtocol unregister") self.transport.unregisterProducer() # This should all be pretty quick. Fail the test # if we don't get a connectionLost event really # soon. reactor.callLater( 1.0, finished.errback, Failure(Exception("Connection was not lost"))) def connectionLost(self, reason): log.msg("ClientProtocol.connectionLost") finished.callback(None) clientFactory = ClientFactory() clientFactory.protocol = ClientProtocol reactor.connectTCP('127.0.0.1', port.getHost().port, clientFactory) self.runReactor(reactor)