class HandlerSwitcherTests(NeoUnitTestBase): def setUp(self): NeoUnitTestBase.setUp(self) self._handler = handler = Mock({ '__repr__': 'initial handler', }) self._connection = Mock({ '__repr__': 'connection', 'getAddress': ('127.0.0.1', 10000), }) self._handlers = HandlerSwitcher(handler) def _makeNotification(self, msg_id): packet = Packets.StartOperation() packet.setId(msg_id) return packet def _makeRequest(self, msg_id): packet = Packets.AskBeginTransaction() packet.setId(msg_id) return packet def _makeAnswer(self, msg_id): packet = Packets.AnswerBeginTransaction(self.getNextTID()) packet.setId(msg_id) return packet def _makeHandler(self): return Mock({'__repr__': 'handler'}) def _checkPacketReceived(self, handler, packet, index=0): calls = handler.mockGetNamedCalls('packetReceived') self.assertEqual(len(calls), index + 1) def _checkCurrentHandler(self, handler): self.assertTrue(self._handlers.getHandler() is handler) def testInit(self): self._checkCurrentHandler(self._handler) self.assertFalse(self._handlers.isPending()) def testEmit(self): # First case, emit is called outside of a handler self.assertFalse(self._handlers.isPending()) request = self._makeRequest(1) self._handlers.emit(request, 0, None) self.assertTrue(self._handlers.isPending()) # Second case, emit is called from inside a handler with a pending # handler change. new_handler = self._makeHandler() applied = self._handlers.setHandler(new_handler) self.assertFalse(applied) self._checkCurrentHandler(self._handler) call_tracker = [] def packetReceived(conn, packet, kw): self._handlers.emit(self._makeRequest(2), 0, None) call_tracker.append(True) self._handler.packetReceived = packetReceived self._handlers.handle(self._connection, self._makeAnswer(1)) self.assertEqual(call_tracker, [True]) # Effective handler must not have changed (new request is blocking # it) self._checkCurrentHandler(self._handler) # Handling the next response will cause the handler to change delattr(self._handler, 'packetReceived') self._handlers.handle(self._connection, self._makeAnswer(2)) self._checkCurrentHandler(new_handler) def testHandleNotification(self): # handle with current handler notif1 = self._makeNotification(1) self._handlers.handle(self._connection, notif1) self._checkPacketReceived(self._handler, notif1) # emit a request and delay an handler request = self._makeRequest(2) self._handlers.emit(request, 0, None) handler = self._makeHandler() applied = self._handlers.setHandler(handler) self.assertFalse(applied) # next notification fall into the current handler notif2 = self._makeNotification(3) self._handlers.handle(self._connection, notif2) self._checkPacketReceived(self._handler, notif2, index=1) # handle with new handler answer = self._makeAnswer(2) self._handlers.handle(self._connection, answer) notif3 = self._makeNotification(4) self._handlers.handle(self._connection, notif3) self._checkPacketReceived(handler, notif2) def testHandleAnswer1(self): # handle with current handler request = self._makeRequest(1) self._handlers.emit(request, 0, None) answer = self._makeAnswer(1) self._handlers.handle(self._connection, answer) self._checkPacketReceived(self._handler, answer) def testHandleAnswer2(self): # handle with blocking handler request = self._makeRequest(1) self._handlers.emit(request, 0, None) handler = self._makeHandler() applied = self._handlers.setHandler(handler) self.assertFalse(applied) answer = self._makeAnswer(1) self._handlers.handle(self._connection, answer) self._checkPacketReceived(self._handler, answer) self._checkCurrentHandler(handler) def testHandleAnswer3(self): # multiple setHandler r1 = self._makeRequest(1) r2 = self._makeRequest(2) r3 = self._makeRequest(3) a1 = self._makeAnswer(1) a2 = self._makeAnswer(2) a3 = self._makeAnswer(3) h1 = self._makeHandler() h2 = self._makeHandler() h3 = self._makeHandler() # emit all requests and setHandleres self._handlers.emit(r1, 0, None) applied = self._handlers.setHandler(h1) self.assertFalse(applied) self._handlers.emit(r2, 0, None) applied = self._handlers.setHandler(h2) self.assertFalse(applied) self._handlers.emit(r3, 0, None) applied = self._handlers.setHandler(h3) self.assertFalse(applied) self._checkCurrentHandler(self._handler) self.assertTrue(self._handlers.isPending()) # process answers self._handlers.handle(self._connection, a1) self._checkCurrentHandler(h1) self._handlers.handle(self._connection, a2) self._checkCurrentHandler(h2) self._handlers.handle(self._connection, a3) self._checkCurrentHandler(h3) def testHandleAnswer4(self): # process out of order r1 = self._makeRequest(1) r2 = self._makeRequest(2) r3 = self._makeRequest(3) a1 = self._makeAnswer(1) a2 = self._makeAnswer(2) a3 = self._makeAnswer(3) h = self._makeHandler() # emit all requests self._handlers.emit(r1, 0, None) self._handlers.emit(r2, 0, None) self._handlers.emit(r3, 0, None) applied = self._handlers.setHandler(h) self.assertFalse(applied) # process answers self._handlers.handle(self._connection, a1) self._checkCurrentHandler(self._handler) self._handlers.handle(self._connection, a2) self._checkCurrentHandler(self._handler) self._handlers.handle(self._connection, a3) self._checkCurrentHandler(h) def testHandleUnexpected(self): # process out of order r1 = self._makeRequest(1) r2 = self._makeRequest(2) a2 = self._makeAnswer(2) h = self._makeHandler() # emit requests aroung state setHandler self._handlers.emit(r1, 0, None) applied = self._handlers.setHandler(h) self.assertFalse(applied) self._handlers.emit(r2, 0, None) # process answer for next state self._handlers.handle(self._connection, a2) self.checkAborted(self._connection)