def run(): # Ensure the input and output files do not exist initially if os.path.isfile(INPUT_FILE): os.remove(INPUT_FILE) if os.path.isfile(OUTPUT_FILE): os.remove(OUTPUT_FILE) # create the connection and multiplexer objects configuration = ConnectionConfig( input_file=INPUT_FILE, output_file=OUTPUT_FILE, connection_id=StubConnection.connection_id, ) stub_connection = StubConnection(configuration=configuration, identity=Identity("some_agent", "some_address")) multiplexer = Multiplexer([stub_connection]) try: # Set the multiplexer running in a different thread t = Thread(target=multiplexer.connect) t.start() # Wait for everything to start up time.sleep(3) # Create a message inside an envelope and get the stub connection to pass it into the multiplexer message_text = ( "multiplexer,some_agent,fetchai/default:0.4.0,\x08\x01*\x07\n\x05hello," ) with open(INPUT_FILE, "w") as f: write_with_lock(f, message_text) # Wait for the envelope to get processed time.sleep(2) # get the envelope envelope = multiplexer.get() # type: Optional[Envelope] assert envelope is not None # Inspect its contents print( "Envelope received by Multiplexer: sender={}, to={}, protocol_id={}, message={}" .format(envelope.sender, envelope.to, envelope.protocol_id, envelope.message)) # Create a mirrored response envelope response_envelope = copy(envelope) response_envelope.to = envelope.sender response_envelope.sender = envelope.to # Send the envelope back multiplexer.put(response_envelope) # Read the output envelope generated by the multiplexer with open(OUTPUT_FILE, "r") as f: print("Envelope received from Multiplexer: " + f.readline()) finally: # Shut down the multiplexer multiplexer.disconnect() t.join()
def test_send_message_no_supported_protocol(): """Test the case when we send an envelope with a specific connection that does not support the protocol.""" with LocalNode() as node: identity_1 = Identity("", address="address_1") public_id = PublicId.from_str("fetchai/my_private_protocol:0.1.0") connection_1 = _make_local_connection( identity_1.address, node, restricted_to_protocols={public_id}, excluded_protocols={public_id}, ) multiplexer = Multiplexer([connection_1]) multiplexer.connect() with mock.patch.object(aea.mail.base.logger, "warning") as mock_logger_warning: protocol_id = UNKNOWN_PROTOCOL_PUBLIC_ID envelope = Envelope( to=identity_1.address, sender=identity_1.address, protocol_id=protocol_id, message=b"some bytes", ) multiplexer.put(envelope) time.sleep(0.5) mock_logger_warning.assert_called_with( "Connection {} cannot handle protocol {}. Cannot send the envelope.".format( connection_1.connection_id, protocol_id ) ) multiplexer.disconnect()
def test_communication_direct(self): """Test communication direct (i.e. both clients registered to same peer).""" for i in range(len(PUBLIC_DHT_DELEGATE_URIS)): uri = PUBLIC_DHT_DELEGATE_URIS[i] peer_public_key = PUBLIC_DHT_PUBLIC_KEYS[i] multiplexers = [] try: temp_dir_1 = os.path.join(self.t, f"dir_{i}_1") os.mkdir(temp_dir_1) connection1 = _make_libp2p_client_connection( peer_public_key=peer_public_key, uri=uri, data_dir=temp_dir_1 ) multiplexer1 = Multiplexer([connection1]) multiplexer1.connect() multiplexers.append(multiplexer1) temp_dir_2 = os.path.join(self.t, f"dir_{i}_2") os.mkdir(temp_dir_2) connection2 = _make_libp2p_client_connection( peer_public_key=peer_public_key, uri=uri, data_dir=temp_dir_2 ) multiplexer2 = Multiplexer([connection2]) multiplexer2.connect() multiplexers.append(multiplexer2) addr_1 = connection1.address addr_2 = connection2.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope(to=addr_2, sender=addr_1, message=msg,) multiplexer1.put(envelope) delivered_envelope = multiplexer2.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert ( delivered_envelope.protocol_specification_id == envelope.protocol_specification_id ) assert delivered_envelope.message != envelope.message msg = DefaultMessage.serializer.decode(delivered_envelope.message) msg.to = delivered_envelope.to msg.sender = delivered_envelope.sender assert envelope.message == msg except Exception: raise finally: for mux in multiplexers: mux.disconnect()
def test_communication_direct(self): """Test communication direct.""" for maddr in PUBLIC_DHT_MADDRS: multiplexers = [] try: connection1 = _make_libp2p_connection(DEFAULT_PORT + 1, relay=False, entry_peers=[maddr]) multiplexer1 = Multiplexer([connection1]) self.log_files.append(connection1.node.log_file) multiplexer1.connect() multiplexers.append(multiplexer1) connection2 = _make_libp2p_connection(DEFAULT_PORT + 2, relay=False, entry_peers=[maddr]) multiplexer2 = Multiplexer([connection2]) self.log_files.append(connection2.node.log_file) multiplexer2.connect() multiplexers.append(multiplexer2) addr_1 = connection1.node.address addr_2 = connection2.node.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope( to=addr_2, sender=addr_1, protocol_id=DefaultMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) delivered_envelope = multiplexer2.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert delivered_envelope.protocol_id == envelope.protocol_id assert delivered_envelope.message != envelope.message msg = DefaultMessage.serializer.decode( delivered_envelope.message) msg.to = delivered_envelope.to msg.sender = delivered_envelope.sender assert envelope.message == msg except Exception: raise finally: for mux in multiplexers: mux.disconnect()
def test_communication_indirect(self): assert (len(PUBLIC_DHT_DELEGATE_URIS) > 1), "Test requires at least 2 public dht node" for i in range(len(PUBLIC_DHT_DELEGATE_URIS)): connection1 = _make_libp2p_client_connection( uri=PUBLIC_DHT_DELEGATE_URIS[i]) multiplexer1 = Multiplexer([connection1]) multiplexer1.connect() addr_1 = connection1.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) for j in range(len(PUBLIC_DHT_DELEGATE_URIS)): if j == i: continue connection2 = _make_libp2p_client_connection( uri=PUBLIC_DHT_DELEGATE_URIS[j]) multiplexer2 = Multiplexer([connection2]) multiplexer2.connect() addr_2 = connection2.address envelope = Envelope( to=addr_2, sender=addr_1, protocol_id=DefaultMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) delivered_envelope = multiplexer2.get(block=True, timeout=20) try: assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert delivered_envelope.protocol_id == envelope.protocol_id assert delivered_envelope.message != envelope.message msg = DefaultMessage.serializer.decode( delivered_envelope.message) assert envelope.message == msg except Exception: multiplexer1.disconnect() raise finally: multiplexer2.disconnect() multiplexer1.disconnect()
def test_send_message_no_supported_protocol(): """Test the case when we send an envelope with a specific connection that does not support the protocol.""" with LocalNode() as node: identity_1 = Identity("", address="address_1") connection_1 = _make_local_connection( identity_1.address, node, restricted_to_protocols={DefaultMessage.protocol_id}, excluded_protocols={FipaMessage.protocol_id}, ) multiplexer = Multiplexer( [connection_1], protocols=[DefaultMessage, FipaMessage, UnknownProtocolMock]) multiplexer.connect() with mock.patch.object(multiplexer.logger, "warning") as mock_logger_warning: envelope = Envelope( to=identity_1.address, sender=identity_1.address, protocol_specification_id=FipaMessage. protocol_specification_id, message=b"some bytes", ) multiplexer.put(envelope) time.sleep(0.5) mock_logger_warning.assert_called_with( "Connection {} does not support protocol {}. It is explicitly excluded." .format(connection_1.connection_id, FipaMessage.protocol_id)) with mock.patch.object(multiplexer.logger, "warning") as mock_logger_warning: envelope = Envelope( to=identity_1.address, sender=identity_1.address, protocol_specification_id=UnknownProtocolMock. protocol_specification_id, message=b"some bytes", ) multiplexer.put(envelope) time.sleep(0.5) mock_logger_warning.assert_called_with( "Connection {} does not support protocol {}. The connection is restricted to protocols in {}." .format( connection_1.connection_id, UnknownProtocolMock.protocol_id, connection_1.restricted_to_protocols, )) multiplexer.disconnect()
def test_communication_direct(self): for uri in PUBLIC_DHT_DELEGATE_URIS: connection1 = _make_libp2p_client_connection(uri=uri) multiplexer1 = Multiplexer([connection1]) multiplexer1.connect() connection2 = _make_libp2p_client_connection(uri=uri) multiplexer2 = Multiplexer([connection2]) multiplexer2.connect() addr_1 = connection1.address addr_2 = connection2.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope( to=addr_2, sender=addr_1, protocol_id=DefaultMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) delivered_envelope = multiplexer2.get(block=True, timeout=20) try: assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert delivered_envelope.protocol_id == envelope.protocol_id assert delivered_envelope.message != envelope.message msg = DefaultMessage.serializer.decode( delivered_envelope.message) assert envelope.message == msg except Exception: raise finally: multiplexer1.disconnect() multiplexer2.disconnect()
def test_send_envelope_error_is_logged_by_send_loop(): """Test that the AEAConnectionError in the '_send' method is logged by the '_send_loop'.""" connection = _make_dummy_connection() multiplexer = Multiplexer([connection]) multiplexer.connect() fake_connection_id = UNKNOWN_CONNECTION_PUBLIC_ID envelope = Envelope( to="", sender="", protocol_id=DefaultMessage.protocol_id, message=b"", context=EnvelopeContext(connection_id=fake_connection_id), ) with unittest.mock.patch.object(aea.mail.base.logger, "error") as mock_logger_error: multiplexer.put(envelope) time.sleep(0.1) mock_logger_error.assert_called_with( "No connection registered with id: {}.".format(fake_connection_id) ) multiplexer.disconnect()
class TestSimpleSearchResult: """Test that a simple search result return the expected result.""" def setup(self): """Set up the test.""" self.node = LocalNode() self.node.start() self.address_1 = "address" self.multiplexer = Multiplexer( [_make_local_connection( self.address_1, self.node, )]) self.multiplexer.connect() # register a service. self.dialogues = OefSearchDialogues(self.address_1) self.data_model = DataModel( "foobar", attributes=[ Attribute("foo", int, True), Attribute("bar", str, True) ], ) service_description = Description({ "foo": 1, "bar": "baz" }, data_model=self.data_model) register_service_request, self.sending_dialogue = self.dialogues.create( counterparty=str(OEFLocalConnection.connection_id), performative=OefSearchMessage.Performative.REGISTER_SERVICE, service_description=service_description, ) envelope = Envelope( to=register_service_request.to, sender=register_service_request.sender, message=register_service_request, ) self.multiplexer.put(envelope) @pytest.mark.flaky(reruns=MAX_FLAKY_RERUNS ) # TODO: check reasons!. quite unstable test def test_not_empty_search_result(self): """Test that the search result contains one entry after a successful registration.""" # build and send the request search_services_request, sending_dialogue = self.dialogues.create( counterparty=str(OEFLocalConnection.connection_id), performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=Query(constraints=[], model=self.data_model), ) envelope = Envelope( to=search_services_request.to, sender=search_services_request.sender, 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_specification_id == OefSearchMessage.protocol_specification_id) search_result = cast(OefSearchMessage, response_envelope.message) response_dialogue = self.dialogues.update(search_result) assert response_dialogue == sending_dialogue assert search_result.performative == OefSearchMessage.Performative.SEARCH_RESULT assert search_result.agents == (self.address_1, ) def teardown(self): """Teardown the test.""" self.multiplexer.disconnect() self.node.stop()
class TestLibp2pConnectionRelayNodeRestartIncomingEnvelopes( BaseTestLibp2pRelay): """Test that connection will reliably receive envelopes after its relay node restarted""" @libp2p_log_on_failure def setup(self): """Set the test up""" super().setup() temp_dir_gen = os.path.join(self.t, "temp_dir_gen") os.mkdir(temp_dir_gen) self.genesis = _make_libp2p_connection(data_dir=temp_dir_gen, port=DEFAULT_PORT + 1, build_directory=self.t) self.multiplexer_genesis = Multiplexer([self.genesis], protocols=[DefaultMessage]) self.multiplexer_genesis.connect() self.log_files.append(self.genesis.node.log_file) self.multiplexers.append(self.multiplexer_genesis) genesis_peer = self.genesis.node.multiaddrs[0] with open("node_key", "wb") as f: make_crypto(DEFAULT_LEDGER).dump(f) self.relay_key_path = "node_key" temp_dir_rel = os.path.join(self.t, "temp_dir_rel") os.mkdir(temp_dir_rel) self.relay = _make_libp2p_connection( data_dir=temp_dir_rel, port=DEFAULT_PORT + 2, entry_peers=[genesis_peer], node_key_file=self.relay_key_path, build_directory=self.t, ) self.multiplexer_relay = Multiplexer([self.relay], protocols=[DefaultMessage]) self.multiplexer_relay.connect() self.log_files.append(self.relay.node.log_file) self.multiplexers.append(self.multiplexer_relay) relay_peer = self.relay.node.multiaddrs[0] temp_dir_1 = os.path.join(self.t, "temp_dir_1") os.mkdir(temp_dir_1) self.connection = _make_libp2p_connection( data_dir=temp_dir_1, port=DEFAULT_PORT + 3, relay=False, entry_peers=[relay_peer], build_directory=self.t, ) self.multiplexer = Multiplexer([self.connection], protocols=[DefaultMessage]) self.multiplexer.connect() self.log_files.append(self.connection.node.log_file) self.multiplexers.append(self.multiplexer) temp_dir_2 = os.path.join(self.t, "temp_dir_2") os.mkdir(temp_dir_2) self.connection2 = _make_libp2p_connection( data_dir=temp_dir_2, port=DEFAULT_PORT + 4, relay=False, entry_peers=[relay_peer], build_directory=self.t, ) self.multiplexer2 = Multiplexer([self.connection2], protocols=[DefaultMessage]) self.multiplexer2.connect() self.log_files.append(self.connection2.node.log_file) self.multiplexers.append(self.multiplexer2) def test_connection_is_established(self): """Test connection established.""" assert self.relay.is_connected is True assert self.connection.is_connected is True assert self.connection2.is_connected is True def test_envelope_routed_from_peer_after_relay_restart(self): """Test envelope routed from third peer after relay restart.""" addr_1 = self.genesis.address addr_2 = self.connection.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope( to=addr_2, sender=addr_1, protocol_specification_id=DefaultMessage.protocol_specification_id, message=DefaultSerializer().encode(msg), ) self.multiplexer_genesis.put(envelope) delivered_envelope = self.multiplexer.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert (delivered_envelope.protocol_specification_id == envelope.protocol_specification_id) assert delivered_envelope.message_bytes == envelope.message_bytes self.multiplexer_relay.disconnect() self.change_state_and_wait(self.multiplexer_relay, expected_is_connected=False) # currently, multiplexer cannot be restarted self.multiplexer_relay = Multiplexer([self.relay], protocols=[DefaultMessage]) self.multiplexer_relay.connect() self.change_state_and_wait(self.multiplexer_relay, expected_is_connected=True) self.multiplexers.append(self.multiplexer_relay) msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"helloAfterRestart", ) envelope = Envelope( to=addr_2, sender=addr_1, protocol_specification_id=DefaultMessage.protocol_specification_id, message=DefaultSerializer().encode(msg), ) self.multiplexer_genesis.put(envelope) delivered_envelope = self.multiplexer.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert (delivered_envelope.protocol_specification_id == envelope.protocol_specification_id) assert delivered_envelope.message_bytes == envelope.message_bytes def test_envelope_routed_from_client_after_relay_restart(self): """Test envelope routed from third relay client after relay restart.""" addr_1 = self.connection.address addr_2 = self.connection2.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope( to=addr_1, sender=addr_2, protocol_specification_id=DefaultMessage.protocol_specification_id, message=DefaultSerializer().encode(msg), ) self.multiplexer2.put(envelope) delivered_envelope = self.multiplexer.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert (delivered_envelope.protocol_specification_id == envelope.protocol_specification_id) assert delivered_envelope.message_bytes == envelope.message_bytes self.multiplexer_relay.disconnect() self.change_state_and_wait(self.multiplexer_relay, expected_is_connected=False) # currently, multiplexer cannot be restarted self.multiplexer_relay = Multiplexer([self.relay], protocols=[DefaultMessage]) self.multiplexer_relay.connect() self.change_state_and_wait(self.multiplexer_relay, expected_is_connected=True) self.multiplexers.append(self.multiplexer_relay) msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"helloAfterRestart", ) envelope = Envelope( to=addr_1, sender=addr_2, protocol_specification_id=DefaultMessage.protocol_specification_id, message=DefaultSerializer().encode(msg), ) time.sleep(5) self.multiplexer2.put(envelope) delivered_envelope = self.multiplexer.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert (delivered_envelope.protocol_specification_id == envelope.protocol_specification_id) assert delivered_envelope.message_bytes == envelope.message_bytes
class TestSearchServices: """Tests related to service search functionality.""" def setup(self): """Set the test up.""" self.connection = _make_oef_connection( FETCHAI_ADDRESS_ONE, oef_addr="127.0.0.1", oef_port=10000, ) self.multiplexer = Multiplexer([self.connection]) self.multiplexer.connect() self.oef_search_dialogues = OefSearchDialogues(FETCHAI_ADDRESS_ONE) def test_search_services_with_query_without_model(self): """Test that a search services request can be sent correctly. In this test, the query has no data model. """ search_query_empty_model = Query( [Constraint("foo", ConstraintType("==", "bar"))], model=None) oef_search_request, sending_dialogue = self.oef_search_dialogues.create( counterparty=str(self.connection.connection_id), performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=search_query_empty_model, ) self.multiplexer.put( Envelope( to=oef_search_request.to, sender=oef_search_request.sender, protocol_id=oef_search_request.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_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, sending_dialogue = self.oef_search_dialogues.create( counterparty=str(self.connection.connection_id), performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=search_query, ) self.multiplexer.put( Envelope( to=oef_search_request.to, sender=oef_search_request.sender, protocol_id=oef_search_request.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_search_services_with_distance_query(self): """Test that a search services request can be sent correctly. In this test, the query has a simple data model. """ tour_eiffel = Location(48.8581064, 2.29447) attribute = Attribute("latlon", Location, True) data_model = DataModel("geolocation", [attribute]) search_query = Query( [ Constraint(attribute.name, ConstraintType("distance", (tour_eiffel, 1.0))) ], model=data_model, ) oef_search_request, sending_dialogue = self.oef_search_dialogues.create( counterparty=str(self.connection.connection_id), performative=OefSearchMessage.Performative.SEARCH_SERVICES, query=search_query, ) self.multiplexer.put( Envelope( to=oef_search_request.to, sender=oef_search_request.sender, protocol_id=oef_search_request.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 teardown(self): """Teardowm the test.""" self.multiplexer.disconnect()
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()
def test_communication(): """Test that two multiplexer can communicate through the node.""" with LocalNode() as node: multiplexer1 = Multiplexer( [_make_local_connection("multiplexer1", node)]) multiplexer2 = Multiplexer( [_make_local_connection("multiplexer2", node)]) multiplexer1.connect() multiplexer2.connect() msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope( to="multiplexer2", sender="multiplexer1", protocol_id=DefaultMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) msg = FipaMessage( performative=FipaMessage.Performative.CFP, dialogue_reference=(str(0), ""), message_id=1, target=0, query=Query([Constraint("something", ConstraintType(">", 1))]), ) envelope = Envelope( to="multiplexer2", sender="multiplexer1", protocol_id=FipaMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) msg = FipaMessage( performative=FipaMessage.Performative.PROPOSE, dialogue_reference=(str(0), ""), message_id=2, target=1, proposal=Description({}), ) envelope = Envelope( to="multiplexer2", sender="multiplexer1", protocol_id=FipaMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) msg = FipaMessage( performative=FipaMessage.Performative.ACCEPT, dialogue_reference=(str(0), ""), message_id=1, target=0, ) envelope = Envelope( to="multiplexer2", sender="multiplexer1", protocol_id=FipaMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) msg = FipaMessage( performative=FipaMessage.Performative.DECLINE, dialogue_reference=(str(0), ""), message_id=1, target=0, ) envelope = Envelope( to="multiplexer2", sender="multiplexer1", protocol_id=FipaMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) envelope = multiplexer2.get(block=True, timeout=1.0) msg = envelope.message assert envelope.protocol_id == DefaultMessage.protocol_id assert msg.content == b"hello" envelope = multiplexer2.get(block=True, timeout=1.0) msg = envelope.message assert envelope.protocol_id == FipaMessage.protocol_id assert msg.performative == FipaMessage.Performative.CFP envelope = multiplexer2.get(block=True, timeout=1.0) msg = envelope.message assert envelope.protocol_id == FipaMessage.protocol_id assert msg.performative == FipaMessage.Performative.PROPOSE envelope = multiplexer2.get(block=True, timeout=1.0) msg = envelope.message assert envelope.protocol_id == FipaMessage.protocol_id assert msg.performative == FipaMessage.Performative.ACCEPT envelope = multiplexer2.get(block=True, timeout=1.0) msg = envelope.message assert envelope.protocol_id == FipaMessage.protocol_id assert msg.performative == FipaMessage.Performative.DECLINE multiplexer1.disconnect() multiplexer2.disconnect()
def test_communication_indirect(self): assert len( PUBLIC_DHT_MADDRS) > 1, "Test requires at least 2 public dht node" for i in range(len(PUBLIC_DHT_MADDRS)): connection1 = _make_libp2p_connection( DEFAULT_PORT + 1, relay=False, entry_peers=[PUBLIC_DHT_MADDRS[i]]) multiplexer1 = Multiplexer([connection1]) self.log_files.append(connection1.node.log_file) multiplexer1.connect() addr_1 = connection1.node.address for j in range(len(PUBLIC_DHT_MADDRS)): if j == i: continue connection2 = _make_libp2p_connection( DEFAULT_PORT + 2, relay=False, entry_peers=[PUBLIC_DHT_MADDRS[j]], ) multiplexer2 = Multiplexer([connection2]) self.log_files.append(connection2.node.log_file) multiplexer2.connect() addr_2 = connection2.node.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope( to=addr_2, sender=addr_1, protocol_id=DefaultMessage.protocol_id, message=msg, ) multiplexer1.put(envelope) delivered_envelope = multiplexer2.get(block=True, timeout=20) try: assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert delivered_envelope.protocol_id == envelope.protocol_id assert delivered_envelope.message != envelope.message msg = DefaultMessage.serializer.decode( delivered_envelope.message) assert envelope.message == msg except Exception: multiplexer1.disconnect() raise finally: multiplexer2.disconnect() multiplexer1.disconnect()
class TestExceptionHandlingOnConnectionSend: """Test exception handling policy on connection.send.""" def setup(self): """Set up test case.""" self.connection = _make_dummy_connection() self.multiplexer = Multiplexer([self.connection], protocols=[DefaultProtocolMock]) self.multiplexer.connect() self.envelope = Envelope( to="", sender="", protocol_specification_id=DefaultMessage.protocol_specification_id, message=b"", context=EnvelopeContext( connection_id=self.connection.connection_id), ) self.exception = ValueError("expected") def teardown(self): """Tear down test case.""" self.multiplexer.disconnect() def test_log_policy(self): """Test just log exception.""" with patch.object(self.connection, "send", side_effect=self.exception): self.multiplexer._exception_policy = ExceptionPolicyEnum.just_log self.multiplexer.put(self.envelope) time.sleep(1) assert not self.multiplexer._send_loop_task.done() def test_propagate_policy(self): """Test propagate exception.""" assert self.multiplexer._exception_policy == ExceptionPolicyEnum.propagate with patch.object(self.connection, "send", side_effect=self.exception): self.multiplexer.put(self.envelope) time.sleep(1) wait_for_condition(lambda: self.multiplexer._send_loop_task.done(), timeout=5) assert self.multiplexer._send_loop_task.exception( ) == self.exception def test_stop_policy(self): """Test stop multiplexer on exception.""" with patch.object(self.connection, "send", side_effect=self.exception): self.multiplexer._exception_policy = ExceptionPolicyEnum.stop_and_exit self.multiplexer.put(self.envelope) time.sleep(1) wait_for_condition( lambda: self.multiplexer.connection_status.is_disconnected, timeout=5) def test_disconnect_order(self): """Test disconnect order: tasks first, disconnect_all next.""" parent = MagicMock() async def fn(): return with patch.object( self.multiplexer, "_stop_receive_send_loops", return_value=fn()) as stop_loops, patch.object( self.multiplexer, "_disconnect_all", return_value=fn()) as disconnect_all, patch.object( self.multiplexer, "_check_and_set_disconnected_state" ) as check_and_set_disconnected_state: parent.attach_mock(stop_loops, "stop_loops") parent.attach_mock(disconnect_all, "disconnect_all") parent.attach_mock(check_and_set_disconnected_state, "check_and_set_disconnected_state") self.multiplexer.disconnect() assert parent.mock_calls == [ call.stop_loops(), call.disconnect_all(), call.check_and_set_disconnected_state(), ]
class TestLibp2pConnectionAgentMobility(BaseTestLibp2pRelay): """Test that connection will correctly route envelope to destination that changed its peer""" @libp2p_log_on_failure def setup(self): """Set the test up""" super().setup() temp_dir_gen = os.path.join(self.t, "temp_dir_gen") os.mkdir(temp_dir_gen) self.genesis = _make_libp2p_connection(data_dir=temp_dir_gen, port=DEFAULT_PORT) self.multiplexer_genesis = Multiplexer([self.genesis], protocols=[DefaultMessage]) self.log_files.append(self.genesis.node.log_file) self.multiplexer_genesis.connect() self.multiplexers.append(self.multiplexer_genesis) genesis_peer = self.genesis.node.multiaddrs[0] temp_dir_1 = os.path.join(self.t, "temp_dir_1") os.mkdir(temp_dir_1) self.connection1 = _make_libp2p_connection(data_dir=temp_dir_1, port=DEFAULT_PORT + 1, entry_peers=[genesis_peer]) self.multiplexer1 = Multiplexer([self.connection1], protocols=[DefaultMessage]) self.log_files.append(self.connection1.node.log_file) self.multiplexer1.connect() self.multiplexers.append(self.multiplexer1) self.connection_key = make_crypto(DEFAULT_LEDGER) temp_dir_2 = os.path.join(self.t, "temp_dir_2") os.mkdir(temp_dir_2) self.connection2 = _make_libp2p_connection( data_dir=temp_dir_2, port=DEFAULT_PORT + 2, entry_peers=[genesis_peer], agent_key=self.connection_key, ) self.multiplexer2 = Multiplexer([self.connection2], protocols=[DefaultMessage]) self.log_files.append(self.connection2.node.log_file) self.multiplexer2.connect() self.multiplexers.append(self.multiplexer2) def test_connection_is_established(self): """Test connection established.""" assert self.connection1.is_connected is True assert self.connection2.is_connected is True def test_envelope_routed_after_peer_changed(self): """Test envelope routed after peer changed.""" addr_1 = self.connection1.address addr_2 = self.connection2.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope( to=addr_2, sender=addr_1, protocol_specification_id=DefaultMessage.protocol_specification_id, message=DefaultSerializer().encode(msg), ) self.multiplexer1.put(envelope) delivered_envelope = self.multiplexer2.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert (delivered_envelope.protocol_specification_id == envelope.protocol_specification_id) assert delivered_envelope.message_bytes == envelope.message_bytes self.multiplexer2.disconnect() self.change_state_and_wait(self.multiplexer2, expected_is_connected=False) # currently, multiplexer cannot be restarted self.multiplexer2 = Multiplexer([self.connection2], protocols=[DefaultMessage]) self.multiplexer2.connect() self.change_state_and_wait(self.multiplexer2, expected_is_connected=True) self.multiplexers.append(self.multiplexer2) msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"helloAfterChangingPeer", ) envelope = Envelope( to=addr_2, sender=addr_1, protocol_specification_id=msg.protocol_specification_id, message=msg.encode(), ) self.multiplexer1.put(envelope) delivered_envelope = self.multiplexer2.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert (delivered_envelope.protocol_specification_id == envelope.protocol_specification_id) assert delivered_envelope.message_bytes == envelope.message_bytes
def test_communication_indirect(self): """Test communication indirect.""" assert len(PUBLIC_DHT_MADDRS) > 1, "Test requires at least 2 public dht node" for i in range(len(PUBLIC_DHT_MADDRS)): multiplexers = [] try: temp_dir_1 = os.path.join(self.t, f"dir_{i}__") os.mkdir(temp_dir_1) connection1 = _make_libp2p_connection( port=DEFAULT_PORT + 1, relay=False, entry_peers=[PUBLIC_DHT_MADDRS[i]], data_dir=temp_dir_1, ) multiplexer1 = Multiplexer([connection1]) self.log_files.append(connection1.node.log_file) multiplexer1.connect() multiplexers.append(multiplexer1) addr_1 = connection1.node.address for j in range(len(PUBLIC_DHT_MADDRS)): if j == i: continue temp_dir_2 = os.path.join(self.t, f"dir_{i}_{j}") os.mkdir(temp_dir_2) connection2 = _make_libp2p_connection( port=DEFAULT_PORT + 2, relay=False, entry_peers=[PUBLIC_DHT_MADDRS[j]], data_dir=temp_dir_2, ) multiplexer2 = Multiplexer([connection2]) self.log_files.append(connection2.node.log_file) multiplexer2.connect() multiplexers.append(multiplexer2) addr_2 = connection2.node.address msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) envelope = Envelope(to=addr_2, sender=addr_1, message=msg,) multiplexer1.put(envelope) delivered_envelope = multiplexer2.get(block=True, timeout=20) assert delivered_envelope is not None assert delivered_envelope.to == envelope.to assert delivered_envelope.sender == envelope.sender assert ( delivered_envelope.protocol_specification_id == envelope.protocol_specification_id ) assert delivered_envelope.message != envelope.message msg = DefaultMessage.serializer.decode(delivered_envelope.message) msg.to = delivered_envelope.to msg.sender = delivered_envelope.sender assert envelope.message == msg multiplexer2.disconnect() del multiplexers[-1] except Exception: raise finally: for mux in multiplexers: mux.disconnect()