Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests TCP Service and TCP Client fail #97

Closed
ogonbat opened this issue Mar 12, 2021 · 1 comment
Closed

Tests TCP Service and TCP Client fail #97

ogonbat opened this issue Mar 12, 2021 · 1 comment

Comments

@ogonbat
Copy link

ogonbat commented Mar 12, 2021

Hi All

i have the following client TCP

    class MinosBaseClient:
        __slots__ = 'reader', 'writer', 'futures', 'loop', 'reader_task', '_serial'

       HEADER = struct.Struct(">I")

       def __init__(self, reader: asyncio.StreamReader,
                 writer: asyncio.StreamWriter,
                 loop: asyncio.AbstractEventLoop = None):
           self.reader = reader
           self.writer = writer
           self.futures = {}
           self._serial = None
           self.loop = loop or asyncio.get_event_loop()
           self.reader_task = self.loop.create_task(self._response_reader())

       async def _response_reader(self):
           try:
               while True:
                   log.debug("MRPC Client: Response Received")
                   body_size = self.HEADER.unpack(
                       await self.reader.readexactly(self.HEADER.size)
                   )[0]
                   log.debug(f"MRPC Client: received data size of {body_size}")
                   response: MinosRPCResponse = MinosResponse.load(
                       await self.reader.readexactly(body_size),
                       MinosRPCResponse)

                   future = self.futures.pop(response.id, None)

                   if future is None:
                       continue

                   future.set_result(response)
           finally:
               while self.futures:
                   _, future = self.futures.popitem()

                   if future.done():
                       continue
                   log.debug("MRPC Client: Set error")
                   future.set_exception(ConnectionAbortedError)

       async def close(self):
           """
           close the connection with the server
           """
           log.debug("Client: Closing connection")
           self.writer.write(self.HEADER.pack(0))
           self.reader_task.cancel()
           await asyncio.gather(self.reader_task, return_exceptions=True)

           self.loop.call_soon(self.writer.close)
           self.writer.write_eof()
           self.writer.close()

       def send_headers(self, path: str):
           """
           Send headers before all
           """
           log.debug("MRPC Client: Send Headers")
           header_request: MinosRPCHeadersRequest = MinosRequest.build(MinosRPCHeadersRequest).addAction(path)
           header_bytes: bytes = header_request.binary
           log.debug("MRCP Client: Send headers with ID: %d", header_request.id)
           self._serial = header_request.id
           self._send_bytes(header_bytes)
           log.debug("MRPC Client: Headers, sent")

       def send_body(self, message: t.Any = None):
           log.debug("MRPC Client: Send Body")
           if message:
               body_request: MinosRPCBodyRequest = MinosRequest.build(MinosRPCBodyRequest).addId(self._serial) \
                .addBody(message)
           else:
               body_request: MinosRPCBodyRequest = MinosRequest.build(MinosRPCBodyRequest).addId(self._serial)
           content_bytes: bytes = body_request.binary
           log.debug("MRCP Client: Send Body with ID: %d", body_request.id)
           self._send_bytes(content_bytes)
           log.debug("Body Sent")

       def send_close(self):
        ...

       def _send_bytes(self, data: bytes):
           with io.BytesIO() as f:
               f.write(self.HEADER.pack(len(data)))
               f.write(data)
               self.writer.write(f.getvalue())

       def send(self, path: str, message: t.Any = None, **kwargs):
           self.send_headers(path)
           self.futures[self._serial] = self.loop.create_future()
           self.send_body(message)
           self.send_close()
           return self.futures[self._serial]

Is a lot of code but mainly is the same code used for TCP client in the example folder.

The server service is a bit more complex but i have tested the server and the client outside the pytest environment and work well.

So, i have defined the following test

@pytest.fixture
def config():
    return {
        "controller": "tests.controllers.RootController"
    }

@pytest.fixture
def services(config):
    return [
        MinosRPCServer(address='localhost', port=8900, conf=config)
    ]


@pytest.fixture
async def service_client() -> MinosBaseClient:
    reader, writer = await asyncio.open_connection(
        'localhost', 8900
    )
    client_connector = MinosBaseClient(reader, writer)
    try:
        yield client_connector
    finally:
        await client_connector.close()


async def test_microservice_mrpc_client(service_client):
    result = await service_client.send("without_arg")
    assert True == False

The assert is to have a better veiw of the logs and the error.

when i start the following code i get the following error:

async def test_microservice_mrpc_client(service_client):
>       result = await service_client.send("without_arg")
E       RuntimeError: Task <Task pending name='Task-61' coro=<test_microservice_mrpc_client() running at /Users/xxxx/PycharmProjects/minos_microservice_test/venv/lib/python3.9/site-packages/aiomisc_pytest/pytest_plugin.py:520> cb=[run_until_complete.<locals>.done_cb()]> got Future <Future pending> attached to a different loop

Have something that is wrong in my code, because i have reviewed everithing and seems that all is fine.

thanks in advance for your help

@mosquito
Copy link
Collaborator

mosquito commented Mar 15, 2021

Some object was created before loop fixture was creates the event loop instance. Please try to set pytest mark forbid_get_event_loop for your test cases. That's no solution but might spot the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants