Exemple #1
0
    def test_load_component_failed_cause_package_not_found(self):
        """Test package not found in import."""
        self.add_item("skill", "fetchai/echo:latest", local=True)

        with cd(self._get_cwd()):
            echo_dir = "./vendor/fetchai/skills/echo"
            handlers_file = Path(echo_dir) / "handlers.py"
            assert handlers_file.exists()
            file_data = handlers_file.read_text()
            file_data = file_data.replace(
                "from packages.fetchai.protocols.default",
                "from packages.fetchai.protocols.not_exist_protocol",
            )
            handlers_file.write_text(file_data)
            with cd("./vendor/fetchai"):
                self.run_cli_command("fingerprint", "skill",
                                     "fetchai/echo:0.14.0")
            agent_context = Mock()
            agent_context.agent_name = self.agent_name
            configuration = cast(
                SkillConfig,
                load_component_configuration(ComponentType.SKILL,
                                             Path(echo_dir)),
            )
            configuration.directory = Path(echo_dir)
            with pytest.raises(
                    ClickException,
                    match=
                    r"Package loading error: An error occurred while loading skill fetchai/echo:.*\nTraceback",
            ) as e:
                self.run_cli_command("run", cwd=self._get_cwd())
            assert "No AEA package found with author name" in str(e)
            assert "not_exist_protocol" in str(e)
Exemple #2
0
    def test_upgrade(self):
        """Test upgrade project old version to latest one and compare with latest project fetched."""
        with cd(self.latest_agent_name):
            latest_agent_items = set(
                ItemRemoveHelper(self.load_mock_context())
                .get_agent_dependencies_with_reverse_dependencies()
                .keys()
            )

        with cd(self.agent_name):
            self.runner.invoke(  # pylint: disable=no-member
                cli,
                ["--skip-consistency-check", "upgrade", "--local"],
                standalone_mode=False,
                catch_exceptions=False,
            )
            agent_items = set(
                ItemRemoveHelper(self.load_mock_context())
                .get_agent_dependencies_with_reverse_dependencies()
                .keys()
            )
            assert latest_agent_items == agent_items

        # upgrade again to check it workd with upgraded version
        with cd(self.agent_name):
            self.runner.invoke(  # pylint: disable=no-member
                cli,
                ["--skip-consistency-check", "upgrade", "--local"],
                standalone_mode=False,
                catch_exceptions=False,
            )
            agent_items = set(
                ItemRemoveHelper(self.load_mock_context())
                .get_agent_dependencies_with_reverse_dependencies()
                .keys()
            )
            assert latest_agent_items == agent_items

        # compare both configuration files, except the agent name and the author
        upgraded_agent_dir = Path(self.agent_name)
        latest_agent_dir = Path(self.latest_agent_name)
        lines_upgraded_agent_config = (
            (upgraded_agent_dir / DEFAULT_AEA_CONFIG_FILE).read_text().splitlines()
        )
        lines_latest_agent_config = (
            (latest_agent_dir / DEFAULT_AEA_CONFIG_FILE).read_text().splitlines()
        )
        # the slice is because we don't compare the agent name and the author name
        assert lines_upgraded_agent_config[2:] == lines_latest_agent_config[2:]

        # compare vendor folders.
        assert are_dirs_equal(
            upgraded_agent_dir / "vendor", latest_agent_dir / "vendor"
        )
Exemple #3
0
 def invoke(cls, *args: str) -> Result:
     """Call the cli command."""
     with cd(cls._get_cwd()):
         result = cls.runner.invoke(
             cli, args, standalone_mode=False, catch_exceptions=False
         )
     return result
Exemple #4
0
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
Exemple #5
0
def test_fetch_twice_remote():
    """Test fails on fetch if dir exists."""
    with TemporaryDirectory() as tmp_dir:
        with cd(tmp_dir):
            name = "my_first_aea"
            runner = CliRunner()
            result = runner.invoke(
                cli,
                [
                    "--registry-path",
                    PACKAGES_DIR,
                    "fetch",
                    "--local",
                    "fetchai/my_first_aea",
                ],
                catch_exceptions=False,
            )
            assert result.exit_code == 0, result.stdout
            assert os.path.exists(name)

            with pytest.raises(
                ClickException,
                match='Item "my_first_aea" already exists in target folder.',
            ):
                result = runner.invoke(
                    cli,
                    ["fetch", "--remote", "fetchai/my_first_aea"],
                    standalone_mode=False,
                    catch_exceptions=False,
                )
 def set_runtime_mode_to_async(cls, agent_name: str) -> None:
     """Set runtime mode of the agent to async."""
     with cd(agent_name):
         config_path = Path(cls.t, agent_name, DEFAULT_AEA_CONFIG_FILE)
         config = yaml.safe_load(open(config_path))
         config.setdefault("runtime_mode", "async")
         yaml.safe_dump(config, open(config_path, "w"))
