예제 #1
0
    def test_empty_search_result(self):
        """Test that at the beginning, the search request returns an empty search result."""
        request_id = 1
        query = Query(constraints=[], model=None)

        # build and send the request
        search_services_request = OEFMessage(
            oef_type=OEFMessage.Type.SEARCH_SERVICES,
            id=request_id,
            query=query)
        msg_bytes = OEFSerializer().encode(search_services_request)
        envelope = Envelope(to=DEFAULT_OEF,
                            sender=self.public_key_1,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        self.mailbox1.send(envelope)

        # check the result
        response_envelope = self.mailbox1.inbox.get(block=True, timeout=2.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.to == self.public_key_1
        assert response_envelope.sender == DEFAULT_OEF
        search_result = OEFSerializer().decode(response_envelope.message)
        assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert search_result.get("agents") == []
예제 #2
0
    def register_service(self) -> None:
        """
        Register to the OEF Service Directory.

        In particular, register
            - as a seller, listing the goods supplied, or
            - as a buyer, listing the goods demanded, or
            - as both.

        :return: None
        """
        if self.game_instance.strategy.is_registering_as_seller:
            logger.debug("[{}]: Updating service directory as seller with goods supplied.".format(self.agent_name))
            goods_supplied_description = self.game_instance.get_service_description(is_supply=True)
            self.game_instance.goods_supplied_description = goods_supplied_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=DEFAULT_MSG_ID, service_description=goods_supplied_description, service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(to=DEFAULT_OEF, sender=self.crypto.public_key, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        if self.game_instance.strategy.is_registering_as_buyer:
            logger.debug("[{}]: Updating service directory as buyer with goods demanded.".format(self.agent_name))
            goods_demanded_description = self.game_instance.get_service_description(is_supply=False)
            self.game_instance.goods_demanded_description = goods_demanded_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=DEFAULT_MSG_ID, service_description=goods_demanded_description, service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(to=DEFAULT_OEF, sender=self.crypto.public_key, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
예제 #3
0
    def _unregister_service(self) -> None:
        """
        Unregister service from OEF Service Directory.

        :return: None
        """
        if self._registered_goods_demanded_description is not None:
            msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=self.
                             _registered_goods_demanded_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
            self._registered_goods_demanded_description = None
        if self._registered_goods_supplied_description is not None:
            msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=self.
                             _registered_goods_supplied_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
            self._registered_goods_supplied_description = None
예제 #4
0
    def unregister_service(self) -> None:
        """
        Unregister service from OEF Service Directory.

        :return: None
        """
        if self.game_instance.goods_demanded_description is not None:
            msg = OEFMessage(
                oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                id=DEFAULT_MSG_ID,
                service_description=self.game_instance.goods_demanded_description,
                service_id="",
            )
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes,
            )
        if self.game_instance.goods_supplied_description is not None:
            msg = OEFMessage(
                oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                id=DEFAULT_MSG_ID,
                service_description=self.game_instance.goods_supplied_description,
                service_id="",
            )
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes,
            )
예제 #5
0
async def test_send_oef_message(network_node):
    """Test the send oef message."""
    private_key_pem_path = os.path.join(CUR_PATH, "data", "priv.pem")
    wallet = Wallet({'default': private_key_pem_path})
    public_key = wallet.public_keys['default']
    oef_connection = OEFConnection(public_key=public_key,
                                   oef_addr="127.0.0.1",
                                   oef_port=10000)
    oef_connection.loop = asyncio.get_event_loop()
    await oef_connection.connect()

    msg = OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR,
                     id=0,
                     operation=OEFMessage.OEFErrorOperation.SEARCH_AGENTS)
    msg_bytes = OEFSerializer().encode(msg)
    envelope = Envelope(to=DEFAULT_OEF,
                        sender=public_key,
                        protocol_id=OEFMessage.protocol_id,
                        message=msg_bytes)
    with pytest.raises(ValueError):
        await oef_connection.send(envelope)

    data_model = DataModel("foobar", attributes=[])
    query = Query(constraints=[], model=data_model)

    msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=0, query=query)
    msg_bytes = OEFSerializer().encode(msg)
    envelope = Envelope(to="recipient",
                        sender=public_key,
                        protocol_id=OEFMessage.protocol_id,
                        message=msg_bytes)
    await oef_connection.send(envelope)
    await oef_connection.disconnect()
