def _search_for_tac(self) -> None: """ Search for active TAC Controller. We assume that the controller is registered as a service with the 'tac' data model and with an attribute version = expected_version_id. :return: None """ game = cast(Game, self.context.game) query = game.get_game_query() oef_search_dialogues = cast(OefSearchDialogues, self.context.oef_search_dialogues) oef_search_msg = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=oef_search_dialogues. new_self_initiated_dialogue_reference(), query=query, ) oef_search_msg.counterparty = self.context.search_service_address oef_search_dialogues.update(oef_search_msg) self.context.outbox.put_message(message=oef_search_msg) self.context.logger.info( "[{}]: Searching for TAC, search_id={}".format( self.context.agent_name, oef_search_msg.dialogue_reference))
def test_search_services_with_query_with_model(self): """Test that a search services request can be sent correctly. In this test, the query has a simple data model. """ data_model = DataModel("foobar", [Attribute("foo", str, True)]) search_query = Query( [Constraint("foo", ConstraintType("==", "bar"))], model=data_model ) oef_search_request = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=self.oef_search_dialogues.new_self_initiated_dialogue_reference(), query=search_query, ) oef_search_request.counterparty = DEFAULT_OEF sending_dialogue = self.oef_search_dialogues.update(oef_search_request) self.multiplexer.put( Envelope( to=DEFAULT_OEF, sender=FETCHAI_ADDRESS_ONE, protocol_id=OefSearchMessage.protocol_id, message=oef_search_request, ) ) envelope = self.multiplexer.get(block=True, timeout=5.0) oef_search_response = envelope.message oef_search_dialogue = self.oef_search_dialogues.update(oef_search_response) assert ( oef_search_response.performative == OefSearchMessage.Performative.SEARCH_RESULT ) assert oef_search_dialogue is not None assert oef_search_dialogue == sending_dialogue assert oef_search_response.agents == ()
def test_filtered_search_result(self): """Test that the search result contains only the entries matching the query.""" query = Query(constraints=[], model=self.data_model_barfoo) # build and send the request search_services_request = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=self.dialogues1.new_self_initiated_dialogue_reference(), query=query, ) search_services_request.counterparty = str(OEFLocalConnection.connection_id) sending_dialogue = cast( Optional[OefSearchDialogue], self.dialogues1.update(search_services_request) ) assert sending_dialogue is not None envelope = Envelope( to=search_services_request.counterparty, sender=search_services_request.sender, protocol_id=search_services_request.protocol_id, message=search_services_request, ) self.multiplexer1.put(envelope) # check the result response_envelope = InBox(self.multiplexer1).get(block=True, timeout=5.0) search_result_orig = cast(OefSearchMessage, response_envelope.message) search_result = copy.copy(search_result_orig) search_result.is_incoming = True search_result.counterparty = search_result_orig.sender response_dialogue = self.dialogues1.update(search_result) assert response_dialogue == sending_dialogue assert search_result.performative == OefSearchMessage.Performative.SEARCH_RESULT assert search_result.agents == (self.address_2,), self.node.services
def test_empty_search_result(self): """Test that at the beginning, the search request returns an empty search result.""" query = Query(constraints=[], model=None) # build and send the request search_services_request = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=self.dialogues.new_self_initiated_dialogue_reference(), query=query, ) search_services_request.counterparty = str(OEFLocalConnection.connection_id) sending_dialogue = cast( Optional[OefSearchDialogue], self.dialogues.update(search_services_request) ) assert sending_dialogue is not None envelope = Envelope( to=search_services_request.counterparty, sender=search_services_request.sender, protocol_id=search_services_request.protocol_id, message=search_services_request, ) self.multiplexer.put(envelope) # check the result response_envelope = self.multiplexer.get(block=True, timeout=2.0) assert response_envelope.protocol_id == OefSearchMessage.protocol_id search_result_orig = cast(OefSearchMessage, response_envelope.message) search_result = copy.copy(search_result_orig) search_result.is_incoming = True search_result.counterparty = search_result_orig.sender response_dialogue = self.dialogues.update(search_result) assert response_dialogue == sending_dialogue assert search_result.performative == OefSearchMessage.Performative.SEARCH_RESULT assert search_result.agents == ()
async def _send_error_response( self, oef_search_message: OefSearchMessage, oef_search_dialogue: OefSearchDialogue, oef_error_operation: OefErrorOperation = OefSearchMessage. OefErrorOperation.OTHER, ) -> None: """ Send an error response back. :param oef_search_message: the oef search message :param oef_search_dialogue: the oef search dialogue :param oef_error_operation: the error code to send back :return: None """ assert self.in_queue is not None, "Inqueue not set!" message = OefSearchMessage( performative=OefSearchMessage.Performative.OEF_ERROR, oef_error_operation=oef_error_operation, dialogue_reference=oef_search_dialogue.dialogue_label. dialogue_reference, target=oef_search_message.message_id, message_id=oef_search_message.message_id + 1, ) message.counterparty = oef_search_message.counterparty assert oef_search_dialogue.update(message) envelope = Envelope( to=message.counterparty, sender=SOEFConnection.connection_id.latest, protocol_id=message.protocol_id, message=message, ) await self.in_queue.put(envelope)
def test_on_oef_error(self): """Test the oef error.""" oef_connection = self.multiplexer1.connections[0] oef_channel = oef_connection.channel oef_channel.oef_msg_id += 1 dialogue_reference = ("1", "2") query = Query( constraints=[Constraint("foo", ConstraintType("==", "bar"))], model=None, ) dialogue = OefSearchDialogue( BaseDialogueLabel(dialogue_reference, "agent", "agent"), "agent", OefSearchDialogue.Role.OEF_NODE, ) oef_search_msg = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=dialogue_reference, query=query, ) oef_search_msg.is_incoming = True oef_search_msg.counterparty = "agent" dialogue._incoming_messages = [oef_search_msg] oef_channel.oef_msg_id_to_dialogue[oef_channel.oef_msg_id] = dialogue oef_channel.on_oef_error( answer_id=oef_channel.oef_msg_id, operation=OEFErrorOperation.SEARCH_SERVICES, ) envelope = self.multiplexer1.get(block=True, timeout=5.0) dec_msg = envelope.message assert dec_msg.dialogue_reference == dialogue_reference assert ( dec_msg.performative is OefSearchMessage.Performative.OEF_ERROR ), "It should be an error message"
def test_oef_error_serialization(): """Test the serialization for 'oef_error' speech-act works.""" msg = OefSearchMessage( performative=OefSearchMessage.Performative.OEF_ERROR, oef_error_operation=OefSearchMessage.OefErrorOperation.OTHER, ) msg.to = "receiver" envelope = Envelope( to=msg.to, sender="sender", protocol_id=OefSearchMessage.protocol_id, message=msg, ) envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope.to == actual_envelope.to assert expected_envelope.sender == actual_envelope.sender assert expected_envelope.protocol_id == actual_envelope.protocol_id assert expected_envelope.message != actual_envelope.message actual_msg = OefSearchMessage.serializer.decode(actual_envelope.message) actual_msg.to = actual_envelope.to actual_msg.sender = actual_envelope.sender expected_msg = msg assert expected_msg == actual_msg
async def test_wrong_dialogue(self): """Test that at the beginning, the search request returns an empty search result.""" query = Query(constraints=[Constraint("foo", ConstraintType("==", 1))], model=None) # build and send the request search_services_request = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, message_id=2, target=1, dialogue_reference=self.dialogues. new_self_initiated_dialogue_reference(), query=query, ) search_services_request.to = str(OEFLocalConnection.connection_id) # the incorrect message cannot be sent into a dialogue, so this is omitted. search_services_request.sender = self.address_1 envelope = Envelope( to=search_services_request.to, sender=search_services_request.sender, message=search_services_request, ) with unittest.mock.patch.object( self.node, "_handle_oef_message", side_effect=self.node._handle_oef_message) as mock_handle: with unittest.mock.patch.object(self.node.logger, "warning") as mock_logger: self.multiplexer.put(envelope) wait_for_condition(lambda: mock_handle.called, timeout=1.0) mock_logger.assert_any_call( AnyStringWith("Could not create dialogue for message="))
def test_success_serialization(): """Test the serialization for 'success' speech-act works.""" msg = OefSearchMessage( performative=OefSearchMessage.Performative.SUCCESS, agents_info=OefSearchMessage.AgentsInfo( { "key_1": {"key_1": b"value_1", "key_2": b"value_2"}, "key_2": {"key_3": b"value_3", "key_4": b"value_4"}, } ), ) msg.to = "receiver" envelope = Envelope(to=msg.to, sender="sender", message=msg,) envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope.to == actual_envelope.to assert expected_envelope.sender == actual_envelope.sender assert ( expected_envelope.protocol_specification_id == actual_envelope.protocol_specification_id ) assert expected_envelope.message != actual_envelope.message actual_msg = OefSearchMessage.serializer.decode(actual_envelope.message) actual_msg.to = actual_envelope.to actual_msg.sender = actual_envelope.sender expected_msg = msg assert expected_msg == actual_msg
def _search_services(self) -> None: """ Search on OEF Service Directory. In particular, search - for sellers and their supply, or - for buyers and their demand, or - for both. :return: None """ strategy = cast(Strategy, self.context.strategy) oef_search_dialogues = cast(OefSearchDialogues, self.context.oef_search_dialogues) query = strategy.get_location_and_service_query() for (is_seller_search, searching_for) in strategy.searching_for_types: oef_msg = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=oef_search_dialogues. new_self_initiated_dialogue_reference(), query=query, ) oef_msg.counterparty = self.context.search_service_address oef_search_dialogue = cast(Optional[OefSearchDialogue], oef_search_dialogues.update(oef_msg)) assert oef_search_dialogue is not None, "OefSearchDialogue not created." oef_search_dialogue.is_seller_search = is_seller_search self.context.outbox.put_message(message=oef_msg) self.context.logger.info("searching for {}, search_id={}.".format( searching_for, oef_msg.dialogue_reference))
async def test_bad_search_query(self, caplog): """Test fail on invalid query for search.""" await self.test_register_service() closeness_query = Query([], model=models.AGENT_LOCATION_MODEL) message = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=self.oef_search_dialogues.new_self_initiated_dialogue_reference(), query=closeness_query, ) message.counterparty = SOEFConnection.connection_id.latest sending_dialogue = self.oef_search_dialogues.update(message) assert sending_dialogue is not None envelope = Envelope( to=message.counterparty, sender=self.crypto.address, protocol_id=message.protocol_id, message=message, ) with patch.object( self.connection.channel, "_request_text", make_async(self.search_empty_response), ): await self.connection.send(envelope) expected_envelope = await asyncio.wait_for(self.connection.receive(), timeout=1) assert expected_envelope message = expected_envelope.message assert message.performative == OefSearchMessage.Performative.OEF_ERROR message = copy.deepcopy(expected_envelope.message) message.is_incoming = True # TODO: fix message.counterparty = SOEFConnection.connection_id.latest # TODO; fix receiving_dialogue = self.oef_search_dialogues.update(message) assert sending_dialogue == receiving_dialogue
async def _unregister_service( self, oef_search_msg: OefSearchMessage, dialogue: OefSearchDialogue, ) -> None: """ Unregister a service agent. :param oef_search_msg: the incoming message. :param dialogue: the dialogue. :return: None """ service_description = oef_search_msg.service_description address = oef_search_msg.sender async with self._lock: if address not in self.services: msg = OefSearchMessage( performative=OefSearchMessage.Performative.OEF_ERROR, target=oef_search_msg.message_id, message_id=oef_search_msg.message_id + 1, oef_error_operation=OefSearchMessage.OefErrorOperation.UNREGISTER_SERVICE, dialogue_reference=dialogue.dialogue_label.dialogue_reference, ) msg.counterparty = oef_search_msg.sender assert dialogue.update(msg) envelope = Envelope( to=msg.counterparty, sender=msg.sender, protocol_id=msg.protocol_id, message=msg, ) await self._send(envelope) else: self.services[address].remove(service_description) if len(self.services[address]) == 0: self.services.pop(address)
def _register_service(self) -> None: """ Register to the OEF Service Directory. In particular, register - as a seller, listing the goods supplied, or - as a buyer, listing the goods demanded, or - as both. :return: None """ strategy = cast(Strategy, self.context.strategy) oef_search_dialogues = cast(OefSearchDialogues, self.context.oef_search_dialogues) self.context.logger.debug("updating service directory as {}.".format( strategy.registering_as)) description = strategy.get_register_service_description() oef_msg = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, dialogue_reference=oef_search_dialogues. new_self_initiated_dialogue_reference(), service_description=description, ) oef_msg.counterparty = self.context.search_service_address oef_dialogue = oef_search_dialogues.update(oef_msg) assert oef_dialogue is not None, "OefSearchDialogue not created." self.context.outbox.put_message(message=oef_msg)
async def test_register_service(self): """Test register service.""" agent_location = Location(52.2057092, 2.1183431) service_instance = {"location": agent_location} service_description = Description( service_instance, data_model=models.AGENT_LOCATION_MODEL ) message = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, dialogue_reference=self.oef_search_dialogues.new_self_initiated_dialogue_reference(), service_description=service_description, ) message.counterparty = SOEFConnection.connection_id.latest sending_dialogue = self.oef_search_dialogues.update(message) assert sending_dialogue is not None envelope = Envelope( to=message.counterparty, sender=self.crypto.address, protocol_id=message.protocol_id, message=message, ) with patch.object( self.connection.channel, "_request_text", make_async(self.generic_success_response), ): await self.connection.send(envelope) with pytest.raises(asyncio.TimeoutError): # got no message back await asyncio.wait_for(self.connection.receive(), timeout=1) assert self.connection.channel.agent_location == agent_location
async def test_unregister_service(self): """Test unregister service.""" agent_location = Location(52.2057092, 2.1183431) service_instance = {"location": agent_location} service_description = Description( service_instance, data_model=models.AGENT_LOCATION_MODEL ) message = OefSearchMessage( performative=OefSearchMessage.Performative.UNREGISTER_SERVICE, dialogue_reference=self.oef_search_dialogues.new_self_initiated_dialogue_reference(), service_description=service_description, ) message.counterparty = SOEFConnection.connection_id.latest sending_dialogue = self.oef_search_dialogues.update(message) assert sending_dialogue is not None envelope = Envelope( to=message.counterparty, sender=self.crypto.address, protocol_id=message.protocol_id, message=message, ) with patch.object( self.connection.channel, "_request_text", make_async("<response><message>Goodbye!</message></response>"), ): await self.connection.send(envelope) assert self.connection.channel.unique_page_address is None
def test_unregister_service_serialization(): """Test the serialization for 'unregister_service' speech-act works.""" msg = OefSearchMessage( message_id=2, target=1, performative=OefSearchMessage.Performative.UNREGISTER_SERVICE, service_description=Description({ "foo1": 1, "bar1": 2 }), ) msg.to = "receiver" envelope = Envelope( to=msg.to, sender="sender", protocol_id=OefSearchMessage.protocol_id, message=msg, ) envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope.to == actual_envelope.to assert expected_envelope.sender == actual_envelope.sender assert expected_envelope.protocol_id == actual_envelope.protocol_id assert expected_envelope.message != actual_envelope.message actual_msg = OefSearchMessage.serializer.decode(actual_envelope.message) actual_msg.to = actual_envelope.to actual_msg.sender = actual_envelope.sender expected_msg = msg assert expected_msg == actual_msg
def test_on_oef_error(self): """Test the oef error.""" oef_connection = self.multiplexer1.connections[0] oef_channel = oef_connection.channel oef_channel.oef_msg_id += 1 dialogue_reference = ("1", "") query = Query( constraints=[Constraint("foo", ConstraintType("==", "bar"))], model=None, ) dialogues = oef_channel.oef_search_dialogues oef_search_msg = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=dialogue_reference, query=query, ) oef_search_msg.to = str(oef_connection.connection_id) oef_search_msg.sender = "agent" dialogue = dialogues.update(oef_search_msg) assert dialogue is not None oef_channel.oef_msg_id_to_dialogue[oef_channel.oef_msg_id] = dialogue oef_channel.on_oef_error( answer_id=oef_channel.oef_msg_id, operation=OEFErrorOperation.SEARCH_SERVICES, ) envelope = self.multiplexer1.get(block=True, timeout=5.0) dec_msg = envelope.message assert dec_msg.dialogue_reference[0] == dialogue_reference[0] assert (dec_msg.performative is OefSearchMessage.Performative.OEF_ERROR ), "It should be an error message"
def test_search_services_serialization(): """Test the serialization for 'search_services' speech-act works.""" msg = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=Query([Constraint("something", ConstraintType(">", 1))]), ) msg.to = "receiver" envelope = Envelope( to=msg.to, sender="sender", protocol_id=OefSearchMessage.protocol_id, message=msg, ) envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope.to == actual_envelope.to assert expected_envelope.sender == actual_envelope.sender assert expected_envelope.protocol_id == actual_envelope.protocol_id assert expected_envelope.message != actual_envelope.message actual_msg = OefSearchMessage.serializer.decode(actual_envelope.message) actual_msg.to = actual_envelope.to actual_msg.sender = actual_envelope.sender expected_msg = msg assert expected_msg == actual_msg
def on_oef_error( self, answer_id: int, operation: oef.messages.OEFErrorOperation ) -> None: """ On oef error event handler. :param answer_id: the answer id. :param operation: the error operation. :return: None """ assert self.in_queue is not None assert self.loop is not None try: operation = OefSearchMessage.OefErrorOperation(operation) except ValueError: operation = OefSearchMessage.OefErrorOperation.OTHER dialogue_reference = self.oef_msg_it_to_dialogue_reference[answer_id] msg = OefSearchMessage( performative=OefSearchMessage.Performative.OEF_ERROR, dialogue_reference=dialogue_reference, target=RESPONSE_TARGET, message_id=RESPONSE_MESSAGE_ID, oef_error_operation=operation, ) msg_bytes = OefSearchSerializer().encode(msg) envelope = Envelope( to=self.address, sender=DEFAULT_OEF, protocol_id=OefSearchMessage.protocol_id, message=msg_bytes, ) asyncio.run_coroutine_threadsafe( self.in_queue.put(envelope), self.loop ).result()
async def test_ping_command(self): """Test set service key.""" service_description = Description({}, data_model=models.PING_MODEL) message = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, dialogue_reference=self.oef_search_dialogues.new_self_initiated_dialogue_reference(), service_description=service_description, ) message.counterparty = SOEFConnection.connection_id.latest sending_dialogue = self.oef_search_dialogues.update(message) assert sending_dialogue is not None envelope = Envelope( to=message.counterparty, sender=self.crypto.address, protocol_id=message.protocol_id, message=message, ) with patch.object( self.connection.channel, "_request_text", make_async(self.generic_success_response), ): await self.connection.send(envelope) with pytest.raises(asyncio.TimeoutError): # got no message back await asyncio.wait_for(self.connection.receive(), timeout=1)
def decode(obj: bytes) -> Message: """ Decode bytes into a 'OefSearch' message. :param obj: the bytes object. :return: the 'OefSearch' message. """ message_pb = ProtobufMessage() oef_search_pb = oef_search_pb2.OefSearchMessage() message_pb.ParseFromString(obj) message_id = message_pb.dialogue_message.message_id dialogue_reference = ( message_pb.dialogue_message.dialogue_starter_reference, message_pb.dialogue_message.dialogue_responder_reference, ) target = message_pb.dialogue_message.target oef_search_pb.ParseFromString(message_pb.dialogue_message.content) performative = oef_search_pb.WhichOneof("performative") performative_id = OefSearchMessage.Performative(str(performative)) performative_content = dict() # type: Dict[str, Any] if performative_id == OefSearchMessage.Performative.REGISTER_SERVICE: pb2_service_description = oef_search_pb.register_service.service_description service_description = Description.decode(pb2_service_description) performative_content["service_description"] = service_description elif performative_id == OefSearchMessage.Performative.UNREGISTER_SERVICE: pb2_service_description = ( oef_search_pb.unregister_service.service_description) service_description = Description.decode(pb2_service_description) performative_content["service_description"] = service_description elif performative_id == OefSearchMessage.Performative.SEARCH_SERVICES: pb2_query = oef_search_pb.search_services.query query = Query.decode(pb2_query) performative_content["query"] = query elif performative_id == OefSearchMessage.Performative.SEARCH_RESULT: agents = oef_search_pb.search_result.agents agents_tuple = tuple(agents) performative_content["agents"] = agents_tuple pb2_agents_info = oef_search_pb.search_result.agents_info agents_info = AgentsInfo.decode(pb2_agents_info) performative_content["agents_info"] = agents_info elif performative_id == OefSearchMessage.Performative.SUCCESS: pb2_agents_info = oef_search_pb.success.agents_info agents_info = AgentsInfo.decode(pb2_agents_info) performative_content["agents_info"] = agents_info elif performative_id == OefSearchMessage.Performative.OEF_ERROR: pb2_oef_error_operation = oef_search_pb.oef_error.oef_error_operation oef_error_operation = OefErrorOperation.decode( pb2_oef_error_operation) performative_content["oef_error_operation"] = oef_error_operation else: raise ValueError( "Performative not valid: {}.".format(performative_id)) return OefSearchMessage(message_id=message_id, dialogue_reference=dialogue_reference, target=target, performative=performative, **performative_content)
def _register_service(self) -> None: """ Register to the OEF Service Directory. In particular, register - as a seller, listing the goods supplied, or - as a buyer, listing the goods demanded, or - as both. :return: None """ registration = cast(Registration, self.context.registration) strategy = cast(Strategy, self.context.strategy) if strategy.is_registering_as_seller: self.context.logger.debug( "[{}]: Updating service directory as seller with goods supplied." .format(self.context.agent_name)) goods_supplied_description = strategy.get_own_service_description( is_supply=True, is_search_description=False, ) registration.registered_goods_supplied_description = ( goods_supplied_description) oef_msg = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, dialogue_reference=(str(registration.get_next_id()), ""), service_description=goods_supplied_description, ) self.context.outbox.put_message( to=self.context.search_service_address, sender=self.context.agent_address, protocol_id=OefSearchMessage.protocol_id, message=OefSearchSerializer().encode(oef_msg), ) if strategy.is_registering_as_buyer: self.context.logger.debug( "[{}]: Updating service directory as buyer with goods demanded." .format(self.context.agent_name)) goods_demanded_description = strategy.get_own_service_description( is_supply=False, is_search_description=False, ) registration.registered_goods_demanded_description = ( goods_demanded_description) oef_msg = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, dialogue_reference=(str(registration.get_next_id()), ""), service_description=goods_demanded_description, ) self.context.outbox.put_message( to=self.context.search_service_address, sender=self.context.agent_address, protocol_id=OefSearchMessage.protocol_id, message=OefSearchSerializer().encode(oef_msg), )
async def test_send_oef_message(self, pytestconfig, caplog): """Test the send oef message.""" with warnings.catch_warnings(): warnings.simplefilter("ignore") oef_connection = _make_oef_connection( address=FETCHAI_ADDRESS_ONE, oef_addr="127.0.0.1", oef_port=10000, ) await oef_connection.connect() oef_search_dialogues = OefSearchDialogues(FETCHAI_ADDRESS_ONE) msg = OefSearchMessage( performative=OefSearchMessage.Performative.OEF_ERROR, dialogue_reference=oef_search_dialogues. new_self_initiated_dialogue_reference(), oef_error_operation=OefSearchMessage.OefErrorOperation. SEARCH_SERVICES, ) msg.to = str(oef_connection.connection_id) msg.sender = FETCHAI_ADDRESS_ONE envelope = Envelope( to=msg.to, sender=msg.sender, message=msg, ) with caplog.at_level(logging.DEBUG, "aea.packages.fetchai.connections.oef"): await oef_connection.send(envelope) assert "Could not create dialogue for message=" in caplog.text data_model = DataModel("foobar", attributes=[Attribute("foo", str, True)]) query = Query( constraints=[Constraint("foo", ConstraintType("==", "bar"))], model=data_model, ) msg, sending_dialogue = oef_search_dialogues.create( counterparty=str(oef_connection.connection_id), performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=query, ) envelope = Envelope( to=msg.to, sender=msg.sender, message=msg, ) await oef_connection.send(envelope) envelope = await oef_connection.receive() search_result = envelope.message response_dialogue = oef_search_dialogues.update(search_result) assert (search_result.performative == OefSearchMessage.Performative.SEARCH_RESULT) assert sending_dialogue == response_dialogue await asyncio.sleep(2.0) await oef_connection.disconnect()
def test_unregister_service(self): """Test that an unregister service request works correctly. Steps: 2. unregister the service 3. search for that service 4. assert that no result is found. """ self.request_id += 1 msg = OefSearchMessage( performative=OefSearchMessage.Performative.UNREGISTER_SERVICE, dialogue_reference=(str(self.request_id), ""), service_description=self.desc, ) msg_bytes = OefSearchSerializer().encode(msg) self.multiplexer.put( Envelope( to=DEFAULT_OEF, sender=self.crypto1.address, protocol_id=OefSearchMessage.protocol_id, message=msg_bytes, ) ) time.sleep(1.0) self.request_id += 1 search_request = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=(str(self.request_id), ""), query=Query( [Constraint("bar", ConstraintType("==", 1))], model=self.foo_datamodel, ), ) self.multiplexer.put( Envelope( to=DEFAULT_OEF, sender=self.crypto1.address, protocol_id=OefSearchMessage.protocol_id, message=OefSearchSerializer().encode(search_request), ) ) envelope = self.multiplexer.get(block=True, timeout=5.0) search_result = OefSearchSerializer().decode(envelope.message) assert ( search_result.performative == OefSearchMessage.Performative.SEARCH_RESULT ) assert search_result.dialogue_reference[0] == str(self.request_id) assert search_result.agents == ()
async def test_send_oef_message(self, pytestconfig): """Test the send oef message.""" oef_connection = _make_oef_connection( address=FETCHAI_ADDRESS_ONE, oef_addr="127.0.0.1", oef_port=10000, ) request_id = 1 oef_connection.loop = asyncio.get_event_loop() await oef_connection.connect() msg = OefSearchMessage( performative=OefSearchMessage.Performative.OEF_ERROR, dialogue_reference=(str(request_id), ""), oef_error_operation=OefSearchMessage.OefErrorOperation. SEARCH_SERVICES, ) msg_bytes = OefSearchSerializer().encode(msg) envelope = Envelope( to=DEFAULT_OEF, sender=FETCHAI_ADDRESS_ONE, protocol_id=OefSearchMessage.protocol_id, message=msg_bytes, ) with pytest.raises(ValueError): await oef_connection.send(envelope) data_model = DataModel("foobar", attributes=[Attribute("foo", str, True)]) query = Query( constraints=[Constraint("foo", ConstraintType("==", "bar"))], model=data_model, ) request_id += 1 msg = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=(str(request_id), ""), query=query, ) msg_bytes = OefSearchSerializer().encode(msg) envelope = Envelope( to=DEFAULT_OEF, sender=FETCHAI_ADDRESS_ONE, protocol_id=OefSearchMessage.protocol_id, message=msg_bytes, ) await oef_connection.send(envelope) search_result = await oef_connection.receive() assert isinstance(search_result, Envelope) await asyncio.sleep(2.0) await oef_connection.disconnect()
async def test_search(self): """Test search.""" agent_location = Location(52.2057092, 2.1183431) radius = 0.1 close_to_my_service = Constraint( "location", ConstraintType("distance", (agent_location, radius)) ) personality_filters = [ Constraint("genus", ConstraintType("==", "vehicle")), Constraint( "classification", ConstraintType("==", "mobility.railway.train") ), ] service_key_filters = [ Constraint("custom_key", ConstraintType("==", "custom_value")), ] closeness_query = Query( [close_to_my_service] + personality_filters + service_key_filters ) message = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=self.oef_search_dialogues.new_self_initiated_dialogue_reference(), query=closeness_query, ) message.counterparty = SOEFConnection.connection_id.latest sending_dialogue = self.oef_search_dialogues.update(message) assert sending_dialogue is not None envelope = Envelope( to=message.counterparty, sender=self.crypto.address, protocol_id=message.protocol_id, message=message, ) with patch.object( self.connection.channel, "_request_text", make_async(self.search_success_response), ): await self.connection.send(envelope) expected_envelope = await asyncio.wait_for(self.connection.receive(), timeout=1) assert expected_envelope message = expected_envelope.message assert len(message.agents) >= 1 message = copy.deepcopy(expected_envelope.message) message.is_incoming = True # TODO: fix message.counterparty = SOEFConnection.connection_id.latest # TODO; fix receiving_dialogue = self.oef_search_dialogues.update(message) assert sending_dialogue == receiving_dialogue
def test_register_service(self): """Test that a register service request works correctly.""" foo_datamodel = DataModel( "foo", [Attribute("bar", int, True, "A bar attribute.")] ) desc = Description({"bar": 1}, data_model=foo_datamodel) request_id = 1 msg = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, dialogue_reference=(str(request_id), ""), service_description=desc, ) msg_bytes = OefSearchSerializer().encode(msg) self.multiplexer.put( Envelope( to=DEFAULT_OEF, sender=self.crypto1.address, protocol_id=OefSearchMessage.protocol_id, message=msg_bytes, ) ) time.sleep(0.5) request_id += 1 search_request = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, dialogue_reference=(str(request_id), ""), query=Query( [Constraint("bar", ConstraintType("==", 1))], model=foo_datamodel ), ) self.multiplexer.put( Envelope( to=DEFAULT_OEF, sender=self.crypto1.address, protocol_id=OefSearchMessage.protocol_id, message=OefSearchSerializer().encode(search_request), ) ) envelope = self.multiplexer.get(block=True, timeout=5.0) search_result = OefSearchSerializer().decode(envelope.message) assert ( search_result.performative == OefSearchMessage.Performative.SEARCH_RESULT ) assert search_result.dialogue_reference[0] == str(request_id) if search_result.agents != [self.crypto1.address]: logger.warning( "search_result.agents != [self.crypto1.address] FAILED in test_oef/test_communication.py" )
def test_agent_info(): """Test the agent_info custom type.""" agents_info = OefSearchMessage.AgentsInfo( { "agent_address_1": {"key_1": b"value_1", "key_2": b"value_2"}, "agent_address_2": {"key_3": b"value_3", "key_4": b"value_4"}, } ) assert agents_info.get_info_for_agent("agent_address_1") == { "key_1": b"value_1", "key_2": b"value_2", } with pytest.raises(ValueError, match="body must not be None"): OefSearchMessage.AgentsInfo(None)
def _register_tac(self, parameters) -> None: """ Register on the OEF as a TAC controller agent. :return: None. """ self._oef_msg_id += 1 desc = Description( {"version": parameters.version_id}, data_model=CONTROLLER_DATAMODEL, ) self.context.logger.info( "[{}]: Registering TAC data model".format(self.context.agent_name) ) oef_msg = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, dialogue_reference=(str(self._oef_msg_id), ""), service_description=desc, ) self.context.outbox.put_message( to=self.context.search_service_address, sender=self.context.agent_address, protocol_id=OefSearchMessage.protocol_id, message=OefSearchSerializer().encode(oef_msg), ) self._registered_desc = desc self.context.logger.info( "[{}]: TAC open for registration until: {}".format( self.context.agent_name, parameters.registration_end_time ) )
def on_search_result(self, search_id: int, agents: List[Address]) -> None: """ On accept event handler. :param search_id: the search id. :param agents: the list of agents. :return: None """ assert self.in_queue is not None assert self.loop is not None dialogue_reference = self.oef_msg_it_to_dialogue_reference[search_id] msg = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_RESULT, dialogue_reference=dialogue_reference, target=RESPONSE_TARGET, message_id=RESPONSE_MESSAGE_ID, agents=tuple(agents), ) msg_bytes = OefSearchSerializer().encode(msg) envelope = Envelope( to=self.address, sender=DEFAULT_OEF, protocol_id=OefSearchMessage.protocol_id, message=msg_bytes, ) asyncio.run_coroutine_threadsafe( self.in_queue.put(envelope), self.loop ).result()