@@ -145,6 +145,58 @@ def test_ipaddr_info_no_inet_pton(self, m_socket):
145
145
socket .SOCK_STREAM ,
146
146
socket .IPPROTO_TCP ))
147
147
148
+ def test_interleave_ipaddrs (self ):
149
+ addrinfos = [
150
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::1' , 1 )),
151
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::2' , 2 )),
152
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::3' , 3 )),
153
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::4' , 4 )),
154
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.1' , 5 )),
155
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.2' , 6 )),
156
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.3' , 7 )),
157
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.4' , 8 )),
158
+ ]
159
+
160
+ self .assertEqual (
161
+ [
162
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::1' , 1 )),
163
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.1' , 5 )),
164
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::2' , 2 )),
165
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.2' , 6 )),
166
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::3' , 3 )),
167
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.3' , 7 )),
168
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::4' , 4 )),
169
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.4' , 8 )),
170
+ ],
171
+ base_events ._interleave_addrinfos (addrinfos )
172
+ )
173
+
174
+ def test_interleave_ipaddrs_first_address_family_count (self ):
175
+ addrinfos = [
176
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::1' , 1 )),
177
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::2' , 2 )),
178
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::3' , 3 )),
179
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::4' , 4 )),
180
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.1' , 5 )),
181
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.2' , 6 )),
182
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.3' , 7 )),
183
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.4' , 8 )),
184
+ ]
185
+
186
+ self .assertEqual (
187
+ [
188
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::1' , 1 )),
189
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::2' , 2 )),
190
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.1' , 5 )),
191
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::3' , 3 )),
192
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.2' , 6 )),
193
+ (socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::4' , 4 )),
194
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.3' , 7 )),
195
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.4' , 8 )),
196
+ ],
197
+ base_events ._interleave_addrinfos (addrinfos , 2 )
198
+ )
199
+
148
200
149
201
class BaseEventLoopTests (test_utils .TestCase ):
150
202
@@ -1431,6 +1483,65 @@ def getaddrinfo_task(*args, **kwds):
1431
1483
self .assertRaises (
1432
1484
OSError , self .loop .run_until_complete , coro )
1433
1485
1486
+ @unittest .skipUnless (socket_helper .IPV6_ENABLED , 'no IPv6 support' )
1487
+ @patch_socket
1488
+ def test_create_connection_happy_eyeballs (self , m_socket ):
1489
+
1490
+ class MyProto (asyncio .Protocol ):
1491
+ pass
1492
+
1493
+ async def getaddrinfo (* args , ** kw ):
1494
+ return [(socket .AF_INET6 , 0 , 0 , '' , ('2001:db8::1' , 1 )),
1495
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.1' , 5 ))]
1496
+
1497
+ async def sock_connect (sock , address ):
1498
+ if address [0 ] == '2001:db8::1' :
1499
+ await asyncio .sleep (1 )
1500
+ sock .connect (address )
1501
+
1502
+ self .loop ._add_reader = mock .Mock ()
1503
+ self .loop ._add_writer = mock .Mock ()
1504
+ self .loop .getaddrinfo = getaddrinfo
1505
+ self .loop .sock_connect = sock_connect
1506
+
1507
+ coro = self .loop .create_connection (MyProto , 'example.com' , 80 , happy_eyeballs_delay = 0.3 )
1508
+ transport , protocol = self .loop .run_until_complete (coro )
1509
+ try :
1510
+ sock = transport ._sock
1511
+ sock .connect .assert_called_with (('192.0.2.1' , 5 ))
1512
+ finally :
1513
+ transport .close ()
1514
+ test_utils .run_briefly (self .loop ) # allow transport to close
1515
+
1516
+ @patch_socket
1517
+ def test_create_connection_happy_eyeballs_ipv4_only (self , m_socket ):
1518
+
1519
+ class MyProto (asyncio .Protocol ):
1520
+ pass
1521
+
1522
+ async def getaddrinfo (* args , ** kw ):
1523
+ return [(socket .AF_INET , 0 , 0 , '' , ('192.0.2.1' , 5 )),
1524
+ (socket .AF_INET , 0 , 0 , '' , ('192.0.2.2' , 6 ))]
1525
+
1526
+ async def sock_connect (sock , address ):
1527
+ if address [0 ] == '192.0.2.1' :
1528
+ await asyncio .sleep (1 )
1529
+ sock .connect (address )
1530
+
1531
+ self .loop ._add_reader = mock .Mock ()
1532
+ self .loop ._add_writer = mock .Mock ()
1533
+ self .loop .getaddrinfo = getaddrinfo
1534
+ self .loop .sock_connect = sock_connect
1535
+
1536
+ coro = self .loop .create_connection (MyProto , 'example.com' , 80 , happy_eyeballs_delay = 0.3 )
1537
+ transport , protocol = self .loop .run_until_complete (coro )
1538
+ try :
1539
+ sock = transport ._sock
1540
+ sock .connect .assert_called_with (('192.0.2.2' , 6 ))
1541
+ finally :
1542
+ transport .close ()
1543
+ test_utils .run_briefly (self .loop ) # allow transport to close
1544
+
1434
1545
@patch_socket
1435
1546
def test_create_connection_bluetooth (self , m_socket ):
1436
1547
# See http://bugs.python.org/issue27136, fallback to getaddrinfo when
0 commit comments