예제 #6
0
    async def _handle_oef_message(self, envelope: Envelope) -> None:
        """Handle oef messages.

        :param envelope: the envelope
        :return: None
        """
        oef_message = OEFSerializer().decode(envelope.message)
        sender = envelope.sender
        request_id = cast(int, oef_message.get("id"))
        oef_type = OEFMessage.Type(oef_message.get("type"))
        if oef_type == OEFMessage.Type.REGISTER_SERVICE:
            await self._register_service(
                sender,
                cast(Description, oef_message.get("service_description")))
        elif oef_type == OEFMessage.Type.REGISTER_AGENT:
            await self._register_agent(
                sender, cast(Description,
                             oef_message.get("agent_description")))
        elif oef_type == OEFMessage.Type.UNREGISTER_SERVICE:
            await self._unregister_service(
                sender, request_id,
                cast(Description, oef_message.get("service_description")))
        elif oef_type == OEFMessage.Type.UNREGISTER_AGENT:
            await self._unregister_agent(
                sender, request_id,
                cast(Description, oef_message.get("agent_description")))
        elif oef_type == OEFMessage.Type.SEARCH_AGENTS:
            await self._search_agents(sender, request_id,
                                      cast(Query, oef_message.get("query")))
        elif oef_type == OEFMessage.Type.SEARCH_SERVICES:
            await self._search_services(sender, request_id,
                                        cast(Query, oef_message.get("query")))
        else:
            # request not recognized
            pass
예제 #7
0
    def handle_oef_message(self, envelope: Envelope) -> None:
        """
        Handle messages from the oef.

        The oef does not expect a response for any of these messages.

        :param envelope: the OEF message

        :return: None
        """
        logger.debug(
            "[{}]: Handling OEF message. type={}".format(
                self.agent_name, type(envelope)
            )
        )
        assert envelope.protocol_id == "oef"
        msg = OEFSerializer().decode(envelope.message)
        if msg.get("type") == OEFMessage.Type.OEF_ERROR:
            self.on_oef_error(envelope)
        elif msg.get("type") == OEFMessage.Type.DIALOGUE_ERROR:
            self.on_dialogue_error(envelope)
        else:
            logger.warning(
                "[{}]: OEF Message type not recognized.".format(self.agent_name)
            )
예제 #8
0
    def handle_envelope(self, envelope: Envelope) -> None:
        """
        Implement the reaction to an envelope.

        :param envelope: the envelope
        :return: None
        """
        msg = OEFSerializer().decode(envelope.message)
        msg_type = OEFMessage.Type(msg.get("type"))

        if msg_type is OEFMessage.Type.SEARCH_RESULT:
            agents = cast(List[str], msg.get("agents"))
            logger.info("[{}]: found agents={}".format(self.context.agent_name,
                                                       agents))
            for agent in agents:
                msg = FIPAMessage(message_id=STARTING_MESSAGE_ID,
                                  dialogue_id=self.dialogue_id,
                                  performative=FIPAMessage.Performative.CFP,
                                  target=STARTING_TARGET_ID,
                                  query=None)
                self.dialogue_id += 1
                self.context.outbox.put_message(
                    to=agent,
                    sender=self.context.agent_public_key,
                    protocol_id=FIPAMessage.protocol_id,
                    message=FIPASerializer().encode(msg))
예제 #9
0
    def _unregister_service(self) -> None:
        """
        Unregister service from OEF Service Directory.

        :return: None
        """
        registration = cast(Registration, self.context.registration)

        if registration.registered_goods_demanded_description is not None:
            oef_msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                                 id=registration.get_next_id(),
                                 service_description=registration.
                                 registered_goods_demanded_description,
                                 service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))
            registration.registered_goods_demanded_description = None

        if registration.registered_goods_supplied_description is not None:
            oef_msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE,
                                 id=registration.get_next_id(),
                                 service_description=registration.
                                 registered_goods_supplied_description,
                                 service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))
            registration.registered_goods_supplied_description = None
예제 #10
0
    def _search_services(self) -> None:
        """
        Search on OEF Service Directory.

        In particular, search
            - for sellers and their supply, or
            - for buyers and their demand, or
            - for both.

        :return: None
        """
        strategy = cast(Strategy, self.context.strategy)
        search = cast(Search, self.context.search)

        if strategy.is_searching_for_sellers:
            query = strategy.get_own_services_query(
                is_searching_for_sellers=True)
            if query is None:
                logger.warning(
                    "[{}]: Not searching the OEF for sellers because the agent demands no goods."
                    .format(self.context.agent_name))
                return None
            else:
                search_id = search.get_next_id(is_searching_for_sellers=True)
                logger.info(
                    "[{}]: Searching for sellers which match the demand of the agent, search_id={}."
                    .format(self.context.agent_name, search_id))
                oef_msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES,
                                     id=search_id,
                                     query=query)
                self.context.outbox.put_message(
                    to=DEFAULT_OEF,
                    sender=self.context.agent_public_key,
                    protocol_id=OEFMessage.protocol_id,
                    message=OEFSerializer().encode(oef_msg))

        if strategy.is_searching_for_buyers:
            query = strategy.get_own_services_query(
                is_searching_for_sellers=False)
            if query is None:
                logger.warning(
                    "[{}]: Not searching the OEF for buyers because the agent supplies no goods."
                    .format(self.context.agent_name))
                return None
            else:
                search_id = search.get_next_id(is_searching_for_sellers=False)
                logger.info(
                    "[{}]: Searching for buyers which match the supply of the agent, search_id={}."
                    .format(self.context.agent_name, search_id))
                oef_msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES,
                                     id=search_id,
                                     query=query)
                self.context.outbox.put_message(
                    to=DEFAULT_OEF,
                    sender=self.context.agent_public_key,
                    protocol_id=OEFMessage.protocol_id,
                    message=OEFSerializer().encode(oef_msg))
예제 #11
0
    def test_on_dialogue_error(self):
        """Test the dialogue error."""
        oef_connection = self.multiplexer1.connections[0]
        oef_channel = oef_connection.channel

        oef_channel.on_dialogue_error(answer_id=0, dialogue_id=0, origin="me")
        envelope = self.multiplexer1.get(block=True, timeout=5.0)
        dec_msg = OEFSerializer().decode(envelope.message)
        assert dec_msg.get(
            "type"
        ) is OEFMessage.Type.DIALOGUE_ERROR, "It should be a dialogue error"
예제 #12
0
    def test_on_oef_error(self):
        """Test the oef error."""
        oef_connection = self.multiplexer1.connections[0]
        oef_channel = oef_connection.channel

        oef_channel.on_oef_error(answer_id=0,
                                 operation=OEFErrorOperation.SEARCH_AGENTS)
        envelope = self.multiplexer1.get(block=True, timeout=5.0)
        dec_msg = OEFSerializer().decode(envelope.message)
        assert dec_msg.get(
            "type"
        ) is OEFMessage.Type.OEF_ERROR, "It should be an error message"
예제 #13
0
    def on_oef_error(self, envelope: Envelope) -> None:
        """
        Handle an OEF error message.

        :param envelope: the oef error

        :return: None
        """
        oef_error = OEFSerializer().decode(envelope.message)
        logger.error(
            "[{}]: Received OEF error: answer_id={}, operation={}".format(
                self.agent_name, oef_error.get("id"),
                oef_error.get("operation")))
