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)
Esempio n. 2
0
    def _add_protocol(self, directory: str, protocol_name: str):
        """
        Add a protocol.

        :param directory: the agent's resources directory.
        :param protocol_name: the name of the protocol to be added.
        :return: None
        """
        # get the serializer
        serialization_spec = importlib.util.spec_from_file_location("serialization",
                                                                    os.path.join(directory, "protocols", protocol_name, "serialization.py"))
        serialization_module = importlib.util.module_from_spec(serialization_spec)
        serialization_spec.loader.exec_module(serialization_module)  # type: ignore
        classes = inspect.getmembers(serialization_module, inspect.isclass)
        serializer_classes = list(filter(lambda x: re.match("\\w+Serializer", x[0]), classes))
        serializer_class = serializer_classes[0][1]

        logger.debug("Found serializer class {serializer_class} for protocol {protocol_name}"
                     .format(serializer_class=serializer_class, protocol_name=protocol_name))
        serializer = serializer_class()

        config_loader = ConfigLoader("protocol-config_schema.json", ProtocolConfig)
        protocol_config = config_loader.load(open(Path(directory, "protocols", protocol_name, DEFAULT_PROTOCOL_CONFIG_FILE)))

        # instantiate the protocol manager.
        protocol = Protocol(protocol_name, serializer, protocol_config)
        self.register((protocol_name, None), protocol)
Esempio n. 3
0
    def setup_class(cls):
        """Set the test up."""
        cls.node = LocalNode()
        cls.node.start()
        cls.agent_name = "MyAgent"
        cls.private_key_pem_path = os.path.join(CUR_PATH, "data", "priv.pem")
        cls.wallet = Wallet({'default': cls.private_key_pem_path})
        cls.ledger_apis = LedgerApis({})
        cls.connection = OEFLocalConnection(cls.agent_name, cls.node)
        cls.connections = [cls.connection]

        cls.temp = tempfile.mkdtemp(prefix="test_aea_resources")
        cls.resources = Resources(cls.temp)
        cls.aea = AEA(cls.agent_name, cls.connections, cls.wallet, cls.ledger_apis, resources=cls.resources)

        cls.default_protocol_configuration = ProtocolConfig.from_json(
            yaml.safe_load(open(Path(AEA_DIR, "protocols", "default", "protocol.yaml"))))
        cls.default_protocol = Protocol("default",
                                        DefaultSerializer(),
                                        cls.default_protocol_configuration)
        cls.resources.protocol_registry.register(("default", None), cls.default_protocol)

        cls.error_skill = Skill.from_dir(Path(AEA_DIR, "skills", "error"), cls.aea.context)
        cls.dummy_skill = Skill.from_dir(Path(CUR_PATH, "data", "dummy_skill"), cls.aea.context)
        cls.resources.add_skill(cls.dummy_skill)
        cls.resources.add_skill(cls.error_skill)

        cls.expected_message = DefaultMessage(type=DefaultMessage.Type.BYTES, content=b"hello")

        cls.t = Thread(target=cls.aea.start)
        cls.t.start()
        time.sleep(0.5)

        cls.aea.outbox.put(Envelope(to=cls.agent_name, sender=cls.agent_name, protocol_id="default", message=DefaultSerializer().encode(cls.expected_message)))
