summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_asyncio/test_events.py
diff options
context:
space:
mode:
authorErik Soma <stillusingirc@gmail.com>2024-03-23 15:39:35 (GMT)
committerGitHub <noreply@github.com>2024-03-23 15:39:35 (GMT)
commitf11d0d8be8af28e1368c3c7c116218cf65ddf93e (patch)
tree0bbe9b536a17f8417cda142808be37adb113b217 /Lib/test/test_asyncio/test_events.py
parent9967b568edd2e35b0415c14c7242f3ca2c0dc03d (diff)
downloadcpython-f11d0d8be8af28e1368c3c7c116218cf65ddf93e.zip
cpython-f11d0d8be8af28e1368c3c7c116218cf65ddf93e.tar.gz
cpython-f11d0d8be8af28e1368c3c7c116218cf65ddf93e.tar.bz2
gh-91227: Ignore ERROR_PORT_UNREACHABLE in proactor recvfrom() (#32011)
Diffstat (limited to 'Lib/test/test_asyncio/test_events.py')
-rw-r--r--Lib/test/test_asyncio/test_events.py74
1 files changed, 74 insertions, 0 deletions
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index ae0bff0..88c85a3 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -1378,6 +1378,80 @@ class EventLoopTestsMixin:
tr.close()
self.loop.run_until_complete(pr.done)
+ def test_datagram_send_to_non_listening_address(self):
+ # see:
+ # https://github.com/python/cpython/issues/91227
+ # https://github.com/python/cpython/issues/88906
+ # https://bugs.python.org/issue47071
+ # https://bugs.python.org/issue44743
+ # The Proactor event loop would fail to receive datagram messages after
+ # sending a message to an address that wasn't listening.
+ loop = self.loop
+
+ class Protocol(asyncio.DatagramProtocol):
+
+ _received_datagram = None
+
+ def datagram_received(self, data, addr):
+ self._received_datagram.set_result(data)
+
+ async def wait_for_datagram_received(self):
+ self._received_datagram = loop.create_future()
+ result = await asyncio.wait_for(self._received_datagram, 10)
+ self._received_datagram = None
+ return result
+
+ def create_socket():
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ sock.setblocking(False)
+ sock.bind(('127.0.0.1', 0))
+ return sock
+
+ socket_1 = create_socket()
+ transport_1, protocol_1 = loop.run_until_complete(
+ loop.create_datagram_endpoint(Protocol, sock=socket_1)
+ )
+ addr_1 = socket_1.getsockname()
+
+ socket_2 = create_socket()
+ transport_2, protocol_2 = loop.run_until_complete(
+ loop.create_datagram_endpoint(Protocol, sock=socket_2)
+ )
+ addr_2 = socket_2.getsockname()
+
+ # creating and immediately closing this to try to get an address that
+ # is not listening
+ socket_3 = create_socket()
+ transport_3, protocol_3 = loop.run_until_complete(
+ loop.create_datagram_endpoint(Protocol, sock=socket_3)
+ )
+ addr_3 = socket_3.getsockname()
+ transport_3.abort()
+
+ transport_1.sendto(b'a', addr=addr_2)
+ self.assertEqual(loop.run_until_complete(
+ protocol_2.wait_for_datagram_received()
+ ), b'a')
+
+ transport_2.sendto(b'b', addr=addr_1)
+ self.assertEqual(loop.run_until_complete(
+ protocol_1.wait_for_datagram_received()
+ ), b'b')
+
+ # this should send to an address that isn't listening
+ transport_1.sendto(b'c', addr=addr_3)
+ loop.run_until_complete(asyncio.sleep(0))
+
+ # transport 1 should still be able to receive messages after sending to
+ # an address that wasn't listening
+ transport_2.sendto(b'd', addr=addr_1)
+ self.assertEqual(loop.run_until_complete(
+ protocol_1.wait_for_datagram_received()
+ ), b'd')
+
+ transport_1.close()
+ transport_2.close()
+
def test_internal_fds(self):
loop = self.create_event_loop()
if not isinstance(loop, selector_events.BaseSelectorEventLoop):