def test_propose(self): """Test that a Propose can be sent correctly.""" propose_empty = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.PROPOSE, proposal=[], ) propose_empty.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(propose_empty), ) ) envelope = self.multiplexer2.get(block=True, timeout=2.0) expected_propose_empty = FIPASerializer().decode(envelope.message) expected_propose_empty.counterparty = self.crypto2.address assert expected_propose_empty == propose_empty propose_descriptions = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.PROPOSE, proposal=[ Description( {"foo": "bar"}, DataModel("foobar", [Attribute("foo", str, True)]) ) ], ) propose_descriptions.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(propose_descriptions), ) ) envelope = self.multiplexer2.get(block=True, timeout=2.0) expected_propose_descriptions = FIPASerializer().decode(envelope.message) expected_propose_descriptions.counterparty = self.crypto2.address assert expected_propose_descriptions == propose_descriptions
def test_fipa_cfp_serialization_bytes(): """Test that the serialization - deserialization for the 'fipa' protocol works.""" query = b"Hello" msg = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.CFP, query=query, ) msg.counterparty = "sender" msg_bytes = FIPASerializer().encode(msg) envelope = Envelope( to="receiver", sender="sender", protocol_id=FIPAMessage.protocol_id, message=msg_bytes, ) envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope == actual_envelope actual_msg = FIPASerializer().decode(actual_envelope.message) actual_msg.counterparty = "sender" expected_msg = msg assert expected_msg == actual_msg deserialised_msg = FIPASerializer().decode(envelope.message) deserialised_msg.counterparty = "sender" assert msg.get("performative") == deserialised_msg.get("performative")
def test_fipa_accept_serialization(): """Test that the serialization for the 'fipa' protocol works.""" msg = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.ACCEPT, ) msg.counterparty = "sender" msg_bytes = FIPASerializer().encode(msg) envelope = Envelope( to="receiver", sender="sender", protocol_id=FIPAMessage.protocol_id, message=msg_bytes, ) envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope == actual_envelope actual_msg = FIPASerializer().decode(actual_envelope.message) actual_msg.counterparty = "sender" expected_msg = msg assert expected_msg == actual_msg
def test_cfp(self): """Test that a CFP can be sent correctly.""" cfp_message = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.CFP, query=Query([Constraint("something", ConstraintType(">", 1))]), ) cfp_message.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(cfp_message), ) ) envelope = self.multiplexer2.get(block=True, timeout=5.0) expected_cfp_message = FIPASerializer().decode(envelope.message) expected_cfp_message.counterparty = self.crypto2.address assert expected_cfp_message == cfp_message cfp_none = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.CFP, query=None, ) cfp_none.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(cfp_none), ) ) envelope = self.multiplexer2.get(block=True, timeout=5.0) expected_cfp_none = FIPASerializer().decode(envelope.message) expected_cfp_none.counterparty = self.crypto2.address assert expected_cfp_none == cfp_none
def test_error_handler_handle(self): """Test the handle function.""" msg = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.ACCEPT, ) msg.counterparty = "a_counterparty" self.my_error_handler.handle(message=msg)
def test_decline(self): """Test that a Decline can be sent correctly.""" decline = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.DECLINE, ) decline.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(decline), ) ) envelope = self.multiplexer2.get(block=True, timeout=2.0) expected_decline = FIPASerializer().decode(envelope.message) expected_decline.counterparty = self.crypto2.address assert expected_decline == decline
def test_accept(self): """Test that an Accept can be sent correctly.""" accept = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.ACCEPT, ) accept.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(accept), ) ) envelope = self.multiplexer2.get(block=True, timeout=2.0) expected_accept = FIPASerializer().decode(envelope.message) expected_accept.counterparty = self.crypto2.address assert expected_accept == accept
def test_accept_w_inform(self): """Test that an accept with address can be sent correctly.""" accept_w_inform = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.ACCEPT_W_INFORM, info={"address": "my_address"}, ) accept_w_inform.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(accept_w_inform), ) ) envelope = self.multiplexer2.get(block=True, timeout=2.0) returned_accept_w_inform = FIPASerializer().decode(envelope.message) returned_accept_w_inform.counterparty = self.crypto2.address assert returned_accept_w_inform == accept_w_inform
def test_match_accept(self): """Test that a match accept can be sent correctly.""" # NOTE since the OEF SDK doesn't support the match accept, we have to use a fixed message id! match_accept = FIPAMessage( message_id=4, dialogue_reference=(str(0), ""), target=3, performative=FIPAMessage.Performative.MATCH_ACCEPT, ) match_accept.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(match_accept), ) ) envelope = self.multiplexer2.get(block=True, timeout=2.0) expected_match_accept = FIPASerializer().decode(envelope.message) expected_match_accept.counterparty = self.crypto2.address assert expected_match_accept == match_accept
def test_performative_match_accept(): """Test the serialization - deserialization of the match_accept performative.""" msg = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=1, performative=FIPAMessage.Performative.MATCH_ACCEPT, ) msg_bytes = FIPASerializer().encode(msg) envelope = Envelope( to="receiver", sender="sender", protocol_id=FIPAMessage.protocol_id, message=msg_bytes, ) msg.counterparty = "sender" envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope == actual_envelope deserialised_msg = FIPASerializer().decode(envelope.message) assert msg.get("performative") == deserialised_msg.get("performative")
def test_inform(self): """Test that an inform can be sent correctly.""" payload = {"foo": "bar"} inform = FIPAMessage( message_id=0, dialogue_reference=(str(0), ""), target=0, performative=FIPAMessage.Performative.INFORM, info=payload, ) inform.counterparty = self.crypto2.address self.multiplexer1.put( Envelope( to=self.crypto2.address, sender=self.crypto1.address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(inform), ) ) envelope = self.multiplexer2.get(block=True, timeout=2.0) returned_inform = FIPASerializer().decode(envelope.message) returned_inform.counterparty = self.crypto2.address assert returned_inform == inform
def test_dialogues_self_initiated_is_seller(self): """Test an end to end scenario of seller-client dialogue.""" # Initialise a dialogue seller_dialogue = self.seller_dialogues.create_self_initiated( dialogue_opponent_addr=self.client_addr, dialogue_starter_addr=self.seller_addr, is_seller=True, ) # Register the dialogue to the dictionary of dialogues. self.seller_dialogues.dialogues[seller_dialogue.dialogue_label] = cast( FIPADialogue, seller_dialogue ) # Send a message to the client. cfp_msg = FIPAMessage( message_id=1, dialogue_reference=seller_dialogue.dialogue_label.dialogue_reference, target=0, performative=FIPAMessage.Performative.CFP, query=None, ) cfp_msg.counterparty = self.seller_addr seller_dialogue.outgoing_extend(cfp_msg) # Creates a new dialogue for the client side based on the income message. client_dialogue = self.client_dialogues.create_opponent_initiated( dialogue_opponent_addr=cfp_msg.counterparty, dialogue_reference=cfp_msg.dialogue_reference, is_seller=False, ) # Register the dialogue to the dictionary of dialogues. self.client_dialogues.dialogues[client_dialogue.dialogue_label] = cast( FIPADialogue, client_dialogue ) # Extend the incoming list of messages. client_dialogue.incoming_extend(cfp_msg) # Checks if the message we received is permitted for a new dialogue or if it is a registered dialogue. assert self.client_dialogues.is_permitted_for_new_dialogue( client_dialogue.last_incoming_message ), "Should be permitted since the first incoming msg is CFP" # Generate a proposal message to send to the seller. proposal = [ Description({"foo1": 1, "bar1": 2}), Description({"foo2": 1, "bar2": 2}), ] message_id = cfp_msg.message_id + 1 target = cfp_msg.message_id proposal_msg = FIPAMessage( message_id=message_id, dialogue_reference=client_dialogue.dialogue_label.dialogue_reference, target=target, performative=FIPAMessage.Performative.PROPOSE, proposal=proposal, ) proposal_msg.counterparty = self.client_addr # Extends the outgoing list of messages. client_dialogue.outgoing_extend(proposal_msg) # Seller received the message and we extend the incoming messages list. seller_dialogue.incoming_extend(proposal_msg) assert not self.seller_dialogues.is_permitted_for_new_dialogue( seller_dialogue.last_incoming_message ), "Should not be permitted since we registered the cfp message." response = self.seller_dialogues.is_belonging_to_registered_dialogue( proposal_msg, agent_addr=self.seller_addr ) assert response, "We expect the response from the function to be true." # Test the self_initiated_dialogue explicitly message_id = proposal_msg.message_id + 1 target = proposal_msg.message_id accept_msg = FIPAMessage( message_id=message_id, dialogue_reference=seller_dialogue.dialogue_label.dialogue_reference, target=target, performative=FIPAMessage.Performative.ACCEPT_W_INFORM, info={"address": "dummy_address"}, ) accept_msg.counterparty = self.client_addr # Adds the message to the client outgoing list. seller_dialogue.outgoing_extend(accept_msg) # Adds the message to the seller incoming message list. client_dialogue.incoming_extend(accept_msg) # Check if this message is registered to a dialogue. response = self.seller_dialogues.is_belonging_to_registered_dialogue( accept_msg, agent_addr=self.seller_addr ) assert not response, "We expect the response from the function to be true."
def test_dialogues_self_initiated_no_seller(self): """Test an end to end scenario of client-seller dialogue.""" # Initialise a dialogue client_dialogue = self.client_dialogues.create_self_initiated( dialogue_opponent_addr=self.seller_addr, dialogue_starter_addr=self.client_addr, is_seller=False, ) # Register the dialogue to the dictionary of dialogues. self.client_dialogues.dialogues[client_dialogue.dialogue_label] = cast( FIPADialogue, client_dialogue ) # Send a message to the seller. cfp_msg = FIPAMessage( message_id=1, dialogue_reference=client_dialogue.dialogue_label.dialogue_reference, target=0, performative=FIPAMessage.Performative.CFP, query=None, ) cfp_msg.counterparty = self.client_addr # Checking that I cannot retrieve the dialogue. retrieved_dialogue = self.client_dialogues.is_belonging_to_registered_dialogue( cfp_msg, "client" ) assert not retrieved_dialogue, "Should not belong to registered dialogue" # Checking the value error when we are trying to retrieve an un-existing dialogue. with pytest.raises(ValueError, match="Should have found dialogue."): self.client_dialogues.get_dialogue(cfp_msg, self.client_addr) # Extends the outgoing list of messages. client_dialogue.outgoing_extend(cfp_msg) # Creates a new dialogue for the seller side based on the income message. seller_dialogue = self.seller_dialogues.create_opponent_initiated( dialogue_opponent_addr=cfp_msg.counterparty, dialogue_reference=cfp_msg.dialogue_reference, is_seller=True, ) # Register the dialogue to the dictionary of dialogues. self.seller_dialogues.dialogues[seller_dialogue.dialogue_label] = cast( FIPADialogue, seller_dialogue ) # Extend the incoming list of messages. seller_dialogue.incoming_extend(cfp_msg) # Check that both fields in the dialogue_reference are set. last_msg = seller_dialogue.last_incoming_message assert last_msg == cfp_msg, "The messages must be equal" dialogue_reference = cast( Tuple[str, str], last_msg.body.get("dialogue_reference") ) assert ( dialogue_reference[0] != "" and dialogue_reference[1] == "" ), "The dialogue_reference is not set correctly." # Checks if the message we received is permitted for a new dialogue or if it is a registered dialogue. assert self.seller_dialogues.is_permitted_for_new_dialogue( seller_dialogue.last_incoming_message ), "Should be permitted since the first incoming msg is CFP" # Generate a proposal message to send to the client. proposal = [ Description({"foo1": 1, "bar1": 2}), Description({"foo2": 1, "bar2": 2}), ] message_id = cfp_msg.message_id + 1 target = cfp_msg.message_id proposal_msg = FIPAMessage( message_id=message_id, dialogue_reference=seller_dialogue.dialogue_label.dialogue_reference, target=target, performative=FIPAMessage.Performative.PROPOSE, proposal=proposal, ) proposal_msg.counterparty = self.seller_addr # Extends the outgoing list of messages. seller_dialogue.outgoing_extend(proposal_msg) # Client received the message and we extend the incoming messages list. client_dialogue.incoming_extend(proposal_msg) # Check that both fields in the dialogue_reference are set. last_msg = client_dialogue.last_incoming_message assert last_msg == proposal_msg, "The two messages must be equal." dialogue_reference = cast( Tuple[str, str], last_msg.body.get("dialogue_reference") ) assert ( dialogue_reference[0] != "" and dialogue_reference[1] != "" ), "The dialogue_reference is not setup properly." assert not self.client_dialogues.is_permitted_for_new_dialogue( client_dialogue.last_incoming_message ), "Should not be permitted since we registered the cfp message." response = self.client_dialogues.is_belonging_to_registered_dialogue( proposal_msg, agent_addr=self.client_addr ) assert response, "We expect the response from the function to be true." # Retrieve the dialogue based on the received message. retrieved_dialogue = self.client_dialogues.get_dialogue( proposal_msg, self.client_addr ) assert retrieved_dialogue.dialogue_label is not None # Create an accept_w_inform message to send seller. message_id = proposal_msg.message_id + 1 target = proposal_msg.message_id accept_msg = FIPAMessage( message_id=message_id, dialogue_reference=client_dialogue.dialogue_label.dialogue_reference, target=target, performative=FIPAMessage.Performative.ACCEPT_W_INFORM, info={"address": "dummy_address"}, ) accept_msg.counterparty = self.client_addr # Adds the message to the client outgoing list. client_dialogue.outgoing_extend(accept_msg) # Adds the message to the seller incoming message list. seller_dialogue.incoming_extend(accept_msg) # Check if this message is registered to a dialogue. response = self.seller_dialogues.is_belonging_to_registered_dialogue( accept_msg, agent_addr=self.seller_addr ) assert response, "We expect the response from the function to be true." retrieved_dialogue = self.seller_dialogues.get_dialogue( accept_msg, self.seller_addr ) assert retrieved_dialogue.dialogue_label in self.seller_dialogues.dialogues