Esempio n. 4
0
 def test_protocols_config(self):
     """Test the protocol config."""
     protocol = Protocol(
         protocol_id=PublicId.from_str("author/my_own_protocol:0.1.0"),
         serializer=cast(Serializer, ProtobufSerializer),
         config=ProtocolConfig(),
     )
     assert protocol.config is not None
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)
Esempio n. 6
0
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
Esempio n. 7
0
    def _add_protocol(
        self,
        protocol_directory: Path,
        allowed_protocols: Optional[Set[PublicId]] = None,
    ):
        """
        Add a protocol. If the protocol is not allowed, it is ignored.

        :param protocol_directory: the directory of the protocol to be added.
        :param allowed_protocols: an optional set of allowed protocols.
                                  If None, every protocol is allowed.
        :return: None
        """
        protocol_name = protocol_directory.name
        config_loader = ConfigLoader("protocol-config_schema.json",
                                     ProtocolConfig)
        protocol_config = config_loader.load(
            open(protocol_directory / DEFAULT_PROTOCOL_CONFIG_FILE))
        protocol_public_id = PublicId(protocol_config.author,
                                      protocol_config.name,
                                      protocol_config.version)
        if (allowed_protocols is not None
                and protocol_public_id not in allowed_protocols):
            logger.debug(
                "Ignoring protocol {}, not declared in the configuration file."
                .format(protocol_public_id))
            return

        # get the serializer
        serialization_spec = importlib.util.spec_from_file_location(
            "serialization", protocol_directory / "serialization.py")
        serialization_module = importlib.util.module_from_spec(
            serialization_spec)
        serialization_spec.loader.exec_module(
            serialization_module)  # type: ignore
        classes = inspect.getmembers(serialization_module, inspect.isclass)
        serializer_classes = list(
            filter(lambda x: re.match("\\w+Serializer", x[0]), classes))
        serializer_class = serializer_classes[0][1]

        logger.debug(
            "Found serializer class {serializer_class} for protocol {protocol_name}"
            .format(serializer_class=serializer_class,
                    protocol_name=protocol_name))
        serializer = serializer_class()

        # instantiate the protocol
        protocol = Protocol(protocol_config.public_id, serializer,
                            protocol_config)
        self.register(protocol_public_id, protocol)
Esempio n. 8
0
def test_component_add_bad_dep():
    """Test component load failed cause dependency."""
    builder = AEABuilder()
    builder.set_name("aea_1")
    builder.add_private_key("fetchai")
    connection = _make_dummy_connection()
    connection.configuration.pypi_dependencies = {
        "something": Dependency("something", "==0.1.0")
    }
    builder.add_component_instance(connection)

    a_protocol = Protocol(
        ProtocolConfig("a_protocol", "author", "0.1.0"), DefaultMessage
    )
    a_protocol.configuration.pypi_dependencies = {
        "something": Dependency("something", "==0.2.0")
    }
    with pytest.raises(
        AEAException, match=r"Conflict on package something: specifier set .*"
    ):
        builder.add_component_instance(a_protocol)
    async def test_end_to_end_aea_aca(self):
        # AEA components
        ledger_apis = LedgerApis({}, FetchAICrypto.identifier)
        wallet = Wallet({FetchAICrypto.identifier: FETCHAI_PRIVATE_KEY_FILE})
        identity = Identity(
            name="my_aea_1",
            address=wallet.addresses.get(FetchAICrypto.identifier),
            default_address_key=FetchAICrypto.identifier,
        )
        http_client_connection = HTTPClientConnection(
            address=self.aea_address,
            provider_address=self.aca_admin_address,
            provider_port=self.aca_admin_port,
        )
        resources = Resources()

        # create AEA
        aea = AEA(identity, [http_client_connection], wallet, ledger_apis,
                  resources)

        # Add http protocol to AEA resources
        http_protocol_configuration = ProtocolConfig.from_json(
            yaml.safe_load(
                open(
                    os.path.join(
                        self.cwd,
                        "packages",
                        "fetchai",
                        "protocols",
                        "http",
                        "protocol.yaml",
                    ))))
        http_protocol = Protocol(http_protocol_configuration, HttpSerializer())
        resources.add_protocol(http_protocol)

        # Request message & envelope
        request_http_message = HttpMessage(
            dialogue_reference=("", ""),
            target=0,
            message_id=1,
            performative=HttpMessage.Performative.REQUEST,
            method="GET",
            url="http://{}:{}/status".format(self.aca_admin_address,
                                             self.aca_admin_port),
            headers="",
            version="",
            bodyy=b"",
        )
        request_envelope = Envelope(
            to="ACA",
            sender="AEA",
            protocol_id=HTTP_PROTOCOL_PUBLIC_ID,
            message=HttpSerializer().encode(request_http_message),
        )

        # add a simple skill with handler
        skill_context = SkillContext(aea.context)
        skill_config = SkillConfig(name="simple_skill",
                                   author="fetchai",
                                   version="0.1.0")
        aea_handler = AEAHandler(skill_context=skill_context,
                                 name="aea_handler")
        simple_skill = Skill(skill_config,
                             skill_context,
                             handlers={aea_handler.name: aea_handler})
        resources.add_skill(simple_skill)

        # add error skill to AEA
        error_skill = Skill.from_dir(os.path.join(AEA_DIR, "skills", "error"))
        resources.add_skill(error_skill)

        # start AEA thread
        t_aea = Thread(target=aea.start)
        try:
            t_aea.start()
            time.sleep(1.0)
            aea.outbox.put(request_envelope)
            time.sleep(5.0)
            assert (aea_handler.handled_message.performative ==
                    HttpMessage.Performative.RESPONSE)
            assert aea_handler.handled_message.version == ""
            assert aea_handler.handled_message.status_code == 200
            assert aea_handler.handled_message.status_text == "OK"
            assert aea_handler.handled_message.headers is not None
            assert aea_handler.handled_message.version is not None
        finally:
            aea.stop()
            t_aea.join()