예제 #14
0
    def _register_service(self) -> None:
        """
        Register to the OEF Service Directory.

        In particular, register
            - as a seller, listing the goods supplied, or
            - as a buyer, listing the goods demanded, or
            - as both.

        :return: None
        """
        strategy = cast(Strategy, self.context.strategy)
        transactions = cast(Transactions, self.context.transactions)
        if strategy.is_registering_as_seller:
            logger.debug(
                "[{}]: Updating service directory as seller with goods supplied."
                .format(self.context.agent_name))
            ownership_state_after_locks = transactions.ownership_state_after_locks(
                self.context.ownership_state, is_seller=True)
            goods_supplied_description = strategy.get_own_service_description(
                ownership_state_after_locks, is_supply=True)
            self._registered_goods_supplied_description = goods_supplied_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=goods_supplied_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
        if strategy.is_registering_as_buyer:
            logger.debug(
                "[{}]: Updating service directory as buyer with goods demanded."
                .format(self.context.agent_name))
            ownership_state_after_locks = transactions.ownership_state_after_locks(
                self.context.ownership_state, is_seller=False)
            goods_demanded_description = strategy.get_own_service_description(
                ownership_state_after_locks, is_supply=False)
            self._registered_goods_demanded_description = goods_demanded_description
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                             id=DEFAULT_MSG_ID,
                             service_description=goods_demanded_description,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)
예제 #15
0
    def on_dialogue_error(self, envelope: Envelope) -> None:
        """
        Handle a dialogue error message.

        :param envelope: the dialogue error message

        :return: None
        """
        dialogue_error = OEFSerializer().decode(envelope.message)
        logger.error(
            "[{}]: Received Dialogue error: answer_id={}, dialogue_id={}, origin={}"
            .format(self.agent_name, dialogue_error.get("id"),
                    dialogue_error.get("dialogue_id"),
                    dialogue_error.get("origin")))
예제 #16
0
    def test_search_agent(self):
        """Test the registered agents, we will not find any."""
        data_model = DataModel("foobar", attributes=[])
        agent_description = Description({"foo": 1, "bar": "baz"}, data_model=data_model)
        query = Query(constraints=[], model=data_model)

        # Register an agent
        msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_AGENT, id=0, agent_description=agent_description,
                         agent_id="Test_agent")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        time.sleep(0.1)

        # Search for the register agent
        msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_AGENTS, id=0, query=query)
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_2, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer2.put(envelope)

        # check the result
        response_envelope = self.multiplexer2.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert len(result.get("agents")) == 1, "There are registered agents!"

        # Send unregister message.
        msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_AGENT, id=0, agent_description=agent_description,
                         agent_id="Test_agent")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        time.sleep(0.1)

        # Trigger error message.
        msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_AGENT, id=0, agent_description=agent_description,
                         agent_id="Unknown_Agent")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        # check the result
        response_envelope = self.multiplexer1.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert result.get("type") == OEFMessage.Type.OEF_ERROR
예제 #17
0
    def _register_service(self) -> None:
        """
        Register to the OEF Service Directory.

        In particular, register
            - as a seller, listing the goods supplied, or
            - as a buyer, listing the goods demanded, or
            - as both.

        :return: None
        """
        registration = cast(Registration, self.context.registration)
        strategy = cast(Strategy, self.context.strategy)

        if strategy.is_registering_as_seller:
            logger.debug(
                "[{}]: Updating service directory as seller with goods supplied."
                .format(self.context.agent_name))
            goods_supplied_description = strategy.get_own_service_description(
                is_supply=True)
            registration.registered_goods_supplied_description = goods_supplied_description
            oef_msg = OEFMessage(
                oef_type=OEFMessage.Type.REGISTER_SERVICE,
                id=registration.get_next_id(),
                service_description=goods_supplied_description,
                service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))

        if strategy.is_registering_as_buyer:
            logger.debug(
                "[{}]: Updating service directory as buyer with goods demanded."
                .format(self.context.agent_name))
            goods_demanded_description = strategy.get_own_service_description(
                is_supply=False)
            registration.registered_goods_demanded_description = goods_demanded_description
            oef_msg = OEFMessage(
                oef_type=OEFMessage.Type.REGISTER_SERVICE,
                id=registration.get_next_id(),
                service_description=goods_demanded_description,
                service_id="")
            self.context.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.context.agent_public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(oef_msg))
