Skip to content

Commit

Permalink
bpo-30064: Fix slow asyncio sock test (pythonGH-20868)
Browse files Browse the repository at this point in the history
Using a log2n way to fill a much smaller buffer, and receiving in a cleaner way with EOF.

The failing test was reproducible using the following command thanks to @aeros :

```bash
./python -m test test_asyncio.test_sock_lowlevel --match test_sock_client_racing -j100 -F -v
```

According to test results, we may still need to bump the timeout:

https://github.com/python/cpython/blob/5aad027db9618f22f6fa2274e05dd50f928d2ed7/Lib/test/test_asyncio/test_sock_lowlevel.py#L256-L257
  • Loading branch information
fantix authored Jun 14, 2020
1 parent 5aad027 commit 8f04a84
Showing 1 changed file with 20 additions and 14 deletions.
34 changes: 20 additions & 14 deletions Lib/test/test_asyncio/test_sock_lowlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ async def _basetest_sock_send_racing(self, listener, sock):
listener.listen(1)

# make connection
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024)
sock.setblocking(False)
task = asyncio.create_task(
self.loop.sock_connect(sock, listener.getsockname()))
Expand All @@ -176,30 +177,35 @@ async def _basetest_sock_send_racing(self, listener, sock):
with server:
await task

# fill the buffer
with self.assertRaises(BlockingIOError):
while True:
sock.send(b' ' * 5)
# fill the buffer until sending 5 chars would block
size = 8192
while size >= 4:
with self.assertRaises(BlockingIOError):
while True:
sock.send(b' ' * size)
size = int(size / 2)

# cancel a blocked sock_sendall
task = asyncio.create_task(
self.loop.sock_sendall(sock, b'hello'))
await asyncio.sleep(0)
task.cancel()

# clear the buffer
async def recv_until():
data = b''
while not data:
data = await self.loop.sock_recv(server, 1024)
data = data.strip()
return data
task = asyncio.create_task(recv_until())
# receive everything that is not a space
async def recv_all():
rv = b''
while True:
buf = await self.loop.sock_recv(server, 8192)
if not buf:
return rv
rv += buf.strip()
task = asyncio.create_task(recv_all())

# immediately register another sock_sendall
# immediately make another sock_sendall call
await self.loop.sock_sendall(sock, b'world')
sock.shutdown(socket.SHUT_WR)
data = await task
# ProactorEventLoop could deliver hello
# ProactorEventLoop could deliver hello, so endswith is necessary
self.assertTrue(data.endswith(b'world'))

# After the first connect attempt before the listener is ready,
Expand Down

0 comments on commit 8f04a84

Please sign in to comment.