Esempio n. 10
0
 def test_protocols_config(self):
     """Test the protocol config."""
     protocol = Protocol(id="test",
                         serializer=cast(Serializer, ProtobufSerializer),
                         config=ProtocolConfig())
     assert protocol.config is not None
    async def test_end_to_end_aea_aca(self):
        """Test the end to end aea aca interaction."""
        # AEA components
        wallet = Wallet({DEFAULT_LEDGER: DEFAULT_PRIVATE_KEY_FILE})
        identity = Identity(
            name="my_aea_1",
            address=wallet.addresses.get(DEFAULT_LEDGER),
            default_address_key=DEFAULT_LEDGER,
        )
        configuration = ConnectionConfig(
            host=self.aca_admin_address,
            port=self.aca_admin_port,
            connection_id=HTTPClientConnection.connection_id,
        )
        http_client_connection = HTTPClientConnection(
            configuration=configuration,
            identity=identity,
        )
        resources = Resources()
        resources.add_connection(http_client_connection)

        # create AEA
        aea = AEA(identity, wallet, resources)

        # Add http protocol to AEA resources
        http_protocol_configuration = ProtocolConfig.from_json(
            yaml.safe_load(
                open(
                    os.path.join(
                        self.cwd,
                        "packages",
                        "fetchai",
                        "protocols",
                        "http",
                        "protocol.yaml",
                    ))))
        http_protocol = Protocol(http_protocol_configuration,
                                 HttpMessage.serializer())
        resources.add_protocol(http_protocol)

        # Request message & envelope
        request_http_message = HttpMessage(
            dialogue_reference=("", ""),
            target=0,
            message_id=1,
            performative=HttpMessage.Performative.REQUEST,
            method="GET",
            url="http://{}:{}/status".format(self.aca_admin_address,
                                             self.aca_admin_port),
            headers="",
            version="",
            body=b"",
        )
        request_http_message.to = "ACA"
        request_envelope = Envelope(
            to="ACA",
            sender="AEA",
            protocol_id=HttpMessage.protocol_id,
            message=request_http_message,
        )

        # add a simple skill with handler
        skill_context = SkillContext(aea.context)
        skill_config = SkillConfig(name="simple_skill",
                                   author="fetchai",
                                   version="0.1.0")
        aea_handler = AEAHandler(skill_context=skill_context,
                                 name="aea_handler")
        simple_skill = Skill(skill_config,
                             skill_context,
                             handlers={aea_handler.name: aea_handler})
        resources.add_skill(simple_skill)

        # add error skill to AEA
        error_skill = Skill.from_dir(os.path.join(AEA_DIR, "skills", "error"),
                                     agent_context=aea.context)
        resources.add_skill(error_skill)

        # start AEA thread
        t_aea = Thread(target=aea.start)
        try:
            t_aea.start()
            time.sleep(1.0)
            aea.outbox.put(request_envelope)
            time.sleep(5.0)
            assert (aea_handler.handled_message.performative ==
                    HttpMessage.Performative.RESPONSE)
            assert aea_handler.handled_message.version == ""
            assert aea_handler.handled_message.status_code == 200
            assert aea_handler.handled_message.status_text == "OK"
            assert aea_handler.handled_message.headers is not None
            assert aea_handler.handled_message.version is not None
        finally:
            aea.stop()
            t_aea.join()
