def setUp(self): self.t = tracking.MessageTracker() self.listener = unittest.mock.Mock() for ev in ["on_closed", "on_state_changed"]: cb = getattr(self.listener, ev) cb.return_value = None getattr(self.t, ev).connect(cb)
def test_attach_tracker_sets_aborted_on_other_exception(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) token = unittest.mock.Mock() self.assertIs(self.s.attach_tracker(msg, tracker, token), tracker) class FooException(Exception): pass token.future.add_done_callback.assert_called_once_with( unittest.mock.ANY, ) token.future.result.side_effect = FooException() _, (cb, ), _ = token.future.add_done_callback.mock_calls[0] cb(token.future) self.assertEqual( tracker.state, tracking.MessageState.ABORTED, )
def test_attach_tracker_with_subsequent_error_from_bare_modifies_tracking( self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs( self.s.attach_tracker(msg, tracker), tracker ) error = msg.make_error(aioxmpp.stanza.Error.from_exception( aioxmpp.XMPPCancelError( (namespaces.stanzas, "feature-not-implemented") ) )) error.from_ = error.from_.bare() self.assertIsNone(self.s._inbound_message_filter(error)) self.assertEqual( tracker.state, tracking.MessageState.ERROR ) self.assertIs( tracker.response, error, )
def test_attach_tracker_does_not_set_error_if_in_seen_state(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs( self.s.attach_tracker(msg, tracker), tracker ) tracker._set_state(tracking.MessageState.SEEN_BY_RECIPIENT) error = msg.make_error(aioxmpp.stanza.Error.from_exception( aioxmpp.XMPPCancelError( (namespaces.stanzas, "feature-not-implemented") ) )) self.assertIsNone(self.s._inbound_message_filter(error)) self.assertEqual( tracker.state, tracking.MessageState.SEEN_BY_RECIPIENT ) self.assertIs( tracker.response, None, )
def test_inbound_message_filter_ignores_closed_tracker(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs( self.s.attach_tracker(msg, tracker), tracker ) tracker.close() error = msg.make_error(aioxmpp.stanza.Error.from_exception( aioxmpp.XMPPCancelError( (namespaces.stanzas, "feature-not-implemented") ) )) self.assertIs(error, self.s._inbound_message_filter(error)) self.assertEqual( tracker.state, tracking.MessageState.IN_TRANSIT, ) self.assertTrue(tracker.closed)
def test_attach_tracker_ignores_cancelled_stanza_token(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) token = unittest.mock.Mock() self.assertIs( self.s.attach_tracker(msg, tracker, token), tracker ) token.future.add_done_callback.assert_called_once_with( unittest.mock.ANY, ) token.future.result.side_effect = asyncio.CancelledError() _, (cb, ), _ = token.future.add_done_callback.mock_calls[0] cb(token.future) self.assertEqual( tracker.state, tracking.MessageState.IN_TRANSIT, )
def test_attach_tracker_sets_delivered_to_server_if_ok(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) token = unittest.mock.Mock() self.assertIs( self.s.attach_tracker(msg, tracker, token), tracker ) token.future.add_done_callback.assert_called_once_with( unittest.mock.ANY, ) _, (cb, ), _ = token.future.add_done_callback.mock_calls[0] cb(token.future) self.assertEqual( tracker.state, tracking.MessageState.DELIVERED_TO_SERVER, )
def test_attach_tracker_with_subsequent_error_from_other_id_untracked( self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs( self.s.attach_tracker(msg, tracker), tracker ) error = msg.make_error(aioxmpp.stanza.Error.from_exception( aioxmpp.XMPPCancelError( (namespaces.stanzas, "feature-not-implemented") ) )) error.id_ = "fnord" self.assertIs(self.s._inbound_message_filter(error), error) self.assertEqual( tracker.state, tracking.MessageState.IN_TRANSIT ) self.assertIs( tracker.response, None, )
def test_attach_tracker_with_subsequent_chat_is_not_tracked(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs(self.s.attach_tracker(msg, tracker), tracker) reply = msg.make_reply() reply.id_ = msg.id_ self.assertIs(reply, self.s._inbound_message_filter(reply)) self.assertEqual(tracker.state, tracking.MessageState.IN_TRANSIT)
def test__set_state_rejects_transitions_to_in_transit(self): for state in tracking.MessageState: t = tracking.MessageTracker() if state != t.state: t._set_state(state, unittest.mock.sentinel.response) on_state_changed = unittest.mock.Mock() t.on_state_changed.connect(on_state_changed) with self.assertRaisesRegex(ValueError, "transition from .* to .*not allowed"): t._set_state(tracking.MessageState.IN_TRANSIT) on_state_changed.assert_not_called() self.assertEqual( t.state, state, ) if state != t.state: self.assertEqual( t.response, unittest.mock.sentinel.response, )
def test_attach_tracker_with_subsequent_error_modifies_tracking(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs(self.s.attach_tracker(msg, tracker), tracker) error = msg.make_error( aioxmpp.stanza.Error.from_exception( aioxmpp.XMPPCancelError( aioxmpp.ErrorCondition.FEATURE_NOT_IMPLEMENTED))) self.assertIsNone(self.s._inbound_message_filter(error)) self.assertEqual(tracker.state, tracking.MessageState.ERROR) self.assertIs( tracker.response, error, )
def test_inbound_message_filter_ignores_closed_tracker(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs(self.s.attach_tracker(msg, tracker), tracker) tracker.close() error = msg.make_error( aioxmpp.stanza.Error.from_exception( aioxmpp.XMPPCancelError( aioxmpp.ErrorCondition.FEATURE_NOT_IMPLEMENTED))) self.assertIs(error, self.s._inbound_message_filter(error)) self.assertEqual( tracker.state, tracking.MessageState.IN_TRANSIT, ) self.assertTrue(tracker.closed)
def test_attach_tracker_handler_does_not_raise_exception_if_state_already_set( self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) token = unittest.mock.Mock() self.assertIs(self.s.attach_tracker(msg, tracker, token), tracker) token.future.add_done_callback.assert_called_once_with( unittest.mock.ANY, ) _, (cb, ), _ = token.future.add_done_callback.mock_calls[0] tracker._set_state(tracking.MessageState.DELIVERED_TO_RECIPIENT) cb(token.future) self.assertEqual( tracker.state, tracking.MessageState.DELIVERED_TO_RECIPIENT, )
def test_attach_tracker_does_not_set_error_if_in_delivered_state(self): tracker = tracking.MessageTracker() msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, from_=TEST_LOCAL, to=TEST_PEER, ) self.assertIs(self.s.attach_tracker(msg, tracker), tracker) tracker._set_state(tracking.MessageState.DELIVERED_TO_RECIPIENT) error = msg.make_error( aioxmpp.stanza.Error.from_exception( aioxmpp.XMPPCancelError( aioxmpp.ErrorCondition.FEATURE_NOT_IMPLEMENTED))) self.assertIsNone(self.s._inbound_message_filter(error)) self.assertEqual(tracker.state, tracking.MessageState.DELIVERED_TO_RECIPIENT) self.assertIs( tracker.response, None, )
def setUp(self): self.stanza = aioxmpp.stanza.Message(type_=structs.MessageType.CHAT) self.token = stream.StanzaToken(self.stanza) self.tr = tracking.MessageTracker(self.token)
def setUp(self): self.stanza = aioxmpp.stanza.Message(type_="chat") self.token = stream.StanzaToken(self.stanza) self.tr = tracking.MessageTracker(self.token)
def test__set_state_rejects_some_other_transitions(self): to_reject = [ ( tracking.MessageState.DELIVERED_TO_RECIPIENT, tracking.MessageState.DELIVERED_TO_SERVER, ), ( tracking.MessageState.SEEN_BY_RECIPIENT, tracking.MessageState.DELIVERED_TO_SERVER, ), ( tracking.MessageState.SEEN_BY_RECIPIENT, tracking.MessageState.DELIVERED_TO_RECIPIENT, ), ] for state1, state2 in itertools.product(tracking.MessageState, tracking.MessageState): if state1 == tracking.MessageState.ABORTED: # already tested elsewhere continue if state1 == tracking.MessageState.ERROR: # already tested elsewhere continue if state2 == tracking.MessageState.IN_TRANSIT: # already tested elsewhere continue t = tracking.MessageTracker() if state1 != t.state: t._set_state(state1, unittest.mock.sentinel.response) on_state_changed = unittest.mock.Mock() t.on_state_changed.connect(on_state_changed) if (state1, state2) in to_reject: with self.assertRaisesRegex( ValueError, "transition from .* to .*not allowed", msg=(state1, state2)): t._set_state(state2) on_state_changed.assert_not_called() self.assertEqual( t.state, state1, ) if state1 != t.state: self.assertEqual( t.response, unittest.mock.sentinel.response, ) else: t._set_state(state2, unittest.mock.sentinel.response2) self.assertEqual( t.state, state2, ) self.assertEqual( t.response, unittest.mock.sentinel.response2, )