Skip to content

Commit ae44ec2

Browse files
committed
Add tests for bpo-39951
1 parent 98e113e commit ae44ec2

File tree

1 file changed

+98
-14
lines changed

1 file changed

+98
-14
lines changed

Diff for: tests/test_tcp.py

+98-14
Original file line numberDiff line numberDiff line change
@@ -2608,10 +2608,6 @@ async def client(addr):
26082608
self.loop.run_until_complete(client(srv.addr))
26092609

26102610
def test_remote_shutdown_receives_trailing_data(self):
2611-
if self.implementation == 'asyncio':
2612-
# this is an issue in asyncio
2613-
raise unittest.SkipTest()
2614-
26152611
CHUNK = 1024 * 16
26162612
SIZE = 8
26172613
count = 0
@@ -2676,13 +2672,18 @@ def server(sock):
26762672
data_len += chunk
26772673
except ssl.SSLWantReadError:
26782674
incoming.write(sock.recv(16384))
2675+
if not incoming.pending:
2676+
# EOF received
2677+
break
26792678
except ssl.SSLZeroReturnError:
26802679
break
26812680

26822681
self.assertEqual(data_len, CHUNK * count)
26832682

2684-
# verify that close_notify is received
2685-
sslobj.unwrap()
2683+
if self.implementation == 'uvloop':
2684+
# Verify that close_notify is received. asyncio is currently
2685+
# not guaranteed to send close_notify before dropping off
2686+
sslobj.unwrap()
26862687

26872688
sock.close()
26882689

@@ -2708,11 +2709,12 @@ async def client(addr):
27082709
await asyncio.wait_for(
27092710
asyncio.ensure_future(writer.drain()), 0.5)
27102711
except asyncio.TimeoutError:
2711-
# fill write backlog in a hacky way
2712-
for _ in range(SIZE):
2713-
writer.transport._test__append_write_backlog(
2714-
b'x' * CHUNK)
2715-
count += 1
2712+
# fill write backlog in a hacky way for uvloop
2713+
if self.implementation == 'uvloop':
2714+
for _ in range(SIZE):
2715+
writer.transport._test__append_write_backlog(
2716+
b'x' * CHUNK)
2717+
count += 1
27162718

27172719
data = await reader.read()
27182720
self.assertEqual(data, b'')
@@ -2929,7 +2931,7 @@ def server(sock):
29292931
except ssl.SSLWantReadError:
29302932
if outgoing.pending:
29312933
sock.send(outgoing.read())
2932-
# incoming.write(sock.recv(16384))
2934+
incoming.write(sock.recv(16384))
29332935
else:
29342936
if outgoing.pending:
29352937
sock.send(outgoing.read())
@@ -2963,12 +2965,94 @@ async def client(addr):
29632965
tr.pause_reading()
29642966
tr.close()
29652967

2966-
await eof_recvd
2967-
await conn_lost
2968+
await asyncio.wait_for(eof_recvd, 10)
2969+
await asyncio.wait_for(conn_lost, 10)
29682970

29692971
with self.tcp_server(server) as srv:
29702972
loop.run_until_complete(client(srv.addr))
29712973

2974+
def test_bpo_39951_discard_trailing_data(self):
2975+
sslctx = self._create_server_ssl_context(self.ONLYCERT, self.ONLYKEY)
2976+
client_sslctx = self._create_client_ssl_context()
2977+
future = None
2978+
close_notify = threading.Lock()
2979+
2980+
def server(sock):
2981+
incoming = ssl.MemoryBIO()
2982+
outgoing = ssl.MemoryBIO()
2983+
sslobj = sslctx.wrap_bio(incoming, outgoing, server_side=True)
2984+
2985+
while True:
2986+
try:
2987+
sslobj.do_handshake()
2988+
except ssl.SSLWantReadError:
2989+
if outgoing.pending:
2990+
sock.send(outgoing.read())
2991+
incoming.write(sock.recv(16384))
2992+
else:
2993+
if outgoing.pending:
2994+
sock.send(outgoing.read())
2995+
break
2996+
2997+
while True:
2998+
try:
2999+
data = sslobj.read(4)
3000+
except ssl.SSLWantReadError:
3001+
incoming.write(sock.recv(16384))
3002+
else:
3003+
break
3004+
3005+
self.assertEqual(data, b'ping')
3006+
sslobj.write(b'pong')
3007+
sock.send(outgoing.read())
3008+
3009+
with close_notify:
3010+
sslobj.write(b'trailing')
3011+
sock.send(outgoing.read())
3012+
time.sleep(0.5) # allow time for the client to receive
3013+
3014+
incoming.write(sock.recv(16384))
3015+
sslobj.unwrap()
3016+
sock.send(outgoing.read())
3017+
sock.close()
3018+
3019+
async def client(addr):
3020+
nonlocal future
3021+
future = self.loop.create_future()
3022+
3023+
with close_notify:
3024+
reader, writer = await asyncio.open_connection(
3025+
*addr,
3026+
ssl=client_sslctx,
3027+
server_hostname='')
3028+
writer.write(b'ping')
3029+
data = await reader.readexactly(4)
3030+
self.assertEqual(data, b'pong')
3031+
3032+
writer.close()
3033+
3034+
try:
3035+
await self.wait_closed(writer)
3036+
except ssl.SSLError as e:
3037+
if self.implementation == 'asyncio' and \
3038+
'application data after close notify' in str(e):
3039+
raise unittest.SkipTest('bpo-39951')
3040+
raise
3041+
await future
3042+
3043+
def run(meth):
3044+
def wrapper(sock):
3045+
try:
3046+
meth(sock)
3047+
except Exception as ex:
3048+
self.loop.call_soon_threadsafe(future.set_exception, ex)
3049+
else:
3050+
self.loop.call_soon_threadsafe(future.set_result, None)
3051+
return wrapper
3052+
3053+
with self.tcp_server(run(server)) as srv:
3054+
self.loop.run_until_complete(client(srv.addr))
3055+
29723056

29733057
class Test_UV_TCPSSL(_TestSSL, tb.UVTestCase):
29743058
pass

0 commit comments

Comments
 (0)