예제 #18
0
def test_oef_message_OEFError():
    """Tests the OEF_ERROR type of message."""
    msg = OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR,
                     id=0,
                     operation=OEFMessage.OEFErrorOperation.SEARCH_AGENTS)

    assert OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR, id=0,
                      operation=OEFMessage.OEFErrorOperation.SEARCH_AGENTS),\
        "Expects an oef message Error!"
    msg_bytes = OEFSerializer().encode(msg)
    assert len(msg_bytes) > 0,\
        "Expects the length of bytes not to be Empty"
    deserialized_msg = OEFSerializer().decode(msg_bytes)
    assert msg == deserialized_msg,\
        "Expected the deserialized_msg to me equals to msg"
예제 #19
0
    async def _search_services(self, public_key: str, search_id: int,
                               query: Query) -> None:
        """
        Search the agents in the local Service Directory, and send back the result.

        This is actually a dummy search, it will return all the registered agents with the specified data model.
        If the data model is not specified, it will return all the agents.

        :param public_key: the source of the search request.
        :param search_id: the search identifier associated with the search request.
        :param query: the query that constitutes the search.
        :return: None
        """
        result = []  # type: List[str]
        if query.model is None:
            result = list(set(self.services.keys()))
        else:
            for agent_public_key, descriptions in self.services.items():
                for description in descriptions:
                    if description.data_model == query.model:
                        result.append(agent_public_key)

        msg = OEFMessage(oef_type=OEFMessage.Type.SEARCH_RESULT,
                         id=search_id,
                         agents=sorted(set(result)))
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=public_key,
                            sender=DEFAULT_OEF,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        await self._send(envelope)
예제 #20
0
    async def _unregister_agent(self, public_key: str, msg_id: int,
                                agent_description: Description) -> None:
        """
        Unregister an agent.

        :param agent_description:
        :param public_key: the public key of the service agent to be unregistered.
        :param msg_id: the message id of the request.
        :return: None
        """
        async with self._lock:
            if public_key not in self.agents:
                msg = OEFMessage(
                    oef_type=OEFMessage.Type.OEF_ERROR,
                    id=msg_id,
                    operation=OEFMessage.OEFErrorOperation.UNREGISTER_AGENT)
                msg_bytes = OEFSerializer().encode(msg)
                envelope = Envelope(to=public_key,
                                    sender=DEFAULT_OEF,
                                    protocol_id=OEFMessage.protocol_id,
                                    message=msg_bytes)
                await self._send(envelope)
            else:
                self.agents[public_key].remove(agent_description)
                if len(self.agents[public_key]) == 0:
                    self.agents.pop(public_key)
예제 #21
0
    def on_oef_error(self, answer_id: int,
                     operation: oef.messages.OEFErrorOperation) -> None:
        """
        On oef error event handler.

        :param answer_id: the answer id.
        :param operation: the error operation.
        :return: None
        """
        assert self.in_queue is not None
        assert self.loop is not None
        try:
            operation = OEFMessage.OEFErrorOperation(operation)
        except ValueError:
            operation = OEFMessage.OEFErrorOperation.OTHER

        msg = OEFMessage(oef_type=OEFMessage.Type.OEF_ERROR,
                         id=answer_id,
                         operation=operation)
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=self.public_key,
                            sender=DEFAULT_OEF,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        asyncio.run_coroutine_threadsafe(self.in_queue.put(envelope),
                                         self.loop).result()