Exemple #7
0
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
Exemple #8
0
    def run_cli_command(cls, *args: str, cwd: str = ".", **kwargs: str) -> Result:
        """
        Run AEA CLI command.

        :param args: CLI args
        :param cwd: the working directory from where to run the command.
        :param kwargs: other keyword arguments to click.CLIRunner.invoke.
        :raises AEATestingException: if command fails.

        :return: Result
        """
        with cd(cwd):
            result = cls.runner.invoke(
                cli,
                [*CLI_LOG_OPTION, *args],
                standalone_mode=False,
                catch_exceptions=False,
                **kwargs,
            )
            cls.last_cli_runner_result = result
            if result.exit_code != 0:  # pragma: nocover
                raise AEATestingException(
                    "Failed to execute AEA CLI command with args {}.\n"
                    "Exit code: {}\nException: {}".format(
                        args, result.exit_code, result.exception
                    )
                )
            return result
    def difference_to_fetched_agent(cls, public_id: str,
                                    agent_name: str) -> List[str]:
        """
        Compare agent against the one fetched from public id.

        :param public_id: str public id
        :param agents_name: str agent name.

        :return: list of files differing in the projects
        """
        def is_allowed_diff_in_agent_config(
            path_to_fetched_aea, path_to_manually_created_aea
        ) -> Tuple[bool, Dict[str, str], Dict[str, str]]:
            with open(os.path.join(path_to_fetched_aea, "aea-config.yaml"),
                      "r") as file:
                content1 = yaml.full_load(file)
            with open(
                    os.path.join(path_to_manually_created_aea,
                                 "aea-config.yaml"), "r") as file:
                content2 = yaml.full_load(file)
            content1c = copy.deepcopy(content1)
            for key, value in content1c.items():
                if content2[key] == value:
                    content1.pop(key)
                    content2.pop(key)
            allowed_diff_keys = [
                "aea_version", "author", "description", "version"
            ]
            result = all([key in allowed_diff_keys for key in content1.keys()])
            result = result and all(
                [key in allowed_diff_keys for key in content2.keys()])
            if result:
                return result, {}, {}
            else:
                return result, content1, content2

        path_to_manually_created_aea = os.path.join(cls.t, agent_name)
        new_cwd = os.path.join(cls.t, "fetch_dir")
        os.mkdir(new_cwd)
        path_to_fetched_aea = os.path.join(new_cwd, agent_name)
        registry_tmp_dir = os.path.join(new_cwd, cls.packages_dir_path)
        shutil.copytree(str(cls.package_registry_src), str(registry_tmp_dir))
        with cd(new_cwd):
            cls.run_cli_command("fetch", "--local", public_id, "--alias",
                                agent_name)
        comp = dircmp(path_to_manually_created_aea, path_to_fetched_aea)
        file_diff = comp.diff_files
        result, diff1, diff2 = is_allowed_diff_in_agent_config(
            path_to_fetched_aea, path_to_manually_created_aea)
        if result:
            file_diff.remove("aea-config.yaml")  # won't match!
        else:
            file_diff.append("Difference in aea-config.yaml: " + str(diff1) +
                             " vs. " + str(diff2))
        try:
            shutil.rmtree(new_cwd)
        except (OSError, IOError):
            pass
        return file_diff
