Exemplo n.º 1
0
    def to_envelope_and_set_id(
        self,
        connection_id: PublicId,
        agent_address: str,
        dialogues: HttpDialogues,
    ) -> Envelope:
        """
        Process incoming API request by packaging into Envelope and sending it in-queue.

        :param connection_id: id of the connection
        :param agent_address: agent's address
        :param dialogue_reference: new dialog refernece for envelope

        :return: envelope
        """
        url = (self.full_url_pattern if self.parameters.query == {} else
               self.full_url_pattern + "?" + urlencode(self.parameters.query))
        uri = URI(self.full_url_pattern)
        context = EnvelopeContext(connection_id=connection_id, uri=uri)
        http_message = HttpMessage(
            dialogue_reference=dialogues.new_self_initiated_dialogue_reference(
            ),
            performative=HttpMessage.Performative.REQUEST,
            method=self.method,
            url=url,
            headers=self.parameters.header,
            bodyy=self.body if self.body is not None else b"",
            version="",
        )
        http_message.counterparty = agent_address
        dialogue = cast(Optional[HttpDialogue], dialogues.update(http_message))
        assert dialogue is not None, "Could not create dialogue for message={}".format(
            http_message)
        self.id = dialogue.incomplete_dialogue_label
        envelope = Envelope(
            to=agent_address,
            sender=str(connection_id),
            protocol_id=http_message.protocol_id,
            context=context,
            message=http_message,
        )
        return envelope
class TestClientServer:
    """Client-Server end-to-end test."""

    def setup_server(self):
        """Set up server connection."""
        self.server_agent_address = "server_agent_address"
        self.server_agent_identity = Identity(
            "agent running server", address=self.server_agent_address
        )
        self.host = get_host()
        self.port = get_unused_tcp_port()
        self.connection_id = HTTPServerConnection.connection_id
        self.protocol_id = PublicId.from_str("fetchai/http:0.4.0")

        self.configuration = ConnectionConfig(
            host=self.host,
            port=self.port,
            api_spec_path=None,  # do not filter on API spec
            connection_id=HTTPServerConnection.connection_id,
            restricted_to_protocols=set([self.protocol_id]),
        )
        self.server = HTTPServerConnection(
            configuration=self.configuration, identity=self.server_agent_identity,
        )
        self.loop = asyncio.get_event_loop()
        self.loop.run_until_complete(self.server.connect())
        # skill side dialogues
        self._server_dialogues = HttpDialogues(self.server_agent_address)

    def setup_client(self):
        """Set up client connection."""
        self.client_agent_address = "client_agent_address"
        self.client_agent_identity = Identity(
            "agent running client", address=self.client_agent_address
        )
        configuration = ConnectionConfig(
            host="localost",
            port="8888",  # TODO: remove host/port for client?
            connection_id=HTTPClientConnection.connection_id,
        )
        self.client = HTTPClientConnection(
            configuration=configuration, identity=self.client_agent_identity
        )
        self.client.loop = asyncio.get_event_loop()
        self.loop.run_until_complete(self.client.connect())
        # skill side dialogues
        self._client_dialogues = HttpDialogues(self.client_agent_address)

    def setup(self):
        """Set up test case."""
        self.setup_server()
        self.setup_client()

    def _make_request(
        self, path: str, method: str = "get", headers: str = "", bodyy: bytes = b""
    ) -> Envelope:
        """Make request envelope."""
        request_http_message = HttpMessage(
            dialogue_reference=self._client_dialogues.new_self_initiated_dialogue_reference(),
            target=0,
            message_id=1,
            performative=HttpMessage.Performative.REQUEST,
            method=method,
            url=f"http://{self.host}:{self.port}{path}",
            headers="",
            version="",
            bodyy=b"",
        )
        request_http_message.counterparty = str(HTTPClientConnection.connection_id)
        assert self._client_dialogues.update(request_http_message) is not None
        request_envelope = Envelope(
            to=request_http_message.counterparty,
            sender=request_http_message.sender,
            protocol_id=request_http_message.protocol_id,
            message=request_http_message,
        )
        return request_envelope

    def _make_response(
        self, request_envelope: Envelope, status_code: int = 200, status_text: str = ""
    ) -> Envelope:
        """Make response envelope."""
        incoming_message = cast(HttpMessage, request_envelope.message)
        incoming_message.is_incoming = True
        incoming_message.counterparty = str(HTTPServerConnection.connection_id)
        dialogue = self._server_dialogues.update(incoming_message)
        assert dialogue is not None
        message = HttpMessage(
            performative=HttpMessage.Performative.RESPONSE,
            dialogue_reference=dialogue.dialogue_label.dialogue_reference,
            target=incoming_message.message_id,
            message_id=incoming_message.message_id + 1,
            version=incoming_message.version,
            headers=incoming_message.headers,
            status_code=status_code,
            status_text=status_text,
            bodyy=incoming_message.bodyy,
        )
        message.counterparty = incoming_message.counterparty
        assert dialogue.update(message) is not None
        response_envelope = Envelope(
            to=message.counterparty,
            sender=message.sender,
            protocol_id=message.protocol_id,
            context=request_envelope.context,
            message=message,
        )
        return response_envelope

    @pytest.mark.asyncio
    async def test_post_with_payload(self):
        """Test client and server with post request."""
        initial_request = self._make_request("/test", "POST", bodyy=b"1234567890")
        await self.client.send(initial_request)
        request = await asyncio.wait_for(self.server.receive(), timeout=5)
        # this is "inside" the server agent
        initial_response = self._make_response(request)
        await self.server.send(initial_response)
        response = await asyncio.wait_for(self.client.receive(), timeout=5)
        assert (
            cast(HttpMessage, initial_request.message).bodyy
            == cast(HttpMessage, response.message).bodyy
        )
        assert (
            initial_request.message.dialogue_reference[0]
            == response.message.dialogue_reference[0]
        )

    def teardown(self):
        """Tear down testcase."""
        self.loop.run_until_complete(self.client.disconnect())
        self.loop.run_until_complete(self.server.disconnect())