def test_initialize_aea_programmatically(): """Test that we can initialize an AEA programmatically.""" with LocalNode() as node: agent_name = "MyAgent" private_key_path = os.path.join(CUR_PATH, "data", DEFAULT_PRIVATE_KEY_FILE) builder = AEABuilder() builder.set_name(agent_name) builder.add_private_key(DEFAULT_LEDGER, private_key_path) builder.add_protocol( Path(ROOT_DIR, "packages", "fetchai", "protocols", "oef_search")) builder.add_connection( Path(ROOT_DIR, "packages", "fetchai", "connections", "local")) local_connection_id = OEFLocalConnection.connection_id builder.set_default_connection(local_connection_id) builder.add_skill(Path(CUR_PATH, "data", "dummy_skill")) aea = builder.build(connection_ids=[local_connection_id]) local_connection = aea.resources.get_connection(local_connection_id) local_connection._local_node = node expected_message = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) expected_message.to = aea.identity.address expected_message.sender = aea.identity.address envelope = Envelope( to=expected_message.to, sender=expected_message.sender, protocol_id=expected_message.protocol_id, message=expected_message, ) with run_in_thread(aea.start, timeout=5, on_exit=aea.stop): wait_for_condition(lambda: aea.is_running, timeout=10) aea.outbox.put(envelope) dummy_skill_id = DUMMY_SKILL_PUBLIC_ID dummy_behaviour_name = "dummy" dummy_behaviour = aea.resources.get_behaviour( dummy_skill_id, dummy_behaviour_name) wait_for_condition(lambda: dummy_behaviour is not None, timeout=10) wait_for_condition(lambda: dummy_behaviour.nb_act_called > 0, timeout=10) # TODO the previous code caused an error: # _pickle.PicklingError: Can't pickle <class 'tasks.DummyTask'>: import of module 'tasks' failed dummy_task = DummyTask() task_id = aea.enqueue_task(dummy_task) async_result = aea.get_task_result(task_id) expected_dummy_task = async_result.get(10.0) wait_for_condition( lambda: expected_dummy_task.nb_execute_called > 0, timeout=10) dummy_handler = aea.resources.get_handler( DefaultMessage.protocol_id, dummy_skill_id) dummy_handler_alt = aea.resources._handler_registry.fetch( (dummy_skill_id, "dummy")) wait_for_condition(lambda: dummy_handler == dummy_handler_alt, timeout=10) wait_for_condition(lambda: dummy_handler is not None, timeout=10) wait_for_condition( lambda: len(dummy_handler.handled_messages) == 1, timeout=10) wait_for_condition( lambda: dummy_handler.handled_messages[0] == expected_message, timeout=10, )
def run(): # Create a private key create_private_key(CosmosCrypto.identifier, COSMOS_PRIVATE_KEY_FILE) # 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) # Instantiate the builder and build the AEA # By default, the default protocol, error skill and stub connection are added builder = AEABuilder() builder.set_name("my_aea") builder.add_private_key(CosmosCrypto.identifier, COSMOS_PRIVATE_KEY_FILE) # Add the echo skill (assuming it is present in the local directory 'packages') builder.add_skill("./packages/fetchai/skills/echo") # create skill and handler manually from aea.protocols.base import Message from aea.protocols.default.message import DefaultMessage from aea.skills.base import Handler class DummyHandler(Handler): """Dummy handler to handle messages.""" SUPPORTED_PROTOCOL = DefaultMessage.protocol_id def setup(self) -> None: """Noop setup.""" def teardown(self) -> None: """Noop teardown.""" def handle(self, message: Message) -> None: """Handle incoming message.""" self.context.logger.info("You got a message: {}".format( str(message))) config = SkillConfig(name="test_skill", author="fetchai") skill = Skill(configuration=config) dummy_handler = DummyHandler(name="dummy_handler", skill_context=skill.skill_context) skill.handlers.update({dummy_handler.name: dummy_handler}) builder.add_component_instance(skill) # Create our AEA my_aea = builder.build() # Set the AEA running in a different thread try: t = Thread(target=my_aea.start) t.start() # Wait for everything to start up time.sleep(4) # Create a message inside an envelope and get the stub connection to pass it on to the echo skill message_text = b"my_aea,other_agent,fetchai/default:0.4.0,\x08\x01\x12\x011*\x07\n\x05hello," with open(INPUT_FILE, "wb") as f: write_with_lock(f, message_text) print(b"input message: " + message_text) # Wait for the envelope to get processed time.sleep(4) # Read the output envelope generated by the echo skill with open(OUTPUT_FILE, "rb") as f: print(b"output message: " + f.readline()) finally: # Shut down the AEA my_aea.stop() t.join() t = None
def test_handle(): """Tests handle method of an agent.""" with LocalNode() as node: agent_name = "MyAgent" private_key_path = os.path.join(CUR_PATH, "data", DEFAULT_PRIVATE_KEY_FILE) builder = AEABuilder() builder.set_name(agent_name) builder.add_private_key(DEFAULT_LEDGER, private_key_path) builder.add_protocol( Path(ROOT_DIR, "packages", "fetchai", "protocols", "oef_search")) builder.add_connection( Path(ROOT_DIR, "packages", "fetchai", "connections", "local")) local_connection_id = OEFLocalConnection.connection_id builder.set_default_connection(local_connection_id) builder.add_skill(Path(CUR_PATH, "data", "dummy_skill")) aea = builder.build(connection_ids=[local_connection_id]) # This is a temporary workaround to feed the local node to the OEF Local connection # TODO remove it. local_connection = aea.resources.get_connection(local_connection_id) local_connection._local_node = node msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) msg.to = aea.identity.address msg.sender = aea.identity.address encoded_msg = DefaultSerializer.encode(msg) envelope = Envelope( to=msg.to, sender=msg.sender, protocol_id=UNKNOWN_PROTOCOL_PUBLIC_ID, message=msg, ) with run_in_thread(aea.start, timeout=5): wait_for_condition(lambda: aea.is_running, timeout=10) dummy_skill = aea.resources.get_skill(DUMMY_SKILL_PUBLIC_ID) dummy_handler = dummy_skill.handlers["dummy"] aea.outbox.put(envelope) wait_for_condition( lambda: len(dummy_handler.handled_messages) == 1, timeout=1, ) # DECODING ERROR envelope = Envelope( to=aea.identity.address, sender=aea.identity.address, protocol_id=DefaultMessage.protocol_id, message=b"", ) # send envelope via localnode back to agent/bypass `outbox` put consistency checks aea.outbox._multiplexer.put(envelope) """ inbox twice cause first message is invalid. generates error message and it accepted """ wait_for_condition( lambda: len(dummy_handler.handled_messages) == 2, timeout=1, ) # UNSUPPORTED SKILL msg = FipaMessage( performative=FipaMessage.Performative.ACCEPT, message_id=1, dialogue_reference=(str(0), ""), target=0, ) msg.to = aea.identity.address msg.sender = aea.identity.address envelope = Envelope( to=msg.to, sender=msg.sender, protocol_id=msg.protocol_id, message=msg, ) # send envelope via localnode back to agent aea.outbox.put(envelope) wait_for_condition( lambda: len(dummy_handler.handled_messages) == 3, timeout=2, ) # DECODING OK envelope = Envelope( to=msg.to, sender=msg.sender, protocol_id=DefaultMessage.protocol_id, message=encoded_msg, ) # send envelope via localnode back to agent/bypass `outbox` put consistency checks aea.outbox._multiplexer.put(envelope) wait_for_condition( lambda: len(dummy_handler.handled_messages) == 4, timeout=1, ) aea.stop()
def test_generated_protocol_end_to_end(self): """Test that a generated protocol could be used in exchanging messages between two agents.""" builder_1 = AEABuilder() builder_1.set_name("my_aea_1") builder_1.add_private_key(FETCHAI, FETCHAI_PRIVATE_KEY_FILE) builder_1.set_default_ledger(FETCHAI) builder_1.add_component( ComponentType.PROTOCOL, Path(ROOT_DIR, "tests", "data", "generator", "t_protocol"), skip_consistency_check=True, ) builder_1.add_connection( Path(ROOT_DIR, "packages", "fetchai", "connections", "oef")) builder_2 = AEABuilder() builder_2.set_name("my_aea_2") builder_2.add_private_key(FETCHAI, FETCHAI_PRIVATE_KEY_FILE) builder_2.set_default_ledger(FETCHAI) builder_2.add_component( ComponentType.PROTOCOL, Path(ROOT_DIR, "tests", "data", "generator", "t_protocol"), skip_consistency_check=True, ) builder_2.add_connection( Path(ROOT_DIR, "packages", "fetchai", "connections", "oef")) # create AEAs aea_1 = builder_1.build( connection_ids=[PublicId.from_str("fetchai/oef:0.1.0")]) aea_2 = builder_2.build( connection_ids=[PublicId.from_str("fetchai/oef:0.1.0")]) # message 1 message = TProtocolMessage( message_id=1, dialogue_reference=(str(0), ""), target=0, performative=TProtocolMessage.Performative.PERFORMATIVE_PT, content_bytes=b"some bytes", content_int=42, content_float=42.7, content_bool=True, content_str="some string", ) encoded_message_in_bytes = TProtocolSerializer().encode(message) envelope = Envelope( to=aea_2.identity.address, sender=aea_1.identity.address, protocol_id=TProtocolMessage.protocol_id, message=encoded_message_in_bytes, ) # message 2 message_2 = TProtocolMessage( message_id=2, dialogue_reference=(str(0), ""), target=1, performative=TProtocolMessage.Performative.PERFORMATIVE_PT, content_bytes=b"some other bytes", content_int=43, content_float=43.7, content_bool=False, content_str="some other string", ) encoded_message_2_in_bytes = TProtocolSerializer().encode(message_2) # add handlers to AEA resources agent_1_handler = Agent1Handler(skill_context=SkillContext( aea_1.context), name="fake_skill") aea_1.resources._handler_registry.register( ( PublicId.from_str("fetchai/fake_skill:0.1.0"), TProtocolMessage.protocol_id, ), agent_1_handler, ) agent_2_handler = Agent2Handler( encoded_messsage=encoded_message_2_in_bytes, skill_context=SkillContext(aea_2.context), name="fake_skill", ) aea_2.resources._handler_registry.register( ( PublicId.from_str("fetchai/fake_skill:0.1.0"), TProtocolMessage.protocol_id, ), agent_2_handler, ) # Start threads t_1 = Thread(target=aea_1.start) t_2 = Thread(target=aea_2.start) try: t_1.start() t_2.start() time.sleep(1.0) aea_1.outbox.put(envelope) time.sleep(5.0) assert (agent_2_handler.handled_message.message_id == message.message_id ), "Message from Agent 1 to 2: message ids do not match" assert ( agent_2_handler.handled_message.dialogue_reference == message.dialogue_reference ), "Message from Agent 1 to 2: dialogue references do not match" assert ( agent_2_handler.handled_message.dialogue_reference[0] == message.dialogue_reference[0] ), "Message from Agent 1 to 2: dialogue reference[0]s do not match" assert ( agent_2_handler.handled_message.dialogue_reference[1] == message.dialogue_reference[1] ), "Message from Agent 1 to 2: dialogue reference[1]s do not match" assert (agent_2_handler.handled_message.target == message.target ), "Message from Agent 1 to 2: targets do not match" assert (agent_2_handler.handled_message.performative == message.performative ), "Message from Agent 1 to 2: performatives do not match" assert (agent_2_handler.handled_message.content_bytes == message.content_bytes ), "Message from Agent 1 to 2: content_bytes do not match" assert (agent_2_handler.handled_message.content_int == message.content_int ), "Message from Agent 1 to 2: content_int do not match" # floats do not seem to lose some precision when serialised then deserialised using protobuf # assert agent_2_handler.handled_message.content_float == message.content_float, "Message from Agent 1 to 2: content_float do not match" assert (agent_2_handler.handled_message.content_bool == message.content_bool ), "Message from Agent 1 to 2: content_bool do not match" assert (agent_2_handler.handled_message.content_str == message.content_str ), "Message from Agent 1 to 2: content_str do not match" assert ( agent_1_handler.handled_message.message_id == message_2.message_id ), "Message from Agent 1 to 2: dialogue references do not match" assert ( agent_1_handler.handled_message.dialogue_reference == message_2.dialogue_reference ), "Message from Agent 2 to 1: dialogue references do not match" assert ( agent_1_handler.handled_message.dialogue_reference[0] == message_2.dialogue_reference[0] ), "Message from Agent 2 to 1: dialogue reference[0]s do not match" assert ( agent_1_handler.handled_message.dialogue_reference[1] == message_2.dialogue_reference[1] ), "Message from Agent 2 to 1: dialogue reference[1]s do not match" assert (agent_1_handler.handled_message.target == message_2.target ), "Message from Agent 2 to 1: targets do not match" assert (agent_1_handler.handled_message.performative == message_2.performative ), "Message from Agent 2 to 1: performatives do not match" assert (agent_1_handler.handled_message.content_bytes == message_2.content_bytes ), "Message from Agent 2 to 1: content_bytes do not match" assert (agent_1_handler.handled_message.content_int == message_2.content_int ), "Message from Agent 2 to 1: content_int do not match" # floats do not seem to lose some precision when serialised then deserialised using protobuf # assert agent_1_handler.handled_message.content_float == message_2.content_float, "Message from Agent 2 to 1: content_float do not match" assert (agent_1_handler.handled_message.content_bool == message_2.content_bool ), "Message from Agent 2 to 1: content_bool do not match" assert (agent_1_handler.handled_message.content_str == message_2.content_str ), "Message from Agent 2 to 1: content_str do not match" time.sleep(2.0) finally: aea_1.stop() aea_2.stop() t_1.join() t_2.join()