Close correctly your PB clients and servers in trial
Having a DirtyReactorException in your tests is a PITA and bug 885342 was that type on annoying bug. Since I use this bug not only to tell others what I’m doing but as a log for myself here it is the way to clean the resources nicely when you are testing your PB clients and servers (I mention PB because we use that, a similar approach can be used with any protocol) inspired by this way more interesting post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | class SaveProtocolServerFactory(PBServerFactory): """A PBServerFactory that saves the latest connected client.""" protocolInstance = None def clientConnectionMade(self, protocol): """Keep track of the given protocol.""" self.protocolInstance = protocol class SaveClientFactory(PBClientFactory): """Client Factory that knows when we disconnected.""" def __init__(self, connected_d, disconnected_d): """Create a new instance.""" PBClientFactory.__init__(self) self.connected_d = connected_d self.disconnected_d = disconnected_d def clientConnectionMade(self, broker): """Connection made.""" PBClientFactory.clientConnectionMade(self, broker) self.connected_d.callback(True) def clientConnectionLost(self, connector, reason, reconnecting=0): """Connection lost.""" self.disconnected_d.callback(True) class ServerProtocol(Broker): """Server protocol that allows us to clean the tests.""" def connectionLost(self, *a): self.factory.onConnectionLost.callback(self) class ConnectedTestCase(TestCase): """Base test case with a client and a server.""" @defer.inlineCallbacks def setUp(self): """Set up for the tests.""" yield super(ConnectedTestCase, self).setUp() self.server_disconnected = defer.Deferred() self.client_disconnected = defer.Deferred() self.listener = None self.connector = None self.server_factory = None self.client_factory = None def setup_client_server(self, sso_root): """Set tests.""" port = get_sso_pb_port() self.listener = self._listen_server(sso_root, self.server_disconnected, port) connected = defer.Deferred() self.connector = self._connect_client(connected, self.client_disconnected, port) self.addCleanup(self.teardown_client_server) return connected def _listen_server(self, sso_root, d, port): """Start listenting.""" self.server_factory = SaveProtocolServerFactory(sso_root) self.server_factory.onConnectionLost = d self.server_factory.protocol = ServerProtocol return reactor.listenTCP(port, self.server_factory) def _connect_client(self, d1, d2, port): """Connect client.""" self.client_factory = SaveClientFactory(d1, d2) return reactor.connectTCP(LOCALHOST, port, self.client_factory) def teardown_client_server(self): """Clean resources.""" self.connector.disconnect() d = defer.maybeDeferred(self.listener.stopListening) return defer.gatherResults([d, self.client_disconnected, self.server_disconnected]) |





Pingback: The windows tests are dirty!! | Macaque Project