Exemple #10
0
def test_local_registry_update():
    """Test local-registry-sync cli command."""
    PACKAGES = [
        PackageId(PackageType.CONNECTION, PublicId("fetchai", "local", "0.11.0")),
        PackageId(PackageType.AGENT, PublicId("fetchai", "my_first_aea", "0.10.0")),
    ]
    with TemporaryDirectory() as tmp_dir:
        for package_id in PACKAGES:
            package_dir = os.path.join(
                tmp_dir,
                package_id.public_id.author,
                str(package_id.package_type.to_plural()),
                package_id.public_id.name,
            )
            os.makedirs(package_dir)
            fetch_package(
                str(package_id.package_type),
                public_id=package_id.public_id,
                cwd=tmp_dir,
                dest=package_dir,
            )

        assert set(PACKAGES) == set([i[0] for i in enlist_packages(tmp_dir)])

        runner = CliRunner()
        with cd(tmp_dir):
            # check intention to upgrade
            with patch(
                "aea.cli.local_registry_sync.replace_package"
            ) as replace_package_mock:
                result = runner.invoke(
                    cli, ["-s", "local-registry-sync"], catch_exceptions=False
                )
                assert result.exit_code == 0, result.stdout
            assert replace_package_mock.call_count == len(PACKAGES)

            # do actual upgrade
            result = runner.invoke(
                cli, ["-s", "local-registry-sync"], catch_exceptions=False
            )
            assert result.exit_code == 0, result.stdout

            # check next update will do nothing
            with patch(
                "aea.cli.local_registry_sync.replace_package"
            ) as replace_package_mock:
                result = runner.invoke(
                    cli, ["-s", "local-registry-sync"], catch_exceptions=False
                )
                assert result.exit_code == 0, result.stdout
            assert replace_package_mock.call_count == 0

        def sort_(packages):
            return sorted(packages, key=lambda x: str(x))

        new_packages = [i[0] for i in enlist_packages(tmp_dir)]

        for new_package, old_package in zip(sort_(new_packages), sort_(PACKAGES)):
            assert new_package.public_id > old_package.public_id
Exemple #11
0
 def invoke(self, *args):
     """Call the cli command."""
     with cd(self._get_cwd()):
         result = self.runner.invoke(cli,
                                     args,
                                     standalone_mode=False,
                                     catch_exceptions=False)
     return result
Exemple #12
0
 def load_config(self) -> AgentConfig:
     """Load AgentConfig from current directory."""
     with cd(self._get_cwd()):
         agent_loader = self.loader()
         path = Path(DEFAULT_AEA_CONFIG_FILE)
         with path.open(mode="r", encoding="utf-8") as fp:
             agent_config = agent_loader.load(fp)
         return agent_config
Exemple #13
0
    def test_build_positive_aea(self):
        """Test build project-wide entrypoint, positive."""
        with cd(self._get_cwd()):
            self.script_path.write_text("")
            with patch.object(self.builder.logger, "info") as info_mock:
                self.builder.call_all_build_entrypoints()

        info_mock.assert_any_call("Building AEA package...")
        info_mock.assert_any_call(RegexComparator("Running command '.*script.py .*'"))
    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."
Exemple #15
0
def load_agent(agent_dir: Union[PathLike, str]) -> AEA:
    """
    Load AEA from directory.

    :param agent_dir: agent configuration directory

    :return: AEA instance
    """
    with cd(agent_dir):
        return AEABuilder.from_aea_project(".").build()
Exemple #16
0
 def get_balance(self) -> int:
     """Get balance for current agent."""
     with cd(self._get_cwd()):
         agent_config = AgentConfigManager.verify_or_create_private_keys(
             Path("."),
             substitude_env_vars=False,
             private_key_helper=private_key_verify_or_create,
         ).agent_config
         wallet = get_wallet_from_agent_config(agent_config)
         return int(try_get_balance(agent_config, wallet, self.LEDGER_ID))
Exemple #17
0
    def test_from_project(self):
        """Test builder set from project dir."""
        self._add_dummy_skill_config()
        self.run_cli_command("issue-certificates", cwd=self._get_cwd())
        builder = AEABuilder.from_aea_project(Path(self._get_cwd()))
        with cd(self._get_cwd()):
            builder.call_all_build_entrypoints()
            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."
Exemple #18
0
 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_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()
     builder = AEABuilder.from_aea_project(Path(self._get_cwd()))
     with cd(self._get_cwd()):
         aea = builder.build()
     assert aea.name == self.agent_name
     stub_connection_id = StubConnection.connection_id
     stub_connection = aea.resources.get_connection(stub_connection_id)
     assert stub_connection.configuration.config == dict(
         input_file=self.expected_input_file, output_file=self.expected_output_file
     )