예제 #22
0
    def setup_class(cls):
        """Set up the test."""
        cls.node = LocalNode()

        cls.public_key_1 = "mailbox1"
        cls.mailbox1 = MailBox(OEFLocalConnection(cls.public_key_1, cls.node))

        cls.mailbox1.connect()

        # register a service.
        request_id = 1
        service_id = ''
        cls.data_model = DataModel("foobar", attributes=[])
        service_description = Description({
            "foo": 1,
            "bar": "baz"
        },
                                          data_model=cls.data_model)
        register_service_request = OEFMessage(
            oef_type=OEFMessage.Type.REGISTER_SERVICE,
            id=request_id,
            service_description=service_description,
            service_id=service_id)
        msg_bytes = OEFSerializer().encode(register_service_request)
        envelope = Envelope(to=DEFAULT_OEF,
                            sender=cls.public_key_1,
                            protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        cls.mailbox1.send(envelope)
예제 #23
0
    def search_for_tac(self) -> None:
        """
        Search for active TAC Controller.

        We assume that the controller is registered as a service with the 'tac' data model
        and with an attribute version = expected_version_id.

        :return: None
        """
        query = Query(
            [Constraint("version", GtEq(self.game_instance.expected_version_id))]
        )
        search_id = self.game_instance.search.get_next_id()
        self.game_instance.search.ids_for_tac.add(search_id)

        msg = OEFMessage(
            oef_type=OEFMessage.Type.SEARCH_SERVICES, id=search_id, query=query
        )
        msg_bytes = OEFSerializer().encode(msg)
        self.mailbox.outbox.put_message(
            to=DEFAULT_OEF,
            sender=self.crypto.public_key,
            protocol_id=OEFMessage.protocol_id,
            message=msg_bytes,
        )
예제 #24
0
        def test_register_service(self):
            """Test that a register service request works correctly."""
            foo_datamodel = DataModel(
                "foo", [Attribute("bar", int, True, "A bar attribute.")])
            desc = Description({"bar": 1}, data_model=foo_datamodel)
            msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                             id=1,
                             service_description=desc,
                             service_id="")
            msg_bytes = OEFSerializer().encode(msg)
            self.mailbox1.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto1.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=msg_bytes)

            search_request = OEFMessage(
                oef_type=OEFMessage.Type.SEARCH_SERVICES,
                id=2,
                query=Query([Constraint("bar", ConstraintType("==", 1))],
                            model=foo_datamodel))
            self.mailbox1.outbox.put_message(
                to=DEFAULT_OEF,
                sender=self.crypto1.public_key,
                protocol_id=OEFMessage.protocol_id,
                message=OEFSerializer().encode(search_request))
            envelope = self.mailbox1.inbox.get(block=True, timeout=5.0)
            search_result = OEFSerializer().decode(envelope.message)
            assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
            assert search_result.get("id") == 2
            assert search_result.get("agents") == [self.crypto1.public_key]
예제 #25
0
    def handle_envelope(self, envelope: Envelope) -> None:
        """
        Implement the reaction to an envelope.

        :param envelope: the envelope
        :return: None
        """
        oef_message = OEFSerializer().decode(envelope.message)
        oef_type = oef_message.get("type")

        logger.debug("[{}]: Handling OEF message. type={}".format(self.context.agent_name, oef_type))
        oef_message = cast(OEFMessage, oef_message)
        if oef_type == OEFMessage.Type.SEARCH_RESULT:
            self._on_search_result(oef_message)
        elif oef_type == OEFMessage.Type.OEF_ERROR:
            self._on_oef_error(oef_message)
        elif oef_type == OEFMessage.Type.DIALOGUE_ERROR:
            self._on_dialogue_error(oef_message)
예제 #26
0
    def setup_class(cls):
        """Set up the test."""
        cls.node = LocalNode()
        cls.node.start()

        cls.public_key_1 = "multiplexer1"
        cls.public_key_2 = "multiplexer2"
        cls.multiplexer1 = Multiplexer([OEFLocalConnection(cls.public_key_1, cls.node)])
        cls.multiplexer2 = Multiplexer([OEFLocalConnection(cls.public_key_2, cls.node)])
        cls.multiplexer1.connect()
        cls.multiplexer2.connect()

        # register 'multiplexer1' as a service 'foobar'.
        request_id = 1
        service_id = ''
        cls.data_model_foobar = DataModel("foobar", attributes=[])
        service_description = Description({"foo": 1, "bar": "baz"}, data_model=cls.data_model_foobar)
        register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id,
                                              service_description=service_description, service_id=service_id)
        msg_bytes = OEFSerializer().encode(register_service_request)
        envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_1, protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        cls.multiplexer1.put(envelope)

        time.sleep(1.0)

        # register 'multiplexer2' as a service 'barfoo'.
        cls.data_model_barfoo = DataModel("barfoo", attributes=[])
        service_description = Description({"foo": 1, "bar": "baz"}, data_model=cls.data_model_barfoo)
        register_service_request = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE, id=request_id,
                                              service_description=service_description, service_id=service_id)
        msg_bytes = OEFSerializer().encode(register_service_request)
        envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_2, protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        cls.multiplexer2.put(envelope)

        # unregister multiplexer1
        data_model = DataModel("foobar", attributes=[])
        service_description = Description({"foo": 1, "bar": "baz"}, data_model=data_model)
        msg = OEFMessage(oef_type=OEFMessage.Type.UNREGISTER_SERVICE, id=0, service_description=service_description,
                         service_id="Test_service")
        msg_bytes = OEFSerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=cls.public_key_1, protocol_id=OEFMessage.protocol_id, message=msg_bytes)
        cls.multiplexer1.put(envelope)
