Skip to content

Commit 9b5f9c8

Browse files
committed
Add test for gh-118950
1 parent 0732b89 commit 9b5f9c8

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

Lib/test/test_asyncio/test_sslproto.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from asyncio import log
1717
from asyncio import protocols
1818
from asyncio import sslproto
19+
from asyncio import selector_events
1920
from test.test_asyncio import utils as test_utils
2021
from test.test_asyncio import functional as func_tests
2122

@@ -109,6 +110,48 @@ def test_connection_lost(self):
109110
test_utils.run_briefly(self.loop)
110111
self.assertIsInstance(waiter.exception(), ConnectionAbortedError)
111112

113+
def test_connection_lost_when_busy(self):
114+
sock = mock.Mock()
115+
sock.fileno = mock.Mock(return_value=12345)
116+
sock.send = mock.Mock(side_effect=BrokenPipeError)
117+
118+
# construct StreamWriter chain that contains loop dependant logic this emulates that
119+
# _make_ssl_transport() does in BaseSelectorEventLoop
120+
reader = asyncio.StreamReader(limit=2 ** 16, loop=self.loop)
121+
protocol = asyncio.StreamReaderProtocol(reader, loop=self.loop)
122+
ssl_proto = self.ssl_protocol(proto=protocol)
123+
124+
# emulate reading decompressed data
125+
sslobj = mock.Mock()
126+
sslobj.read.side_effect = ssl.SSLWantReadError
127+
sslobj.write.side_effect = ssl.SSLWantReadError
128+
ssl_proto._sslobj = sslobj
129+
130+
# emulate outgoing data
131+
data = b'An interesting message'
132+
133+
outgoing = mock.Mock()
134+
outgoing.read = mock.Mock(return_value=data)
135+
outgoing.pending = len(data)
136+
ssl_proto._outgoing = outgoing
137+
138+
# use correct socket transport to initialize the SSLProtocol
139+
selector_events._SelectorSocketTransport(self.loop, sock, ssl_proto)
140+
transport = ssl_proto._app_transport
141+
writer = asyncio.StreamWriter(transport, protocol, reader, self.loop)
142+
143+
# Write data to the transport n times in a task that blocks the
144+
# asyncio event loop from a user perspective.
145+
async def _write_loop(n):
146+
for i in range(n):
147+
writer.write(data)
148+
await writer.drain()
149+
150+
# The test is successful if we raise the error the next time
151+
# we try to write to the transport.
152+
with self.assertRaises(ConnectionResetError):
153+
self.loop.run_until_complete(_write_loop(2))
154+
112155
def test_close_during_handshake(self):
113156
# bpo-29743 Closing transport during handshake process leaks socket
114157
waiter = self.loop.create_future()

0 commit comments

Comments
 (0)