Exemple #20
0
    def replace_private_key_in_file(
        cls, private_key: str, private_key_filepath: str = DEFAULT_PRIVATE_KEY_FILE
    ) -> None:
        """
        Replace the private key in the provided file with the provided key.

        :param private_key: the private key
        :param private_key_filepath: the filepath to the private key file

        :return: None
        :raises: exception if file does not exist
        """
        with cd(cls._get_cwd()):  # pragma: nocover
            with open_file(private_key_filepath, "wt") as f:
                f.write(private_key)
Exemple #21
0
    def test_non_vendor_nothing_to_upgrade(self, *mocks):  # pylint: disable=unused-argument
        """Test upgrade project dependencies not removed cause non vendor."""
        with cd(self.agent_name):
            base_agent_items = set(
                ItemRemoveHelper(self.load_config()).
                get_agent_dependencies_with_reverse_dependencies().keys())

            self.runner.invoke(  # pylint: disable=no-member
                cli,
                ["--skip-consistency-check", "upgrade"],
                standalone_mode=False,
                catch_exceptions=False,
            )
            agent_items = set(
                ItemRemoveHelper(self.load_config()).
                get_agent_dependencies_with_reverse_dependencies().keys())
            assert base_agent_items == agent_items
    def test_from_project(self):
        """Test builder set from project dir."""
        self.new_behaviour_args = {"behaviour_arg_1": 42}
        self.new_handler_args = {"handler_arg_1": 42}
        self.new_model_args = {"model_arg_1": 42}
        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)
        dummy_behaviour = dummy_skill.behaviours["dummy"]
        assert dummy_behaviour.config == {"behaviour_arg_1": 42, "behaviour_arg_2": "2"}
        dummy_handler = dummy_skill.handlers["dummy"]
        assert dummy_handler.config == {"handler_arg_1": 42, "handler_arg_2": "2"}
        dummy_model = dummy_skill.models["dummy"]
        assert dummy_model.config == {"model_arg_1": 42, "model_arg_2": "2"}
Exemple #23
0
    def test_component_configuration_removed_from_agent_config(self):
        """Test component configuration removed from agent config."""
        with cd(self._get_cwd()):
            self.run_cli_command(
                "add", "--local", self.ITEM_TYPE, str(self.ITEM_PUBLIC_ID)
            )
            self.run_cli_command("add", "--local", "connection", "fetchai/http_server")

            self.runner.invoke(
                cli,
                [
                    "config",
                    "set",
                    "vendor.fetchai.connections.soef.config.api_key",
                    "some_api_key",
                ],
                standalone_mode=False,
                catch_exceptions=False,
            )
            self.runner.invoke(
                cli,
                [
                    "config",
                    "set",
                    "vendor.fetchai.connections.http_server.config.port",
                    "9000",
                ],
                standalone_mode=False,
                catch_exceptions=False,
            )
            config = self.load_config()
            assert config.component_configurations
            assert (
                PackageId(self.ITEM_TYPE, self.ITEM_PUBLIC_ID)
                in config.component_configurations
            )

            self.run_cli_command("remove", self.ITEM_TYPE, str(self.ITEM_PUBLIC_ID))

            config = self.load_config()
            assert (
                PackageId(self.ITEM_TYPE, self.ITEM_PUBLIC_ID)
                not in config.component_configurations
            )
            assert config.component_configurations
