def test_find_import_order(): """Test find import order works on cycle dependency.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") _old_load = ComponentConfiguration.load def _new_load(*args, **kwargs): skill_config = _old_load(*args, **kwargs) skill_config.skills = [Mock()] return skill_config with patch.object(ComponentConfiguration, "load", _new_load): with pytest.raises( AEAException, match=r"Cannot load skills, there is a cyclic dependency."): builder._find_import_order( [ ComponentId(ComponentType.SKILL, PublicId("dummy_author", "dummy", "0.1.0")), ], Path(os.path.join(CUR_PATH, "data", "dummy_aea")), True, )
def make_aea(self, name: str = "my_aea", components: List[Component] = None) -> AEA: """ Create AEA from name and already loaded components. :param name: name of the agent :param components: list of components to add to agent :return: AEA """ components = components or [] builder = AEABuilder() builder.set_name(self.name) # See https://github.com/fetchai/agents-aea/issues/1237 builder._private_key_paths[ FetchAICrypto.identifier] = None # type: ignore for component in components: builder.add_component_instance(component) aea = builder.build() return aea
def test_start_stop_and_start_stop_again(): """Tests AEA can be started/stopped twice.""" 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_skill(Path(CUR_PATH, "data", "dummy_skill")) agent = builder.build() with run_in_thread(agent.start, timeout=20): wait_for_condition(lambda: agent.is_running, timeout=10) behaviour = agent.resources.get_behaviour(DUMMY_SKILL_PUBLIC_ID, "dummy") time.sleep(1) wait_for_condition(lambda: behaviour.nb_act_called > 0, timeout=5) agent.stop() wait_for_condition(lambda: agent.is_stopped, timeout=10) behaviour.nb_act_called = 0 time.sleep(2) assert behaviour.nb_act_called == 0 with run_in_thread(agent.start, timeout=20): wait_for_condition(lambda: agent.is_running, timeout=10) time.sleep(1) wait_for_condition(lambda: behaviour.nb_act_called > 0, timeout=5) agent.stop() wait_for_condition(lambda: agent.is_stopped, timeout=10)
def test_no_handlers_registered(): """Test no handlers are registered for message processing.""" agent_name = "MyAgent" builder = AEABuilder() private_key_path = os.path.join(CUR_PATH, "data", DEFAULT_PRIVATE_KEY_FILE) builder.set_name(agent_name) builder.add_private_key(DEFAULT_LEDGER, private_key_path) # local_connection_id = PublicId.from_str("fetchai/stub:0.4.0") # builder.set_default_connection(local_connection_id) aea = builder.build() with patch.object(aea._get_error_handler().context._logger, "warning") as mock_logger: msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) msg.counterparty = aea.identity.address envelope = Envelope( to=aea.identity.address, sender=aea.identity.address, protocol_id=DefaultMessage.protocol_id, message=msg, ) with patch.object(aea.filter, "get_active_handlers", return_value=[]): aea._handle(envelope) mock_logger.assert_any_call( f"Cannot handle envelope: no active handler registered for the protocol_id='{DefaultMessage.protocol_id}'." )
def test_storage_access_from_behaviour(): """Test storage access from behaviour component.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key(DEFAULT_LEDGER) skill_context = SkillContext() behaviour = TBehaviour(name="behaviour", skill_context=skill_context) test_skill = Skill( SkillConfig(name="test_skill", author="fetchai"), skill_context=skill_context, handlers={}, behaviours={"behaviour": behaviour}, ) builder.add_component_instance(test_skill) builder.set_storage_uri("sqlite://:memory:") aea = builder.build() skill_context.set_agent_context(aea.context) aea.runtime._threaded = True aea.runtime.start() try: wait_for_condition(lambda: aea.is_running, timeout=10) wait_for_condition(lambda: behaviour.counter > 0, timeout=10) col = skill_context.storage.get_sync_collection(behaviour.COL_NAME) assert col.get(behaviour.OBJ_ID) == behaviour.OBJ_BODY finally: aea.runtime.stop() aea.runtime.wait_completed(sync=True, timeout=10)
def setup(self) -> None: """Set test cae instance.""" agent_name = "MyAgent" builder = AEABuilder() builder.set_name(agent_name) builder.add_private_key(DEFAULT_LEDGER, COSMOS_PRIVATE_KEY_PATH) self.handler_called = 0 def handler_func(*args, **kwargs): self.handler_called += 1 skill_context = SkillContext() handler_cls = make_handler_cls_from_funcion(handler_func) behaviour_cls = make_behaviour_cls_from_funcion(handler_func) self.handler = handler_cls(name="handler1", skill_context=skill_context) self.behaviour = behaviour_cls(name="behaviour1", skill_context=skill_context) test_skill = Skill( SkillConfig(name="test_skill", author="fetchai"), skill_context=skill_context, handlers={"handler": self.handler}, behaviours={"behaviour": self.behaviour}, ) skill_context._skill = test_skill # weird hack builder.add_component_instance(test_skill) self.aea = builder.build() self.aea_tool = AeaTool(self.aea)
def setup_class(cls): """Set up the test.""" dummy_skill_path = os.path.join(CUR_PATH, "data", "dummy_skill") protocol_path = os.path.join( ROOT_DIR, "packages", "fetchai", "protocols", "oef_search" ) contract_path = os.path.join( ROOT_DIR, "packages", "fetchai", "contracts", "erc1155" ) connection_path = os.path.join( ROOT_DIR, "packages", "fetchai", "connections", "soef" ) builder = AEABuilder() builder.set_name("aea1") builder.add_private_key("fetchai") builder.add_protocol(protocol_path) builder.add_contract(contract_path) builder.add_connection(connection_path) builder.add_skill(dummy_skill_path) cls.aea1 = builder.build() builder.set_name("aea2") cls.aea2 = builder.build()
def test_multiple_builds_with_component_instance(): """Test multiple calls to the 'build()' method when adding component instances.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") a_protocol = Protocol( ProtocolConfig("a_protocol", "author", "0.1.0"), DefaultMessage ) builder.add_component_instance(a_protocol) # the first call works aea_1 = builder.build() assert isinstance(aea_1, AEA) # the second call fails with pytest.raises(ValueError, match="Cannot build.*"): builder.build() # after reset, it works builder.reset() builder.set_name("aea_1") builder.add_private_key("fetchai") builder.add_component_instance(a_protocol) aea_2 = builder.build() assert isinstance(aea_2, AEA)
def test_can_remove_not_exists_component(): """Test fail on remove component not registered.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") protocol = ProtocolConfig("a_protocol", "author", "0.1.0") with pytest.raises(ValueError): builder._check_can_remove(protocol.component_id)
def test_find_component_failed(): """Test fail on compomnent not found.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") a_protocol = Protocol(ProtocolConfig("a_protocol", "author", "0.1.0"), DefaultMessage) with pytest.raises(ValueError, match=r"Package .* not found"): builder._find_component_directory_from_component_id( Path("/some_dir"), a_protocol.component_id)
def test_react(): """Tests income messages.""" with LocalNode() as node: agent_name = "MyAgent" private_key_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") builder = AEABuilder() builder.set_name(agent_name) builder.add_private_key(FETCHAI, private_key_path) builder.add_protocol( Path(ROOT_DIR, "packages", "fetchai", "protocols", "oef_search")) builder.add_connection( Path(ROOT_DIR, "packages", "fetchai", "connections", "local")) builder.set_default_connection( PublicId.from_str("fetchai/local:0.1.0")) builder.add_skill(Path(CUR_PATH, "data", "dummy_skill")) agent = builder.build( connection_ids=[PublicId.from_str("fetchai/local:0.1.0")]) # This is a temporary workaround to feed the local node to the OEF Local connection # TODO remove it. list(agent._connections)[0]._local_node = node msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) msg.counterparty = agent.identity.address message_bytes = DefaultSerializer().encode(msg) envelope = Envelope( to=agent.identity.address, sender=agent.identity.address, protocol_id=DefaultMessage.protocol_id, message=message_bytes, ) with run_in_thread(agent.start, timeout=20, on_exit=agent.stop): wait_for_condition( lambda: agent._main_loop and agent._main_loop.is_running, timeout=10) agent.outbox.put(envelope) default_protocol_public_id = DefaultMessage.protocol_id dummy_skill_public_id = DUMMY_SKILL_PUBLIC_ID handler = agent.resources.get_handler(default_protocol_public_id, dummy_skill_public_id) assert handler is not None, "Handler is not set." wait_for_condition( lambda: msg in handler.handled_messages, timeout=10, error_msg="The message is not inside the handled_messages.", ) agent.stop()
def setup(self): """Set up case.""" 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_skill(Path(CUR_PATH, "data", "dummy_skill")) self.agent = builder.build() self.runtime = self.RUNTIME(self.agent, threaded=True)
def test_remove_contract(): """Test add/remove contract.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") contract = Contract.from_dir(contract_path) num_deps = len(builder._package_dependency_manager.all_dependencies) builder.add_component_instance(contract) assert len(builder._package_dependency_manager.all_dependencies) == num_deps + 1 builder.remove_contract(contract.public_id) assert len(builder._package_dependency_manager.all_dependencies) == num_deps
def test_process_connection_ids_not_specified(): """Test process connection fails on no connection specified.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") with pytest.raises( ValueError, match=r"Connection ids .* not declared in the configuration file." ): builder._process_connection_ids( [ConnectionConfig("conn", "author", "0.1.0").public_id])
def test_load_abstract_component(): """Test abstract component loading.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") skill = Skill.from_dir(dummy_skill_path, Mock(agent_name="name")) skill.configuration.is_abstract = True builder.add_component_instance(skill) builder._load_and_add_components( ComponentType.SKILL, Resources(), "aea_1", agent_context=Mock(agent_name="name") )
def test_remove_skill(): """Test add/remove skill.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") skill = Skill.from_dir(dummy_skill_path, Mock(agent_name="name")) num_deps = len(builder._package_dependency_manager.all_dependencies) builder.add_component_instance(skill) assert len(builder._package_dependency_manager.all_dependencies) == num_deps + 1 builder.remove_skill(skill.public_id) assert len(builder._package_dependency_manager.all_dependencies) == num_deps
def test_react(): """Tests income messages.""" 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")) agent = 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 = agent.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 = agent.identity.address msg.sender = agent.identity.address envelope = Envelope( to=msg.to, sender=msg.sender, protocol_id=msg.protocol_id, message=msg, ) with run_in_thread(agent.start, timeout=20, on_exit=agent.stop): wait_for_condition(lambda: agent.is_running, timeout=20) agent.outbox.put(envelope) default_protocol_public_id = DefaultMessage.protocol_id dummy_skill_public_id = DUMMY_SKILL_PUBLIC_ID handler = agent.resources.get_handler(default_protocol_public_id, dummy_skill_public_id) assert handler is not None, "Handler is not set." wait_for_condition( lambda: len(handler.handled_messages) > 0, timeout=20, error_msg="The message is not inside the handled_messages.", )
def test_react(): """Tests income messages.""" with LocalNode() as node: agent_name = "MyAgent" private_key_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") builder = AEABuilder() builder.set_name(agent_name) builder.add_private_key(FETCHAI, private_key_path) builder.add_connection( Path(ROOT_DIR, "packages", "fetchai", "connections", "local")) builder.add_skill(Path(CUR_PATH, "data", "dummy_skill")) agent = builder.build( connection_ids=[PublicId.from_str("fetchai/local:0.1.0")]) # This is a temporary workaround to feed the local node to the OEF Local connection # TODO remove it. list(agent._connections)[0]._local_node = node msg = DefaultMessage( dialogue_reference=("", ""), message_id=1, target=0, performative=DefaultMessage.Performative.BYTES, content=b"hello", ) msg.counterparty = agent.identity.address message_bytes = DefaultSerializer().encode(msg) envelope = Envelope( to=agent.identity.address, sender=agent.identity.address, protocol_id=DefaultMessage.protocol_id, message=message_bytes, ) t = Thread(target=agent.start) try: t.start() time.sleep(1.0) agent.outbox.put(envelope) time.sleep(2.0) default_protocol_public_id = DefaultMessage.protocol_id dummy_skill_public_id = DUMMY_SKILL_PUBLIC_ID handler = agent.resources.get_handler(default_protocol_public_id, dummy_skill_public_id) assert handler is not None, "Handler is not set." assert (msg in handler.handled_messages ), "The message is not inside the handled_messages." except Exception: raise finally: agent.stop() t.join()
def test_remove_connection(): """Test add/remove connection.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") num_deps = len(builder._package_dependency_manager.all_dependencies) conn = _make_dummy_connection() builder.add_component_instance(conn) assert len(builder._package_dependency_manager.all_dependencies) == num_deps + 1 builder.remove_connection(conn.public_id) assert len(builder._package_dependency_manager.all_dependencies) == num_deps
def run(): # Create a private key _create_fetchai_private_key() # 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(FETCHAI, FETCHAI_PRIVATE_KEY_FILE) builder.add_ledger_api_config(FETCHAI, {"network": "testnet"}) # Add the echo skill (assuming it is present in the local directory 'packages') builder.add_skill("./packages/fetchai/skills/echo") # 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 = ( "my_aea,other_agent,fetchai/default:0.1.0,\x08\x01*\x07\n\x05hello," ) with open(INPUT_FILE, "w") as f: f.write(message_text) print("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, "r") as f: print("output message: " + f.readline()) finally: # Shut down the AEA my_aea.stop() t.join() t = None
def test_remove_protocol(): """Test add/remove protocol.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") a_protocol = Protocol( ProtocolConfig("a_protocol", "author", "0.1.0"), DefaultMessage ) num_deps = len(builder._package_dependency_manager.all_dependencies) builder.add_component_instance(a_protocol) assert len(builder._package_dependency_manager.all_dependencies) == num_deps + 1 builder.remove_protocol(a_protocol.public_id) assert len(builder._package_dependency_manager.all_dependencies) == num_deps
def test_start_stop(): """Tests the act function of the AEA.""" 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_skill(Path(CUR_PATH, "data", "dummy_skill")) agent = builder.build() with run_in_thread(agent.start, timeout=20): wait_for_condition(lambda: agent.is_running, timeout=20) agent.stop()
def test_start_stop(): """Tests the act function of the AEA.""" agent_name = "MyAgent" private_key_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") builder = AEABuilder() builder.set_name(agent_name) builder.add_private_key(FETCHAI, private_key_path) builder.add_skill(Path(CUR_PATH, "data", "dummy_skill")) agent = builder.build() with run_in_thread(agent.start, timeout=20): wait_for_condition( lambda: agent._main_loop and agent._main_loop.is_running, timeout=10) agent.stop()
def test_process_connection_ids_bad_default_connection(): """Test fail on incorrect default connections.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") connection = _make_dummy_connection() builder.add_component_instance(connection) with pytest.raises( ValueError, match= r"Default connection not a dependency. Please add it and retry.", ): builder.set_default_connection( ConnectionConfig("conn", "author", "0.1.0").public_id) builder._process_connection_ids([connection.public_id])
def test_private_keys(): """Test add/remove private keys.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") builder.add_private_key("fetchai", is_connection=True) assert builder._connection_private_key_paths assert builder._private_key_paths builder.remove_private_key("fetchai") builder.remove_private_key("fetchai", is_connection=True) assert not builder._connection_private_key_paths assert not builder._private_key_paths
def test__build_identity_from_wallet(): """Test AEABuilder._build_identity_from_wallet.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key("fetchai") wallet = Mock() wallet.addresses = {} with pytest.raises(ValueError): builder._build_identity_from_wallet(wallet) wallet.addresses = {builder._default_ledger: "addr1"} builder._build_identity_from_wallet(wallet) wallet.addresses = {builder._default_ledger: "addr1", "fetchai": "addr2"} builder._build_identity_from_wallet(wallet)
def test_storage_access_from_handler(): """Test storage access from handler component.""" builder = AEABuilder() builder.set_name("aea_1") builder.add_private_key(DEFAULT_LEDGER) skill_context = SkillContext() handler = THandler(name="behaviour", skill_context=skill_context) test_skill = Skill( SkillConfig(name="test_skill", author="fetchai"), skill_context=skill_context, handlers={"handler": handler}, behaviours={}, ) builder.add_component_instance(test_skill) builder.set_storage_uri("sqlite://:memory:") aea = builder.build() skill_context.set_agent_context(aea.context) aea.runtime._threaded = True aea.runtime.start() 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 envelope = Envelope(to=msg.to, sender=msg.sender, message=msg,) try: wait_for_condition(lambda: aea.is_running, timeout=10) aea.runtime.multiplexer.in_queue.put(envelope) wait_for_condition(lambda: handler.counter > 0, timeout=10) col = skill_context.storage.get_sync_collection(handler.COL_NAME) assert col.get(handler.OBJ_ID) == handler.OBJ_BODY finally: aea.runtime.stop() aea.runtime.wait_completed(sync=True, timeout=10)
def test_initialise_aea(): """Tests the initialisation of the AEA.""" private_key_path = os.path.join(CUR_PATH, "data", "fet_private_key.txt") builder = AEABuilder() builder.set_name("my_name").add_private_key(FETCHAI, private_key_path) my_AEA = builder.build() assert my_AEA.context == my_AEA._context, "Cannot access the Agent's Context" assert (not my_AEA.context.connection_status.is_connected ), "AEA should not be connected." my_AEA.setup() assert my_AEA.resources is not None, "Resources must not be None after setup" my_AEA.resources = Resources(str(Path(CUR_PATH, "aea"))) assert my_AEA.resources is not None, "Resources must not be None after set" assert (my_AEA.context.shared_state is not None), "Shared state must not be None after set" assert my_AEA.context.task_manager is not None assert my_AEA.context.identity is not None, "Identity must not be None after set." my_AEA.stop()
def test_act(): """Tests the act function of the AEA.""" 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_skill(Path(CUR_PATH, "data", "dummy_skill")) agent = builder.build() with run_in_thread(agent.start, timeout=20): wait_for_condition(lambda: agent.is_running, timeout=20) behaviour = agent.resources.get_behaviour(DUMMY_SKILL_PUBLIC_ID, "dummy") time.sleep(1) wait_for_condition(lambda: behaviour.nb_act_called > 0, timeout=20) agent.stop()
def test_default_timeout_for_agent(): """Tests agents loop sleep timeout set by AEABuilder.DEFAULT_AGENT_LOOP_TIMEOUT.""" 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) aea = builder.build() assert aea._timeout == builder.DEFAULT_AGENT_LOOP_TIMEOUT builder = AEABuilder() builder.set_name(agent_name) builder.add_private_key(DEFAULT_LEDGER, private_key_path) builder.set_timeout(100) aea = builder.build() assert aea._timeout == 100