def test_builder_applies_default_value_to_aea(self) -> None: """Test AEABuilder applies default value to AEA instance when option is not specified in config.""" configuration = self._make_configuration(NotSet) builder = AEABuilder() builder.set_from_configuration(configuration, aea_project_path=Path(".")) aea = builder.build() assert self._get_aea_value(aea) == self.AEA_DEFAULT_VALUE
def test_builder_applies_config_value_to_aea(self) -> None: """Test AEABuilder applies value to AEA instance when option is specified in config.""" for good_value in self.GOOD_VALUES: configuration = self._make_configuration(good_value) builder = AEABuilder() builder.set_from_configuration(configuration, aea_project_path=Path(ROOT_DIR)) aea = builder.build() assert self._get_aea_value(aea) == good_value
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 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_from_project(self): """Test builder set from project dir.""" self.expected_input_file = "custom_input_file" self.expected_output_file = "custom_output_file" self._add_stub_connection_config() with pytest.raises( AEAEnforceError, match=r"Component \(protocol, some_author/non_existing_package:0.1.0\) not declared in the agent configuration.", ): with cd(self._get_cwd()): AEABuilder.from_aea_project(Path(self._get_cwd()))
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_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 _get_builder( cls, agent_config: AgentConfig, aea_project_path: Union[Path, str], skip_consistency_check: bool = False, ) -> AEABuilder: """Get AEABuilder instance.""" builder = AEABuilder(with_default_packages=False, build_dir_root=str(aea_project_path)) builder.set_from_configuration(agent_config, Path(aea_project_path), skip_consistency_check) return builder
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_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 test_when_package_has_missing_dependency(): """Test the case when the builder tries to load the packages, but fails because of a missing dependency.""" builder = AEABuilder() expected_message = re.escape( "Package 'fetchai/oef:0.7.0' of type 'connection' cannot be added. " "Missing dependencies: ['(protocol, fetchai/oef_search:0.4.0)']") with pytest.raises(AEAException, match=expected_message): # connection "fetchai/oef:0.1.0" requires # "fetchai/oef_search:0.4.0" and "fetchai/fipa:0.5.0" protocols. builder.add_component( ComponentType.CONNECTION, Path(ROOT_DIR) / "packages" / "fetchai" / "connections" / "oef", )
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_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 test_when_package_has_missing_dependency(): """Test the case when the builder tries to load the packages, but fails because of a missing dependency.""" builder = AEABuilder() expected_message = re.escape( f"Package '{str(OEF_CONNECTION_PUBLIC_ID)}' of type 'connection' cannot be added. " f"Missing dependencies: ['(protocol, {str(OefSearchMessage.protocol_id)})']" ) with pytest.raises(AEAException, match=expected_message): # connection "fetchai/oef" requires # "fetchai/oef_search" and "fetchai/fipa" protocols. builder.add_component( ComponentType.CONNECTION, Path(ROOT_DIR) / "packages" / "fetchai" / "connections" / "oef", )
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_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 _launch_threads(click_context: click.Context, agents: List[Path]) -> int: """ Launch many agents, multithreaded. :param agents: the click context. :param agents: list of paths to agent projects. :return: exit status """ aeas = [] # type: List[AEA] for agent_directory in agents: with cd(agent_directory): aeas.append(AEABuilder.from_aea_project(".").build()) threads = [Thread(target=agent.start) for agent in aeas] for t in threads: t.start() try: while sum([t.is_alive() for t in threads]) != 0: # exit when all threads are not alive. # done to avoid block on joins for t in threads: t.join(0.1) except KeyboardInterrupt: logger.info("Keyboard interrupt detected.") finally: for idx, agent in enumerate(aeas): if not agent.liveness.is_stopped: agent.stop() threads[idx].join() logger.info("Agent {} has been stopped.".format(agent.name)) return 0
def setup(self): """Set up the test.""" self.builder = AEABuilder.from_aea_project(Path(self._get_cwd())) self.component_id = "component_id" # add project-wide build entrypoint self.script_path = Path("script.py") self.builder._build_entrypoint = str(self.script_path)
def test_install_dependency(self): """Test dependencies installed.""" package_name = "async_generator" dependency = Dependency(package_name, "==1.10") sys.modules.pop(package_name, None) run_install_subprocess( [sys.executable, "-m", "pip", "uninstall", package_name, "-y"] ) try: import_module(package_name) raise Exception("should not be raised") except ModuleNotFoundError: pass builder = AEABuilder.from_aea_project(Path(self._get_cwd())) with patch( "aea.aea_builder._DependenciesManager.pypi_dependencies", {"package_name": dependency}, ): builder.install_pypi_dependencies() import_module(package_name) sys.modules.pop(package_name) run_install_subprocess( [sys.executable, "-m", "pip", "uninstall", package_name, "-y"] ) try: import_module(package_name) raise Exception("should not be raised") except ModuleNotFoundError: pass
def test_check_dependencies_correct(self): """Test dependencies properly listed.""" self.run_cli_command( "add", "--local", "connection", "fetchai/http_client", cwd=self._get_cwd() ) builder = AEABuilder.from_aea_project(Path(self._get_cwd())) assert "aiohttp" in builder._package_dependency_manager.pypi_dependencies
def _build_aea(self) -> AEA: """Build an AEA.""" builder = AEABuilder.from_aea_project(self._get_cwd()) builder.set_storage_uri("sqlite://some_file.db") aea = builder.build() aea.runtime._threaded = True return aea
def _launch_threads(agents: List[Path]) -> int: """ Launch many agents, multithreaded. :param click_context: the click context. :param agents: list of paths to agent projects. :return: exit status """ aeas = [] # type: List[AEA] for agent_directory in agents: with cd(agent_directory): aeas.append(AEABuilder.from_aea_project(".").build()) runner = AEARunner(agents=aeas, mode="threaded", fail_policy=ExecutorExceptionPolicies.log_only) try: runner.start(threaded=True) runner.join_thread( ) # for some reason on windows and python 3.7/3.7 keyboard interuption exception gets lost so run in threaded mode to catch keyboard interruped except KeyboardInterrupt: logger.info("Keyboard interrupt detected.") finally: runner.stop() return runner.num_failed
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_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 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_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 _build_aea(connection_ids: Optional[List[PublicId]], skip_consistency_check: bool) -> AEA: try: builder = AEABuilder.from_aea_project( Path("."), skip_consistency_check=skip_consistency_check) aea = builder.build(connection_ids=connection_ids) return aea except Exception as e: raise click.ClickException(str(e))
def test_from_project(self): """Test builder set from project dir.""" self._add_dummy_skill_config() builder = AEABuilder.from_aea_project(Path(self._get_cwd())) with cd(self._get_cwd()): aea = builder.build() dummy_skill = aea.resources.get_skill(DUMMY_SKILL_PUBLIC_ID) assert dummy_skill is None, "Shouldn't have found the skill in Resources."
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_AgentConfigManager_get_overridables(): """Test agent config manager get_overridables.""" path = Path(CUR_PATH, "data", "dummy_aea") agent_config = AEABuilder.try_to_load_agent_configuration_file(path) config_manager = AgentConfigManager(agent_config, path) agent_overridables, component_overridables = config_manager.get_overridables( ) assert "description" in agent_overridables assert "is_abstract" in list(component_overridables.values())[0]