Exemple #24
0
    def difference_to_fetched_agent(cls, public_id: str,
                                    agent_name: str) -> List[str]:
        """
        Compare agent against the one fetched from public id.

        :param public_id: str public id
        :param agents_name: str agent name.

        :return: list of files differing in the projects
        """
        def is_allowed_diff_in_agent_config(
                path_to_fetched_aea, path_to_manually_created_aea) -> bool:
            with open(os.path.join(path_to_fetched_aea, "aea-config.yaml"),
                      "r") as file:
                content1 = yaml.full_load(file)
            with open(
                    os.path.join(path_to_manually_created_aea,
                                 "aea-config.yaml"), "r") as file:
                content2 = yaml.full_load(file)
            diff_count = 0
            for key, value in content1.items():
                if content2[key] != value:
                    diff_count += 1
            # allow diff in aea_version, author, description and version
            return diff_count <= 4

        path_to_manually_created_aea = os.path.join(cls.t, agent_name)
        new_cwd = os.path.join(cls.t, "fetch_dir")
        os.mkdir(new_cwd)
        path_to_fetched_aea = os.path.join(new_cwd, agent_name)
        registry_tmp_dir = os.path.join(new_cwd, cls.packages_dir_path)
        shutil.copytree(str(cls.package_registry_src), str(registry_tmp_dir))
        with cd(new_cwd):
            cls.run_cli_command("fetch", "--local", public_id, "--alias",
                                agent_name)
        comp = dircmp(path_to_manually_created_aea, path_to_fetched_aea)
        file_diff = comp.diff_files
        if is_allowed_diff_in_agent_config(path_to_fetched_aea,
                                           path_to_manually_created_aea):
            file_diff.remove("aea-config.yaml")  # won't match!
        try:
            shutil.rmtree(new_cwd)
        except (OSError, IOError):
            pass
        return file_diff
    def run_cli_command(cls, *args: str, cwd: str = ".") -> None:
        """
        Run AEA CLI command.

        :param args: CLI args
        :param cwd: the working directory from where to run the command.
        :raises AEATestingException: if command fails.

        :return: None
        """
        with cd(cwd):
            result = cls.runner.invoke(cli, [*CLI_LOG_OPTION, *args],
                                       standalone_mode=False)
            cls.last_cli_runner_result = result
            if result.exit_code != 0:
                raise AEATestingException(
                    "Failed to execute AEA CLI command with args {}.\n"
                    "Exit code: {}\nException: {}".format(
                        args, result.exit_code, result.exception))
Exemple #26
0
def test_clean_tarfiles_error():
    """Test clean tarfiles wrapper in case of error."""

    expected_message = "some exception"

    def func() -> str:
        """The function being wrapped."""
        raise Exception(expected_message)

    wrapped = clean_tarfiles(func)
    with tempfile.TemporaryDirectory() as tempdir:
        with cd(tempdir):
            tarfile_path = Path(tempdir, "tarfile.tar.gz")
            tarfile_path.touch()

            with pytest.raises(Exception, match=expected_message):
                wrapped()

            assert not tarfile_path.exists()
Exemple #27
0
def test_clean_tarfiles():
    """Test clean tarfiles wrapper."""

    expected_result = "result"

    def func() -> str:
        """The function being wrapped."""
        return expected_result

    wrapped = clean_tarfiles(func)
    with tempfile.TemporaryDirectory() as tempdir:
        with cd(tempdir):
            tarfile_path = Path(tempdir, "tarfile.tar.gz")
            tarfile_path.touch()

            result = wrapped()

            assert not tarfile_path.exists()
            assert result == expected_result
Exemple #28
0
    def test_build_positive_package(self):
        """Test build package entrypoint, positive."""
        with cd(self._get_cwd()):
            self.script_path.write_text("")
            # add mock configuration build entrypoint
            with patch.object(self.builder, "_package_dependency_manager") as _mock_mgr:
                mock_config = MagicMock(
                    component_id=self.component_id,
                    build_entrypoint=str(self.script_path),
                    directory=".",
                    build_directory="test",
                )
                mock_values = MagicMock(return_value=[mock_config])
                _mock_mgr._dependencies = MagicMock(values=mock_values)

                with patch.object(self.builder.logger, "info") as info_mock:
                    self.builder.call_all_build_entrypoints()

        info_mock.assert_any_call(f"Building package {self.component_id}...")
        info_mock.assert_any_call(RegexComparator("Running command '.*script.py .*'"))
Exemple #29
0
    def _test_project(self, is_local: bool, skip_consistency_check: bool):
        """Test method to handle both local and remote registry."""
        registry_path = os.path.join(ROOT_DIR, "packages")
        project = Project.load(
            self.t,
            self.project_public_id,
            is_local=is_local,
            registry_path=registry_path,
            skip_consistency_check=skip_consistency_check,
        )
        assert os.path.exists(self.project_path)

        with cd(self.project_path):
            result = self.runner.invoke(
                cli,
                ["--skip-consistency-check", "config", "get", "agent.agent_name"],
                catch_exceptions=False,
                standalone_mode=False,
            )
        assert self.project_public_id.name in result.output
        project.remove()
        assert not os.path.exists(self.project_path)
Exemple #30
0
 def test_get_wallet_from_ctx(self):
     """Test get_wallet_from_context."""
     ctx = mock.Mock()
     with cd(self._get_cwd()):
         assert isinstance(get_wallet_from_context(ctx), Wallet)