def setup(self): """Set up.""" self.crypto = make_crypto(DEFAULT_LEDGER) self.crypto2 = make_crypto(DEFAULT_LEDGER) identity = Identity("", address=self.crypto.address) self.oef_search_dialogues = OefSearchDialogues(self.crypto.address) self.data_dir = tempfile.mkdtemp() # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, restricted_to_protocols={ OefSearchMessage.protocol_specification_id }, connection_id=SOEFConnection.connection_id, ) self.connection = SOEFConnection( configuration=configuration, data_dir=self.data_dir, identity=identity, ) self.connection2 = SOEFConnection( configuration=configuration, data_dir=self.data_dir, identity=Identity("", address=self.crypto2.address), ) self.loop = asyncio.get_event_loop() self.loop.run_until_complete(self.connection.connect()) self.loop.run_until_complete(self.connection2.connect()) self.connection.channel.unique_page_address = "some_addr"
def setup(self): """Set up.""" self.crypto = make_crypto(DEFAULT_LEDGER) self.crypto2 = make_crypto(DEFAULT_LEDGER) identity = Identity("", address=self.crypto.address) self.oef_search_dialogues = OefSearchDialogues(self.crypto.address) # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, ) self.connection = SOEFConnection( configuration=configuration, identity=identity, ) self.connection.channel.unique_page_address = "some addr" self.connection2 = SOEFConnection( configuration=configuration, identity=Identity("", address=self.crypto2.address), ) self.loop = asyncio.get_event_loop() self.loop.run_until_complete(self.connection.connect()) self.loop.run_until_complete(self.connection2.connect())
def make_multiplexer_and_dialogues( ) -> Tuple[Multiplexer, OefSearchDialogues, Crypto, SOEFConnection]: """Return multplexer, dialogues and crypto instances.""" crypto = make_crypto(DEFAULT_LEDGER) identity = Identity("", address=crypto.address) oef_search_dialogues = OefSearchDialogues(crypto.address) # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, restricted_to_protocols={ OefSearchMessage.protocol_specification_id, OefSearchMessage.protocol_id, }, connection_id=SOEFConnection.connection_id, ) soef_connection = SOEFConnection( configuration=configuration, data_dir=MagicMock(), identity=identity, ) multiplexer = Multiplexer([soef_connection]) return multiplexer, oef_search_dialogues, crypto, soef_connection
def setup(self): """Set up.""" self.crypto = make_crypto(DEFAULT_LEDGER) self.crypto2 = make_crypto(DEFAULT_LEDGER) self.data_dir = tempfile.mkdtemp() identity = Identity("", address=self.crypto.address) self.oef_search_dialogues = OefSearchDialogues(self.crypto.address) # create the connection and multiplexer objects self.token_storage_path = "test.storage" configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, token_storage_path=self.token_storage_path, restricted_to_protocols={ OefSearchMessage.protocol_specification_id }, connection_id=SOEFConnection.connection_id, ) self.connection = SOEFConnection( configuration=configuration, data_dir=self.data_dir, identity=identity, )
def test_chain_identifier_ok(self): """Test set valid chain id.""" chain_identifier = "fetchai_cosmos" identity = Identity("", "") configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, chain_identifier=chain_identifier, ) connection = SOEFConnection(configuration=configuration, identity=identity,) assert connection.channel.chain_identifier == chain_identifier
def test_chain_identifier_fail(self): """Test fail on invalid chain id.""" chain_identifier = "test" identity = Identity("", "") configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, chain_identifier=chain_identifier, ) with pytest.raises(ValueError, match="Unsupported chain_identifier"): SOEFConnection( configuration=configuration, identity=identity, )
def test_chain_identifier_fail(self): """Test fail on invalid chain id.""" chain_identifier = "test" identity = Identity("", "") configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, restricted_to_protocols={ OefSearchMessage.protocol_specification_id }, connection_id=SOEFConnection.connection_id, chain_identifier=chain_identifier, ) with pytest.raises(ValueError, match="Unsupported chain_identifier"): SOEFConnection( configuration=configuration, data_dir=MagicMock(), identity=identity, )
def test_chain_identifier_ok(self): """Test set valid chain id.""" chain_identifier = "fetchai_cosmos" identity = Identity("", "") configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="s-oef.fetch.ai", soef_port=443, restricted_to_protocols={ OefSearchMessage.protocol_specification_id }, connection_id=SOEFConnection.connection_id, chain_identifier=chain_identifier, ) connection = SOEFConnection( configuration=configuration, data_dir=MagicMock(), identity=identity, ) assert connection.channel.chain_identifier == chain_identifier
def test_soef(): """Perform tests over real network.""" # First run OEF in a separate terminal: python scripts/oef/launch.py -c ./scripts/oef/launch_config.json crypto = FetchAICrypto() identity = Identity("", address=crypto.address) # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={ PublicId.from_str("fetchai/oef_search:0.3.0") }, connection_id=SOEFConnection.connection_id, ) soef_connection = SOEFConnection( configuration=configuration, identity=identity, ) multiplexer = Multiplexer([soef_connection]) try: # Set the multiplexer running in a different thread t = Thread(target=multiplexer.connect) t.start() wait_for_condition(lambda: multiplexer.is_connected, timeout=5) # register an agent with location 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, service_description=service_description, ) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=message.protocol_id, message=message, ) logger.info("Registering agent at location=({},{}) by agent={}".format( agent_location.latitude, agent_location.longitude, crypto.address, )) multiplexer.put(envelope) # register personality pieces service_instance = {"piece": "genus", "value": "service"} service_description = Description( service_instance, data_model=models.AGENT_PERSONALITY_MODEL) message = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, service_description=service_description, ) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=message.protocol_id, message=message, ) logger.info("Registering agent personality") multiplexer.put(envelope) # register service key service_instance = {"key": "test", "value": "test"} service_description = Description( service_instance, data_model=models.SET_SERVICE_KEY_MODEL) message = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, service_description=service_description, ) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=message.protocol_id, message=message, ) logger.info("Registering agent service key") multiplexer.put(envelope) # find agents near me radius = 0.1 close_to_my_service = Constraint( "location", ConstraintType("distance", (agent_location, radius))) closeness_query = Query([close_to_my_service], model=models.AGENT_LOCATION_MODEL) message = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=closeness_query, ) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=message.protocol_id, message=message, ) logger.info( "Searching for agents in radius={} of myself at location=({},{})". format( radius, agent_location.latitude, agent_location.longitude, )) multiplexer.put(envelope) wait_for_condition(lambda: not multiplexer.in_queue.empty(), timeout=20) # check for search results envelope = multiplexer.get() message = envelope.message assert len(message.agents) >= 0 # find agents near me with filter 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("test", ConstraintType("==", "test")), ] closeness_query = Query([close_to_my_service] + personality_filters + service_key_filters) message = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=closeness_query, ) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=message.protocol_id, message=message, ) logger.info( "Searching for agents in radius={} of myself at location=({},{}) with personality filters" .format( radius, agent_location.latitude, agent_location.longitude, )) time.sleep(3) # cause requests rate limit on server :( multiplexer.put(envelope) wait_for_condition(lambda: not multiplexer.in_queue.empty(), timeout=20) envelope = multiplexer.get() message = envelope.message assert len(message.agents) >= 0 # test ping command service_description = Description({}, data_model=models.PING_MODEL) message = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, service_description=service_description, ) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=message.protocol_id, message=message, ) logger.info("Registering agent service key") multiplexer.put(envelope) time.sleep(3) assert multiplexer.in_queue.empty() finally: # Shut down the multiplexer multiplexer.disconnect() t.join()
class TestSoef: """Set of unit tests for soef connection.""" search_success_response = """<?xml version="1.0" encoding="UTF-8"?><response><success>1</success><total>2</total><capped>0</capped><results><agent name="8c25cc02fd0c45f8895a3d4b3895376a" genus="" classification=""><identities><identity chain_identifier="fetchai">2ayYmgrCg76R1mzr2zWCmivzJG31hXtFVwQvR4XrXrD88Rc3sT</identity></identities><range_in_km>0</range_in_km></agent><agent name="9b61f3d2217b4d4f995e779db775fbdd" genus="" classification=""><identities><identity chain_identifier="fetchai">2DvN8QNXKE2tjnKgMKvBy9ZFyC6JaFYFrcLyWSS4A9RDWeTP4k</identity></identities><range_in_km>0</range_in_km></agent></results></response>""" search_empty_response = """<?xml version="1.0" encoding="UTF-8"?><response><success>1</success><total>0</total><capped>0</capped><results></results></response>""" search_fail_response = ( """<?xml version="1.0" encoding="UTF-8"?><notaresponse></notaresponse>""" ) generic_success_response = """<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>""" def setup(self): """Set up.""" self.crypto = make_crypto(DEFAULT_LEDGER) self.crypto2 = make_crypto(DEFAULT_LEDGER) identity = Identity("", address=self.crypto.address) self.oef_search_dialogues = OefSearchDialogues(self.crypto.address) # create the connection and multiplexer objects configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, ) self.connection = SOEFConnection( configuration=configuration, identity=identity, ) self.connection.channel.unique_page_address = "some addr" self.connection2 = SOEFConnection( configuration=configuration, identity=Identity("", address=self.crypto2.address), ) self.loop = asyncio.get_event_loop() self.loop.run_until_complete(self.connection.connect()) self.loop.run_until_complete(self.connection2.connect()) @pytest.mark.asyncio async def test_set_service_key(self): """Test set service key.""" service_instance = {"key": "test", "value": "test"} service_description = Description( service_instance, data_model=models.SET_SERVICE_KEY_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) @pytest.mark.asyncio async def test_remove_service_key(self): """Test remove service key.""" await self.test_set_service_key() service_instance = {"key": "test"} service_description = Description( service_instance, data_model=models.REMOVE_SERVICE_KEY_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(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 test_connected(self): """Test connected==True.""" assert self.connection.connection_status.is_connected @pytest.mark.asyncio async def test_disconnected(self): """Test disconnect.""" assert self.connection.connection_status.is_connected with patch.object( self.connection.channel, "_request_text", make_async("<response><message>Goodbye!</message></response>"), ): await self.connection.disconnect() assert not self.connection.connection_status.is_connected @pytest.mark.asyncio 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 @pytest.mark.asyncio async def test_bad_register_service(self): """Test register service fails on bad values provided.""" bad_location_model = DataModel( "not_location_agent", [ Attribute( "non_location", Location, True, "The location where the agent is." ) ], "A data model to describe location of an agent.", ) agent_location = Location(52.2057092, 2.1183431) service_instance = {"non_location": agent_location} service_description = Description( service_instance, data_model=bad_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, ) await self.connection.send(envelope) expected_envelope = await asyncio.wait_for(self.connection.receive(), timeout=1) assert expected_envelope assert ( expected_envelope.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 @pytest.mark.asyncio 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 @pytest.mark.asyncio async def test_register_personailty_pieces(self): """Test register service with personality pieces.""" service_instance = {"piece": "genus", "value": "service"} service_description = Description( service_instance, data_model=models.AGENT_PERSONALITY_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) @pytest.mark.asyncio async def test_send_excluded_protocol(self, caplog): """Test fail on unsupported protocol.""" envelope = Envelope( to="soef", sender=self.crypto.address, protocol_id=UNKNOWN_PROTOCOL_PUBLIC_ID, message=b"some msg", ) self.connection.channel.excluded_protocols = [UNKNOWN_PROTOCOL_PUBLIC_ID] with pytest.raises( ValueError, match=r"Cannot send message, invalid protocol:.*" ): await self.connection.send(envelope) @pytest.mark.asyncio async def test_bad_message(self, caplog): """Test fail on bad message.""" envelope = Envelope( to="soef", sender=self.crypto.address, protocol_id=UNKNOWN_PROTOCOL_PUBLIC_ID, message=b"some msg", ) with pytest.raises(ValueError): await self.connection.send(envelope) @pytest.mark.asyncio async def test_bad_performative(self, caplog): """Test fail on bad perfromative.""" 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="oef_error", service_description=service_description, ) envelope = Envelope( to="soef", sender=self.crypto.address, protocol_id=message.protocol_id, message=message, ) with pytest.raises(ValueError): await self.connection.send(envelope) @pytest.mark.asyncio 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 @pytest.mark.asyncio 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 @pytest.mark.asyncio async def test_find_around_me(self): """Test internal method find around me.""" 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 with patch.object( self.connection.channel, "_request_text", new_callable=MagicMock, side_effect=[ wrap_future(self.search_empty_response), wrap_future(self.search_success_response), wrap_future(self.search_fail_response), ], ): await self.connection.channel._find_around_me( message, sending_dialogue, 1, {} ) await self.connection.channel._find_around_me( message, sending_dialogue, 1, {} ) with pytest.raises(SOEFException, match=r"`find_around_me` error: .*"): await self.connection.channel._find_around_me( message, sending_dialogue, 1, {} ) @pytest.mark.asyncio async def test_register_agent(self): """Test internal method register agent.""" resp_text = '<?xml version="1.0" encoding="UTF-8"?><response></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): with pytest.raises( SOEFException, match="Agent registration error - page address or token not received", ): await self.connection.channel._register_agent() resp_text = '<?xml version="1.0" encoding="UTF-8"?><response><encrypted>0</encrypted><token>672DB3B67780F98984ABF1123BD11</token><page_address>oef_C95B21A4D5759C8FE7A6304B62B726AB8077BEE4BA191A7B92B388F9B1</page_address></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): with pytest.raises( SOEFException, match=r"`acknowledge` error: .*", ): await self.connection.channel._register_agent() resp_text1 = '<?xml version="1.0" encoding="UTF-8"?><response><encrypted>0</encrypted><token>672DB3B67780F98984ABF1123BD11</token><page_address>oef_C95B21A4D5759C8FE7A6304B62B726AB8077BEE4BA191A7B92B388F9B1</page_address></response>' resp_text2 = '<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>' resp_text3 = '<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>' with patch.object( self.connection.channel, "_request_text", new_callable=MagicMock, side_effect=[ wrap_future(resp_text1), wrap_future(resp_text2), wrap_future(resp_text3), ], ): await self.connection.channel._register_agent() assert self.connection.channel._ping_periodic_task is not None @pytest.mark.asyncio async def test_request(self): """Test internal method request_text.""" with patch("requests.request"): await self.connection.channel._request_text("get", "http://not-exists.com") @pytest.mark.asyncio async def test_set_location(self): """Test internal method set location.""" agent_location = Location(52.2057092, 2.1183431) resp_text = '<?xml version="1.0" encoding="UTF-8"?><response></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): with pytest.raises(SOEFException, match=r"`set_position` error: .*"): await self.connection.channel._set_location(agent_location) resp_text = '<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): await self.connection.channel._set_location(agent_location) @pytest.mark.asyncio async def test_set_personality_piece(self): """Test internal method set_personality_piece.""" resp_text = '<?xml version="1.0" encoding="UTF-8"?><response></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): with pytest.raises( SOEFException, match=r"`set_personality_piece` error: .*" ): await self.connection.channel._set_personality_piece(1, 1) resp_text = '<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): await self.connection.channel._set_personality_piece(1, 1) def teardown(self): """Clean up.""" try: with patch.object( self.connection.channel, "_request_text", make_async("<response><message>Goodbye!</message></response>"), ): self.loop.run_until_complete(self.connection.disconnect()) except Exception: # nosec pass @pytest.mark.asyncio async def test__set_value(self): """Test set pieces.""" resp_text = '<?xml version="1.0" encoding="UTF-8"?><response></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): with pytest.raises(SOEFException, match=r"`set_personality_piece` error:"): await self.connection.channel._set_personality_piece(1, 1) resp_text = '<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>' with patch.object( self.connection.channel, "_request_text", make_async(resp_text) ): await self.connection.channel._set_personality_piece(1, 1) def test_chain_identifier_fail(self): """Test fail on invalid chain id.""" chain_identifier = "test" identity = Identity("", "") configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, chain_identifier=chain_identifier, ) with pytest.raises(ValueError, match="Unsupported chain_identifier"): SOEFConnection( configuration=configuration, identity=identity, ) def test_chain_identifier_ok(self): """Test set valid chain id.""" chain_identifier = "fetchai_cosmos" identity = Identity("", "") configuration = ConnectionConfig( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, chain_identifier=chain_identifier, ) connection = SOEFConnection(configuration=configuration, identity=identity,) assert connection.channel.chain_identifier == chain_identifier @pytest.mark.asyncio 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) @pytest.mark.asyncio async def test_periodic_ping_task_is_set(self): """Test periodic ping task is set on agent register.""" resp_text1 = '<?xml version="1.0" encoding="UTF-8"?><response><encrypted>0</encrypted><token>672DB3B67780F98984ABF1123BD11</token><page_address>oef_C95B21A4D5759C8FE7A6304B62B726AB8077BEE4BA191A7B92B388F9B1</page_address></response>' resp_text2 = '<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>' resp_text3 = '<?xml version="1.0" encoding="UTF-8"?><response><success>1</success></response>' self.connection.channel.PING_PERIOD = 0.1 with patch.object( self.connection.channel, "_request_text", new_callable=MagicMock, side_effect=[ wrap_future(resp_text1), wrap_future(resp_text2), wrap_future(resp_text3), ], ): with patch.object(self.connection.channel, "_ping_command",) as mocked_ping: await self.connection.channel._register_agent() assert self.connection.channel._ping_periodic_task is not None await asyncio.sleep(0.3) assert mocked_ping.call_count > 1
def test_soef(): # First run OEF in a separate terminal: python scripts/oef/launch.py -c ./scripts/oef/launch_config.json crypto = FetchAICrypto() # create the connection and multiplexer objects soef_connection = SOEFConnection( api_key="TwiCIriSl0mLahw17pyqoA", soef_addr="soef.fetch.ai", soef_port=9002, address=crypto.address, ) multiplexer = Multiplexer([soef_connection]) try: # Set the multiplexer running in a different thread t = Thread(target=multiplexer.connect) t.start() time.sleep(3.0) # register a service with location attr_service_name = Attribute("service_name", str, True, "The name of the service.") attr_location = Attribute( "location", Location, True, "The location where the service is provided.") service_location_model = DataModel( "location_service", [attr_service_name, attr_location], "A data model to describe location of a service.", ) service_name = "train" service_location = Location(52.2057092, 2.1183431) service_instance = { "service_name": service_name, "location": service_location } service_description = Description(service_instance, data_model=service_location_model) message = OefSearchMessage( performative=OefSearchMessage.Performative.REGISTER_SERVICE, service_description=service_description, ) message_b = OefSearchSerializer().encode(message) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=ProtocolId.from_str("fetchai/oef_search:0.1.0"), message=message_b, ) logger.info( "Registering service={} at location=({},{}) by agent={}".format( service_name, service_location.latitude, service_location.longitude, crypto.address, )) multiplexer.put(envelope) # find agents near the previously registered service radius = 0.1 matches_my_service_name = Constraint( "service_name", ConstraintType("==", service_name)) close_to_my_service = Constraint( "location", ConstraintType("distance", (service_location, radius))) closeness_query = Query([matches_my_service_name, close_to_my_service], model=service_location_model) message = OefSearchMessage( performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=closeness_query, ) message_b = OefSearchSerializer().encode(message) envelope = Envelope( to="soef", sender=crypto.address, protocol_id=ProtocolId.from_str("fetchai/oef_search:0.1.0"), message=message_b, ) logger.info( "Searching for agents in radius={} of service={} at location=({},{})" .format( radius, service_name, service_location.latitude, service_location.longitude, )) multiplexer.put(envelope) time.sleep(4.0) # check for search results envelope = multiplexer.get() message = OefSearchSerializer().decode(envelope.message) assert len(message.agents) >= 0 finally: # Shut down the multiplexer multiplexer.disconnect() t.join()
def run(): # Create a private key create_private_key(CosmosCrypto.identifier) # Set up the wallet, identity and (empty) resources wallet = Wallet( private_key_paths={CosmosCrypto.identifier: COSMOS_PRIVATE_KEY_FILE}, connection_private_key_paths={CosmosCrypto.identifier: COSMOS_PRIVATE_KEY_FILE}, ) identity = Identity("my_aea", address=wallet.addresses.get(CosmosCrypto.identifier)) resources = Resources() # specify the default routing for some protocols default_routing = { PublicId.from_str("fetchai/ledger_api:0.1.0"): LedgerConnection.connection_id, PublicId.from_str("fetchai/oef_search:0.3.0"): SOEFConnection.connection_id, } default_connection = SOEFConnection.connection_id # create the AEA my_aea = AEA( identity, wallet, resources, default_connection=default_connection, default_routing=default_routing, ) # Add the default protocol (which is part of the AEA distribution) default_protocol = Protocol.from_dir(os.path.join(AEA_DIR, "protocols", "default")) resources.add_protocol(default_protocol) # Add the signing protocol (which is part of the AEA distribution) signing_protocol = Protocol.from_dir(os.path.join(AEA_DIR, "protocols", "signing")) resources.add_protocol(signing_protocol) # Add the ledger_api protocol ledger_api_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "ledger_api",) ) resources.add_protocol(ledger_api_protocol) # Add the oef_search protocol oef_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "oef_search",) ) resources.add_protocol(oef_protocol) # Add the fipa protocol fipa_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "fipa",) ) resources.add_protocol(fipa_protocol) # Add the LedgerAPI connection configuration = ConnectionConfig(connection_id=LedgerConnection.connection_id) ledger_api_connection = LedgerConnection( configuration=configuration, identity=identity ) resources.add_connection(ledger_api_connection) # Add the P2P connection configuration = ConnectionConfig( connection_id=P2PLibp2pConnection.connection_id, delegate_uri="127.0.0.1:11001", entry_peers=[ENTRY_PEER_ADDRESS], local_uri="127.0.0.1:9001", log_file="libp2p_node.log", public_uri="127.0.0.1:9001", ) p2p_connection = P2PLibp2pConnection( configuration=configuration, identity=identity, crypto_store=wallet.connection_cryptos, ) resources.add_connection(p2p_connection) # Add the SOEF connection configuration = ConnectionConfig( api_key=API_KEY, soef_addr=SOEF_ADDR, soef_port=SOEF_PORT, restricted_to_protocols={PublicId.from_str("fetchai/oef_search:0.3.0")}, connection_id=SOEFConnection.connection_id, delegate_uri="127.0.0.1:11001", entry_peers=[ENTRY_PEER_ADDRESS], local_uri="127.0.0.1:9001", log_file="libp2p_node.log", public_uri="127.0.0.1:9001", ) soef_connection = SOEFConnection(configuration=configuration, identity=identity) resources.add_connection(soef_connection) # Add the error and weather_client skills error_skill = Skill.from_dir( os.path.join(AEA_DIR, "skills", "error"), agent_context=my_aea.context ) weather_skill = Skill.from_dir( os.path.join(ROOT_DIR, "packages", "fetchai", "skills", "weather_client"), agent_context=my_aea.context, ) strategy = cast(Strategy, weather_skill.models.get("strategy")) strategy._is_ledger_tx = False for skill in [error_skill, weather_skill]: resources.add_skill(skill) # Run the AEA try: logger.info("STARTING AEA NOW!") my_aea.start() except KeyboardInterrupt: logger.info("STOPPING AEA NOW!") my_aea.stop()
def run(): """Run demo.""" # Create a private key create_private_key(FetchAICrypto.identifier, FETCHAI_PRIVATE_KEY_FILE) create_private_key(FetchAICrypto.identifier, FETCHAI_PRIVATE_KEY_FILE_CONNECTION) # Set up the wallet, identity and (empty) resources wallet = Wallet( private_key_paths={FetchAICrypto.identifier: FETCHAI_PRIVATE_KEY_FILE}, connection_private_key_paths={ FetchAICrypto.identifier: FETCHAI_PRIVATE_KEY_FILE_CONNECTION }, ) identity = Identity( "my_aea", address=wallet.addresses.get(FetchAICrypto.identifier) ) resources = Resources() data_dir = os.getcwd() # specify the default routing for some protocols default_routing = { LedgerApiMessage.protocol_id: LedgerConnection.connection_id, OefSearchMessage.protocol_id: SOEFConnection.connection_id, } default_connection = P2PLibp2pConnection.connection_id state_update_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "state_update") ) resources.add_protocol(state_update_protocol) # Add the default protocol (which is part of the AEA distribution) default_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "default") ) resources.add_protocol(default_protocol) # Add the signing protocol (which is part of the AEA distribution) signing_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "signing") ) resources.add_protocol(signing_protocol) # Add the ledger_api protocol ledger_api_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "ledger_api",) ) resources.add_protocol(ledger_api_protocol) # Add the oef_search protocol oef_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "oef_search",) ) resources.add_protocol(oef_protocol) # Add the fipa protocol fipa_protocol = Protocol.from_dir( os.path.join(os.getcwd(), "packages", "fetchai", "protocols", "fipa",) ) resources.add_protocol(fipa_protocol) # Add the LedgerAPI connection configuration = ConnectionConfig(connection_id=LedgerConnection.connection_id) ledger_api_connection = LedgerConnection( configuration=configuration, data_dir=data_dir, identity=identity ) resources.add_connection(ledger_api_connection) # Add the P2P connection cert_path = ".certs/conn_cert.txt" cert_request = CertRequest( identifier="acn", ledger_id=FetchAICrypto.identifier, not_after="2022-01-01", not_before="2021-01-01", public_key="fetchai", save_path=cert_path, ) public_key = wallet.connection_cryptos.public_keys.get(FetchAICrypto.identifier) message = cert_request.get_message(public_key) make_certificate( FetchAICrypto.identifier, FETCHAI_PRIVATE_KEY_FILE, message, cert_path ) configuration = ConnectionConfig( connection_id=P2PLibp2pConnection.connection_id, delegate_uri="127.0.0.1:11001", entry_peers=[ENTRY_PEER_ADDRESS], local_uri="127.0.0.1:9001", log_file="libp2p_node.log", public_uri="127.0.0.1:9001", build_directory=os.getcwd(), build_entrypoint="check_dependencies.py", cert_requests=[cert_request], ) configuration.directory = os.path.dirname( packages.fetchai.connections.p2p_libp2p.connection.__file__ ) AEABuilder.run_build_for_component_configuration(configuration) p2p_connection = P2PLibp2pConnection( configuration=configuration, data_dir=data_dir, identity=identity, crypto_store=wallet.connection_cryptos, ) resources.add_connection(p2p_connection) # Add the SOEF connection configuration = ConnectionConfig( api_key=API_KEY, soef_addr=SOEF_ADDR, soef_port=SOEF_PORT, restricted_to_protocols={OefSearchMessage.protocol_id}, connection_id=SOEFConnection.connection_id, ) soef_connection = SOEFConnection( configuration=configuration, data_dir=data_dir, identity=identity ) resources.add_connection(soef_connection) # create the AEA my_aea = AEA( identity, wallet, resources, data_dir, default_connection=default_connection, default_routing=default_routing, ) # Add the error and weather_client skills error_skill = Skill.from_dir( os.path.join(ROOT_DIR, "packages", "fetchai", "skills", "error"), agent_context=my_aea.context, ) weather_skill = Skill.from_dir( os.path.join(ROOT_DIR, "packages", "fetchai", "skills", "weather_client"), agent_context=my_aea.context, ) strategy = cast(Strategy, weather_skill.models.get("strategy")) strategy._is_ledger_tx = False for skill in [error_skill, weather_skill]: resources.add_skill(skill) # Run the AEA try: logger.info("STARTING AEA NOW!") my_aea.start() except KeyboardInterrupt: logger.info("STOPPING AEA NOW!") my_aea.stop()