Skip to content

Commit 07c0bd5

Browse files
kumaraditya303Pranjal095
authored andcommitted
pythongh-98388: add tests for happy eyeballs (python#136368)
1 parent 7cdbc49 commit 07c0bd5

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

Lib/test/test_asyncio/test_base_events.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,29 @@ def test_ipaddr_info_no_inet_pton(self, m_socket):
150150
socket.SOCK_STREAM,
151151
socket.IPPROTO_TCP))
152152

153+
def test_interleave_addrinfos(self):
154+
self.maxDiff = None
155+
SIX_A = (socket.AF_INET6, 0, 0, '', ('2001:db8::1', 1))
156+
SIX_B = (socket.AF_INET6, 0, 0, '', ('2001:db8::2', 2))
157+
SIX_C = (socket.AF_INET6, 0, 0, '', ('2001:db8::3', 3))
158+
SIX_D = (socket.AF_INET6, 0, 0, '', ('2001:db8::4', 4))
159+
FOUR_A = (socket.AF_INET, 0, 0, '', ('192.0.2.1', 5))
160+
FOUR_B = (socket.AF_INET, 0, 0, '', ('192.0.2.2', 6))
161+
FOUR_C = (socket.AF_INET, 0, 0, '', ('192.0.2.3', 7))
162+
FOUR_D = (socket.AF_INET, 0, 0, '', ('192.0.2.4', 8))
163+
164+
addrinfos = [SIX_A, SIX_B, SIX_C, FOUR_A, FOUR_B, FOUR_C, FOUR_D, SIX_D]
165+
expected = [SIX_A, FOUR_A, SIX_B, FOUR_B, SIX_C, FOUR_C, SIX_D, FOUR_D]
166+
167+
self.assertEqual(expected, base_events._interleave_addrinfos(addrinfos))
168+
169+
expected_fafc_2 = [SIX_A, SIX_B, FOUR_A, SIX_C, FOUR_B, SIX_D, FOUR_C, FOUR_D]
170+
self.assertEqual(
171+
expected_fafc_2,
172+
base_events._interleave_addrinfos(addrinfos, first_address_family_count=2),
173+
)
174+
175+
153176

154177
class BaseEventLoopTests(test_utils.TestCase):
155178

@@ -1053,6 +1076,71 @@ def test_asyncgen_finalization_by_gc_in_other_thread(self):
10531076
test_utils.run_briefly(self.loop)
10541077
self.assertTrue(status['finalized'])
10551078

1079+
@unittest.skipUnless(socket_helper.IPV6_ENABLED, 'no IPv6 support')
1080+
@patch_socket
1081+
def test_create_connection_happy_eyeballs(self, m_socket):
1082+
1083+
class MyProto(asyncio.Protocol):
1084+
pass
1085+
1086+
async def getaddrinfo(*args, **kw):
1087+
return [(socket.AF_INET6, 0, 0, '', ('2001:db8::1', 1)),
1088+
(socket.AF_INET, 0, 0, '', ('192.0.2.1', 5))]
1089+
1090+
async def sock_connect(sock, address):
1091+
if address[0] == '2001:db8::1':
1092+
await asyncio.sleep(1)
1093+
sock.connect(address)
1094+
1095+
loop = asyncio.new_event_loop()
1096+
loop._add_writer = mock.Mock()
1097+
loop._add_writer = mock.Mock()
1098+
loop._add_reader = mock.Mock()
1099+
loop.getaddrinfo = getaddrinfo
1100+
loop.sock_connect = sock_connect
1101+
1102+
coro = loop.create_connection(MyProto, 'example.com', 80, happy_eyeballs_delay=0.3)
1103+
transport, protocol = loop.run_until_complete(coro)
1104+
try:
1105+
sock = transport._sock
1106+
sock.connect.assert_called_with(('192.0.2.1', 5))
1107+
finally:
1108+
transport.close()
1109+
test_utils.run_briefly(loop) # allow transport to close
1110+
loop.close()
1111+
1112+
@patch_socket
1113+
def test_create_connection_happy_eyeballs_ipv4_only(self, m_socket):
1114+
1115+
class MyProto(asyncio.Protocol):
1116+
pass
1117+
1118+
async def getaddrinfo(*args, **kw):
1119+
return [(socket.AF_INET, 0, 0, '', ('192.0.2.1', 5)),
1120+
(socket.AF_INET, 0, 0, '', ('192.0.2.2', 6))]
1121+
1122+
async def sock_connect(sock, address):
1123+
if address[0] == '192.0.2.1':
1124+
await asyncio.sleep(1)
1125+
sock.connect(address)
1126+
1127+
loop = asyncio.new_event_loop()
1128+
loop._add_writer = mock.Mock()
1129+
loop._add_writer = mock.Mock()
1130+
loop._add_reader = mock.Mock()
1131+
loop.getaddrinfo = getaddrinfo
1132+
loop.sock_connect = sock_connect
1133+
1134+
coro = loop.create_connection(MyProto, 'example.com', 80, happy_eyeballs_delay=0.3)
1135+
transport, protocol = loop.run_until_complete(coro)
1136+
try:
1137+
sock = transport._sock
1138+
sock.connect.assert_called_with(('192.0.2.2', 6))
1139+
finally:
1140+
transport.close()
1141+
test_utils.run_briefly(loop) # allow transport to close
1142+
loop.close()
1143+
10561144

10571145
class MyProto(asyncio.Protocol):
10581146
done = None

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy