8000 gh-98388: add tests for happy eyeballs (#136368) · python/cpython@0240ef4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0240ef4

Browse files
gh-98388: add tests for happy eyeballs (#136368)
1 parent fe187fa commit 0240ef4

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)
0