Esempio n. 12
0
    def setup_class(cls):
        """Set the test up."""
        cls.node = LocalNode()
        cls.node.start()
        cls.agent_name = "MyAgent"
        cls.private_key_path = os.path.join(CUR_PATH, "data",
                                            "fet_private_key.txt")
        cls.wallet = Wallet({FETCHAI: cls.private_key_path})
        cls.ledger_apis = LedgerApis({}, FETCHAI)
        cls.identity = Identity(cls.agent_name,
                                address=cls.wallet.addresses[FETCHAI])
        cls.connection = OEFLocalConnection(
            cls.agent_name, cls.node, connection_id=LOCAL_CONNECTION_PUBLIC_ID)
        cls.connections = [cls.connection]

        cls.temp = tempfile.mkdtemp(prefix="test_aea_resources")
        cls.resources = Resources(cls.temp)
        cls.aea = AEA(
            cls.identity,
            cls.connections,
            cls.wallet,
            cls.ledger_apis,
            resources=cls.resources,
        )

        default_protocol_id = DefaultMessage.protocol_id

        cls.default_protocol_configuration = ProtocolConfig.from_json(
            yaml.safe_load(
                open(Path(AEA_DIR, "protocols", "default", "protocol.yaml"))))
        cls.default_protocol = Protocol(default_protocol_id,
                                        DefaultSerializer(),
                                        cls.default_protocol_configuration)
        cls.resources.protocol_registry.register(default_protocol_id,
                                                 cls.default_protocol)

        cls.error_skill = Skill.from_dir(Path(AEA_DIR, "skills", "error"),
                                         cls.aea.context)
        cls.dummy_skill = Skill.from_dir(Path(CUR_PATH, "data", "dummy_skill"),
                                         cls.aea.context)
        cls.resources.add_skill(cls.dummy_skill)
        cls.resources.add_skill(cls.error_skill)

        cls.expected_message = DefaultMessage(
            dialogue_reference=("", ""),
            message_id=1,
            target=0,
            performative=DefaultMessage.Performative.BYTES,
            content=b"hello",
        )
        cls.expected_message.counterparty = cls.agent_name

        cls.t = Thread(target=cls.aea.start)
        cls.t.start()
        time.sleep(0.5)

        cls.aea.outbox.put(
            Envelope(
                to=cls.agent_name,
                sender=cls.agent_name,
                protocol_id=default_protocol_id,
                message=DefaultSerializer().encode(cls.expected_message),
            ))
Esempio n. 13
0
def test_protocol_repr():
    """Test protocol repr."""
    config_mock = Mock()
    config_mock.public_id = UNKNOWN_PROTOCOL_PUBLIC_ID
    protocol = Protocol(config_mock, message_class=Message)
    assert repr(protocol) == f"Protocol({UNKNOWN_PROTOCOL_PUBLIC_ID})"
