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() self.listen(reactor, ServerFactory.forProtocol(Protocol)) connected = [] class CheckConnection(Protocol): def connectionMade(self): connected.append(self) reactor.stop() clientFactory = Stop(reactor) clientFactory.protocol = CheckConnection needsRunningReactor( reactor, lambda: self.connect(reactor, clientFactory)) reactor.run() self.assertTrue(connected)
def test_stopOnlyCloses(self): """ When the L{IListeningPort} returned by L{IReactorSocket.adoptDatagramPort} is stopped using C{stopListening}, the underlying socket is closed but not shutdown. This allows another process which still has a reference to it to continue reading and writing to it. """ reactor = self.buildReactor() portSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.addCleanup(portSocket.close) portSocket.setblocking(False) # The file descriptor is duplicated by adoptDatagramPort port = reactor.adoptDatagramPort( portSocket.fileno(), portSocket.family, DatagramProtocol()) d = port.stopListening() def stopped(ignored): # Should still be possible to recv on portSocket. If # it was shutdown, the exception would be EINVAL instead. exc = self.assertRaises(socket.error, portSocket.recvfrom, 1) self.assertEqual(exc.args[0], errno.EAGAIN) d.addCallback(stopped) d.addErrback(err, "Failed to read on original port.") needsRunningReactor( reactor, lambda: d.addCallback(lambda ignored: reactor.stop())) reactor.run()
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), interface=self.interface) connected = [] class CheckConnection(Protocol): def connectionMade(self): connected.append(self) reactor.stop() clientFactory = Stop(reactor) clientFactory.protocol = CheckConnection needsRunningReactor(reactor, lambda: reactor.connectTCP( self.interface, server.getHost().port, clientFactory)) reactor.run() self.assertTrue(connected)
def test_stopOnlyCloses(self): """ When the L{IListeningPort} returned by L{IReactorSocket.adoptStreamPort} is stopped using C{stopListening}, the underlying socket is closed but not shutdown. This allows another process which still has a reference to it to continue accepting connections over it. """ reactor = self.buildReactor() portSocket = socket.socket() self.addCleanup(portSocket.close) portSocket.listen(1) portSocket.setblocking(False) # The file descriptor is duplicated by adoptStreamPort port = reactor.adoptStreamPort( portSocket.fileno(), portSocket.family, ServerFactory()) d = port.stopListening() def stopped(ignored): # Should still be possible to accept a connection on # portSocket. If it was shutdown, the exception would be # EINVAL instead. exc = self.assertRaises(socket.error, portSocket.accept) self.assertEqual(exc.args[0], errno.EAGAIN) d.addCallback(stopped) d.addErrback(err, "Failed to accept on original port.") needsRunningReactor( reactor, lambda: d.addCallback(lambda ignored: reactor.stop())) reactor.run()
def test_clientConnectionFailedStopsReactor(self): """ The reactor can be stopped by a client factory's C{clientConnectionFailed} method. """ reactor = self.buildReactor() needsRunningReactor(reactor, lambda: self.connect(reactor, Stop(reactor))) self.runReactor(reactor)
def test_addresses(self): """ A client's transport's C{getHost} and C{getPeer} return L{IPv4Address} or L{IPv6Address} instances which have the resolved adddress of the local and remote endpoints of the connection respectively as their C{host} attribute, not the hostname originally passed in to L{connectTCP<twisted.internet.interfaces.IReactorTCP.connectTCP>}, if a hostname was used. """ host, port = findFreePort(self.interface, self.family)[:2] reactor = self.buildReactor() fakeDomain = self.fakeDomainName reactor.installResolver(FakeResolver({fakeDomain: self.interface})) server = reactor.listenTCP( 0, serverFactoryFor(Protocol), interface=host) serverAddress = server.getHost() transportData = {'host': None, 'peer': None, 'instance': None} class CheckAddress(Protocol): def makeConnection(self, transport): transportData['host'] = transport.getHost() transportData['peer'] = transport.getPeer() transportData['instance'] = transport reactor.stop() clientFactory = Stop(reactor) clientFactory.protocol = CheckAddress def connectMe(): reactor.connectTCP( fakeDomain, server.getHost().port, clientFactory, bindAddress=(self.interface, port)) needsRunningReactor(reactor, connectMe) self.runReactor(reactor) if clientFactory.failReason: self.fail(clientFactory.failReason.getTraceback()) hostAddress = self.addressClass('TCP', self.interface, port) peerAddress = self.addressClass('TCP', self.interface, serverAddress.port) transportRepr = "<%s to %s at %x>" % ( transportData['instance'].__class__, transportData['instance'].addr, id(transportData['instance'])) self.assertEqual({ 'host': transportData['host'], 'peer': transportData['peer'], 'repr': repr(transportData['instance']), }, { 'host': hostAddress, 'peer': peerAddress, 'repr': transportRepr, })
def test_clientConnectionFailedStopsReactor(self): """ The reactor can be stopped by a client factory's C{clientConnectionFailed} method. """ host, port = findFreePort(self.interface, self.family)[:2] reactor = self.buildReactor() needsRunningReactor( reactor, lambda: reactor.connectTCP(host, port, Stop(reactor))) self.runReactor(reactor)
def test_badContext(self): """ If the context factory passed to L{ITCPTransport.startTLS} raises an exception from its C{getContext} method, that exception is raised by L{ITCPTransport.startTLS}. """ reactor = self.buildReactor() brokenFactory = BrokenContextFactory() results = [] serverFactory = ServerFactory() serverFactory.protocol = Protocol port = reactor.listenTCP(0, serverFactory, interface=self.interface) endpoint = self.endpoints.client(reactor, port.getHost()) clientFactory = ClientFactory() clientFactory.protocol = Protocol connectDeferred = endpoint.connect(clientFactory) def connected(protocol): if not ITLSTransport.providedBy(protocol.transport): results.append("skip") else: results.append(self.assertRaises(ValueError, protocol.transport.startTLS, brokenFactory)) def connectFailed(failure): results.append(failure) def whenRun(): connectDeferred.addCallback(connected) connectDeferred.addErrback(connectFailed) connectDeferred.addBoth(lambda ign: reactor.stop()) needsRunningReactor(reactor, whenRun) self.runReactor(reactor) self.assertEqual(len(results), 1, "more than one callback result: %s" % (results,)) if isinstance(results[0], Failure): # self.fail(Failure) results[0].raiseException() if results[0] == "skip": raise SkipTest("Reactor does not support ITLSTransport") self.assertEqual(BrokenContextFactory.message, str(results[0]))
def test_writeAfterDisconnect(self): """ After a connection is disconnected, L{ITransport.write} and L{ITransport.writeSequence} are no-ops. """ reactor = self.buildReactor() finished = [] serverConnectionLostDeferred = Deferred() protocol = lambda: ClosingLaterProtocol(serverConnectionLostDeferred) portDeferred = self.endpoints.server(reactor).listen( ServerFactory.forProtocol(protocol) ) def listening(port): msg("Listening on %r" % (port.getHost(),)) endpoint = self.endpoints.client(reactor, port.getHost()) lostConnectionDeferred = Deferred() protocol = lambda: ClosingLaterProtocol(lostConnectionDeferred) client = endpoint.connect(ClientFactory.forProtocol(protocol)) def write(proto): msg("About to write to %r" % (proto,)) proto.transport.write(b"x") client.addCallbacks(write, lostConnectionDeferred.errback) def disconnected(proto): msg("%r disconnected" % (proto,)) proto.transport.write(b"some bytes to get lost") proto.transport.writeSequence([b"some", b"more"]) finished.append(True) lostConnectionDeferred.addCallback(disconnected) serverConnectionLostDeferred.addCallback(disconnected) return gatherResults([lostConnectionDeferred, serverConnectionLostDeferred]) def onListen(): portDeferred.addCallback(listening) portDeferred.addErrback(err) portDeferred.addCallback(lambda ignored: reactor.stop()) needsRunningReactor(reactor, onListen) self.runReactor(reactor) self.assertEqual(finished, [True, True])
def test_writeAfterDisconnect(self): """ After a connection is disconnected, L{ITransport.write} and L{ITransport.writeSequence} are no-ops. """ reactor = self.buildReactor() finished = [] serverConnectionLostDeferred = Deferred() protocol = lambda: ClosingLaterProtocol(serverConnectionLostDeferred) portDeferred = self.endpoints.server(reactor).listen(ServerFactory.forProtocol(protocol)) def listening(port): msg("Listening on %r" % (port.getHost(),)) endpoint = self.endpoints.client(reactor, port.getHost()) lostConnectionDeferred = Deferred() protocol = lambda: ClosingLaterProtocol(lostConnectionDeferred) client = endpoint.connect(ClientFactory.forProtocol(protocol)) def write(proto): msg("About to write to %r" % (proto,)) proto.transport.write(b"x") client.addCallbacks(write, lostConnectionDeferred.errback) def disconnected(proto): msg("%r disconnected" % (proto,)) proto.transport.write(b"some bytes to get lost") proto.transport.writeSequence([b"some", b"more"]) finished.append(True) lostConnectionDeferred.addCallback(disconnected) serverConnectionLostDeferred.addCallback(disconnected) return gatherResults([lostConnectionDeferred, serverConnectionLostDeferred]) def onListen(): portDeferred.addCallback(listening) portDeferred.addErrback(err) portDeferred.addCallback(lambda ignored: reactor.stop()) needsRunningReactor(reactor, onListen) self.runReactor(reactor) self.assertEqual(finished, [True, True])
def test_addresses(self): """ A client's transport's C{getHost} and C{getPeer} return L{IPv4Address} instances which have the dotted-quad string form of the resolved adddress of the local and remote endpoints of the connection respectively as their C{host} attribute, not the hostname originally passed in to L{connectTCP <twisted.internet.interfaces.IReactorTCP.connectTCP>}, if a hostname was used. """ host, port = findFreePort(self.interface, self.family)[:2] reactor = self.buildReactor() fakeDomain = self.fakeDomainName reactor.installResolver(FakeResolver({fakeDomain: self.interface})) 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 def connectMe(): reactor.connectTCP( fakeDomain, server.getHost().port, clientFactory, bindAddress=(self.interface, port)) needsRunningReactor(reactor, connectMe) self.runReactor(reactor) if clientFactory.failReason: self.fail(clientFactory.failReason.getTraceback()) self.assertEqual( addresses['host'], self.addressClass('TCP', self.interface, port)) self.assertEqual( addresses['peer'], self.addressClass('TCP', self.interface, serverAddress.port))
def test_protocolGarbageAfterLostConnection(self): """ After the connection a protocol is being used for is closed, the reactor discards all of its references to the protocol. """ lostConnectionDeferred = Deferred() clientProtocol = ClosingLaterProtocol(lostConnectionDeferred) clientRef = ref(clientProtocol) reactor = self.buildReactor() portDeferred = self.endpoints.server(reactor).listen( ServerFactory.forProtocol(Protocol)) def listening(port): msg(f"Listening on {port.getHost()!r}") endpoint = self.endpoints.client(reactor, port.getHost()) client = endpoint.connect( ClientFactory.forProtocol(lambda: clientProtocol)) def disconnect(proto): msg(f"About to disconnect {proto!r}") proto.transport.loseConnection() client.addCallback(disconnect) client.addErrback(lostConnectionDeferred.errback) return lostConnectionDeferred def onListening(): portDeferred.addCallback(listening) portDeferred.addErrback(err) portDeferred.addBoth(lambda ignored: reactor.stop()) needsRunningReactor(reactor, onListening) self.runReactor(reactor) # Drop the reference and get the garbage collector to tell us if there # are no references to the protocol instance left in the reactor. clientProtocol = None collect() self.assertIsNone(clientRef())
def test_stopOnlyCloses(self): """ When the L{IListeningPort} returned by L{IReactorSocket.adoptStreamPort} is stopped using C{stopListening}, the underlying socket is closed but not shutdown. This allows another process which still has a reference to it to continue accepting connections over it. """ reactor = self.buildReactor() portSocket = socket.socket() self.addCleanup(portSocket.close) portSocket.bind(("127.0.0.1", 0)) portSocket.listen(1) portSocket.setblocking(False) # The file descriptor is duplicated by adoptStreamPort port = reactor.adoptStreamPort( portSocket.fileno(), portSocket.family, ServerFactory() ) d = port.stopListening() def stopped(ignored): # Should still be possible to accept a connection on # portSocket. If it was shutdown, the exception would be # EINVAL instead. exc = self.assertRaises(socket.error, portSocket.accept) if platform.isWindows(): self.assertEqual(exc.args[0], errno.WSAEWOULDBLOCK) else: self.assertEqual(exc.args[0], errno.EAGAIN) d.addCallback(stopped) d.addErrback(err, "Failed to accept on original port.") needsRunningReactor( reactor, lambda: d.addCallback(lambda ignored: reactor.stop()) ) reactor.run()
def test_protocolGarbageAfterLostConnection(self): """ After the connection a protocol is being used for is closed, the reactor discards all of its references to the protocol. """ lostConnectionDeferred = Deferred() clientProtocol = ClosingLaterProtocol(lostConnectionDeferred) clientRef = ref(clientProtocol) reactor = self.buildReactor() portDeferred = self.endpoints.server(reactor).listen(ServerFactory.forProtocol(Protocol)) def listening(port): msg("Listening on %r" % (port.getHost(),)) endpoint = self.endpoints.client(reactor, port.getHost()) client = endpoint.connect(ClientFactory.forProtocol(lambda: clientProtocol)) def disconnect(proto): msg("About to disconnect %r" % (proto,)) proto.transport.loseConnection() client.addCallback(disconnect) client.addErrback(lostConnectionDeferred.errback) return lostConnectionDeferred def onListening(): portDeferred.addCallback(listening) portDeferred.addErrback(err) portDeferred.addBoth(lambda ignored: reactor.stop()) needsRunningReactor(reactor, onListening) self.runReactor(reactor) # Drop the reference and get the garbage collector to tell us if there # are no references to the protocol instance left in the reactor. clientProtocol = None collect() self.assertIdentical(None, clientRef())
def runProtocolsWithReactor( reactorBuilder, serverProtocol, clientProtocol, endpointCreator ): """ Connect two protocols using endpoints and a new reactor instance. A new reactor will be created and run, with the client and server protocol instances connected to each other using the given endpoint creator. The protocols should run through some set of tests, then disconnect; when both have disconnected the reactor will be stopped and the function will return. @param reactorBuilder: A L{ReactorBuilder} instance. @param serverProtocol: A L{ConnectableProtocol} that will be the server. @param clientProtocol: A L{ConnectableProtocol} that will be the client. @param endpointCreator: An instance of L{EndpointCreator}. @return: The reactor run by this test. """ reactor = reactorBuilder.buildReactor() serverProtocol._setAttributes(reactor, Deferred()) clientProtocol._setAttributes(reactor, Deferred()) serverFactory = _SingleProtocolFactory(serverProtocol) clientFactory = _SingleProtocolFactory(clientProtocol) # Listen on a port: serverEndpoint = endpointCreator.server(reactor) d = serverEndpoint.listen(serverFactory) # Connect to the port: def gotPort(p): clientEndpoint = endpointCreator.client(reactor, p.getHost()) return clientEndpoint.connect(clientFactory) d.addCallback(gotPort) # Stop reactor when both connections are lost: def failed(result): log.err(result, "Connection setup failed.") disconnected = gatherResults([serverProtocol._done, clientProtocol._done]) d.addCallback(lambda _: disconnected) d.addErrback(failed) d.addCallback(lambda _: needsRunningReactor(reactor, reactor.stop)) reactorBuilder.runReactor(reactor) return reactor
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() self.listen(reactor, ServerFactory.forProtocol(Protocol)) connected = [] class CheckConnection(Protocol): def connectionMade(self): connected.append(self) reactor.stop() clientFactory = Stop(reactor) clientFactory.protocol = CheckConnection needsRunningReactor(reactor, lambda: self.connect(reactor, clientFactory)) reactor.run() self.assertTrue(connected)
def runProtocolsWithReactor(reactorBuilder, serverProtocol, clientProtocol, endpointCreator): """ Connect two protocols using endpoints and a new reactor instance. A new reactor will be created and run, with the client and server protocol instances connected to each other using the given endpoint creator. The protocols should run through some set of tests, then disconnect; when both have disconnected the reactor will be stopped and the function will return. @param reactorBuilder: A L{ReactorBuilder} instance. @param serverProtocol: A L{ConnectableProtocol} that will be the server. @param clientProtocol: A L{ConnectableProtocol} that will be the client. @param endpointCreator: An instance of L{EndpointCreator}. @return: The reactor run by this test. """ reactor = reactorBuilder.buildReactor() serverProtocol._setAttributes(reactor, Deferred()) clientProtocol._setAttributes(reactor, Deferred()) serverFactory = _SingleProtocolFactory(serverProtocol) clientFactory = _SingleProtocolFactory(clientProtocol) # Listen on a port: serverEndpoint = endpointCreator.server(reactor) d = serverEndpoint.listen(serverFactory) # Connect to the port: def gotPort(p): clientEndpoint = endpointCreator.client( reactor, p.getHost()) return clientEndpoint.connect(clientFactory) d.addCallback(gotPort) # Stop reactor when both connections are lost: def failed(result): log.err(result, "Connection setup failed.") disconnected = gatherResults([serverProtocol._done, clientProtocol._done]) d.addCallback(lambda _: disconnected) d.addErrback(failed) d.addCallback(lambda _: needsRunningReactor(reactor, reactor.stop)) reactorBuilder.runReactor(reactor) return reactor