예제 #27
0
def test_oef_serialization():
    """Testing the serialization of the OEF."""
    foo_datamodel = DataModel(
        "foo", [Attribute("bar", int, True, "A bar attribute.")])
    desc = Description({"bar": 1}, data_model=foo_datamodel)
    msg = OEFMessage(oef_type=OEFMessage.Type.REGISTER_SERVICE,
                     id=1,
                     service_description=desc,
                     service_id="")
    msg_bytes = OEFSerializer().encode(msg)
    assert len(msg_bytes) > 0
예제 #28
0
    def test_not_empty_search_result(self):
        """Test that the search result contains one entry after a successful registration."""
        request_id = 1
        query = Query(constraints=[], model=self.data_model)

        # build and send the request
        search_services_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES, id=request_id, query=query)
        msg_bytes = OEFSerializer().encode(search_services_request)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        self.multiplexer.put(envelope)

        # check the result
        response_envelope = self.multiplexer.get(block=True, timeout=2.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.to == self.public_key_1
        assert response_envelope.sender == DEFAULT_OEF
        search_result = OEFSerializer().decode(response_envelope.message)
        assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert search_result.get("agents") == [self.public_key_1]
예제 #29
0
    def test_filtered_search_result(self):
        """Test that the search result contains only the entries matching the query."""
        request_id = 1
        query = Query(constraints=[], model=self.data_model_barfoo)

        # build and send the request
        search_services_request = OEFMessage(oef_type=OEFMessage.Type.SEARCH_SERVICES, id=request_id, query=query)
        msg_bytes = OEFSerializer().encode(search_services_request)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=OEFMessage.protocol_id,
                            message=msg_bytes)
        self.multiplexer1.put(envelope)

        # check the result
        response_envelope = InBox(self.multiplexer1).get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.to == self.public_key_1
        assert response_envelope.sender == DEFAULT_OEF
        search_result = OEFSerializer().decode(response_envelope.message)
        assert search_result.get("type") == OEFMessage.Type.SEARCH_RESULT
        assert search_result.get("agents") == [self.public_key_2]
예제 #30
0
    async def test_messages(self):
        """Test that at the beginning, the search request returns an empty search result."""
        msg = FIPAMessage((str(0), ''), 0, 0, FIPAMessage.Performative.CFP, query=None)
        msg_bytes = FIPASerializer().encode(msg)
        envelope = Envelope(to=DEFAULT_OEF, sender=self.public_key_1, protocol_id=FIPAMessage.protocol_id, message=msg_bytes)
        with pytest.raises(AEAConnectionError):
            await OEFLocalConnection(self.public_key_1, self.node).send(envelope)

        self.multiplexer1.connect()
        msg = FIPAMessage((str(0), str(1)), 0, 0, FIPAMessage.Performative.CFP, query=None)
        msg_bytes = FIPASerializer().encode(msg)
        envelope = Envelope(to="this_public_key_does_not_exist",
                            sender=self.public_key_1, protocol_id=FIPAMessage.protocol_id, message=msg_bytes)
        self.multiplexer1.put(envelope)

        # check the result
        response_envelope = self.multiplexer1.get(block=True, timeout=5.0)
        assert response_envelope.protocol_id == OEFMessage.protocol_id
        assert response_envelope.sender == DEFAULT_OEF
        result = OEFSerializer().decode(response_envelope.message)
        assert result.get("type") == OEFMessage.Type.DIALOGUE_ERROR