Esempio n. 14
0
    def test_generated_protocol_end_to_end(self):
        """Test that a generated protocol could be used in exchanging messages between two agents."""
        # AEA components
        ledger_apis = LedgerApis({}, FETCHAI)

        wallet_1 = Wallet({FETCHAI: FETCHAI_PRIVATE_KEY_FILE})
        wallet_2 = Wallet({FETCHAI: FETCHAI_PRIVATE_KEY_FILE})

        identity_1 = Identity(
            name="my_aea_1",
            address=wallet_1.addresses.get(FETCHAI),
            default_address_key=FETCHAI,
        )
        identity_2 = Identity(
            name="my_aea_2",
            address=wallet_2.addresses.get(FETCHAI),
            default_address_key=FETCHAI,
        )

        oef_connection_1 = OEFConnection(
            address=identity_1.address, oef_addr=HOST, oef_port=PORT
        )
        oef_connection_2 = OEFConnection(
            address=identity_2.address, oef_addr=HOST, oef_port=PORT
        )

        resources_1 = Resources()
        resources_2 = Resources()

        # add generated protocols to resources
        generated_protocol_configuration = ProtocolConfig.from_json(
            yaml.safe_load(
                open(
                    os.path.join(
                        self.cwd,
                        "tests",
                        "data",
                        "generator",
                        "two_party_negotiation",
                        "protocol.yaml",
                    )
                )
            )
        )
        generated_protocol = Protocol(
            TwoPartyNegotiationMessage.protocol_id,
            TwoPartyNegotiationSerializer(),
            generated_protocol_configuration,
        )
        resources_1.protocol_registry.register(
            TwoPartyNegotiationMessage.protocol_id, generated_protocol
        )
        resources_2.protocol_registry.register(
            TwoPartyNegotiationMessage.protocol_id, generated_protocol
        )

        # create AEAs
        aea_1 = AEA(identity_1, [oef_connection_1], wallet_1, ledger_apis, resources_1)
        aea_2 = AEA(identity_2, [oef_connection_2], wallet_2, ledger_apis, resources_2)

        inform_number = tuple((1370, 1991, 1, 4, 17, 6))
        # message 1
        message = TwoPartyNegotiationMessage(
            message_id=1,
            dialogue_reference=(str(0), ""),
            target=0,
            performative=TwoPartyNegotiationMessage.Performative.INFORM,
            inform_number=inform_number,
        )
        encoded_message_in_bytes = TwoPartyNegotiationSerializer().encode(message)
        envelope = Envelope(
            to=identity_2.address,
            sender=identity_1.address,
            protocol_id=TwoPartyNegotiationMessage.protocol_id,
            message=encoded_message_in_bytes,
        )
        # message 2
        reply_message = {1: "number one", 2: "number two", 7: "number seven"}
        message_2 = TwoPartyNegotiationMessage(
            message_id=2,
            dialogue_reference=(str(0), ""),
            target=1,
            performative=TwoPartyNegotiationMessage.Performative.INFORM_REPLY,
            reply_message=reply_message,
        )
        encoded_message_2_in_bytes = TwoPartyNegotiationSerializer().encode(message_2)

        # add handlers to AEA resources
        agent_1_handler = Agent1Handler(
            skill_context=SkillContext(aea_1.context), name="fake_skill"
        )
        resources_1.handler_registry.register(
            (
                PublicId.from_str("fetchai/fake_skill:0.1.0"),
                TwoPartyNegotiationMessage.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",
        )
        resources_2.handler_registry.register(
            (
                PublicId.from_str("fetchai/fake_skill:0.1.0"),
                TwoPartyNegotiationMessage.protocol_id,
            ),
            agent_2_handler,
        )

        # add error skill to AEAs
        error_skill_1 = Skill.from_dir(
            os.path.join(AEA_DIR, "skills", "error"), aea_1.context
        )
        resources_1.add_skill(error_skill_1)

        error_skill_2 = Skill.from_dir(
            os.path.join(AEA_DIR, "skills", "error"), aea_2.context
        )
        resources_2.add_skill(error_skill_2)

        # 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.inform_number == message.inform_number
            ), "Message from Agent 1 to 2: inform_numbers 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.reply_message == message_2.reply_message
            ), "Message from Agent 1 to 2: reply_messages do not match"
            time.sleep(2.0)
        finally:
            aea_1.stop()
            aea_2.stop()
            t_1.join()
            t_2.join()