77skip_expected = not support .is_resource_enabled ('network' )
88
99import time
10+ import errno
1011import socket
1112
1213
@@ -101,8 +102,29 @@ class TimeoutTestCase(unittest.TestCase):
101102 def setUp (self ):
102103 raise NotImplementedError ()
103104
104- def tearDown (self ):
105- self .sock .close ()
105+ tearDown = setUp
106+
107+ def _sock_operation (self , count , timeout , method , * args ):
108+ """
109+ Test the specified socket method.
110+
111+ The method is run at most `count` times and must raise a socket.timeout
112+ within `timeout` + self.fuzz seconds.
113+ """
114+ self .sock .settimeout (timeout )
115+ method = getattr (self .sock , method )
116+ for i in range (count ):
117+ t1 = time .time ()
118+ try :
119+ method (* args )
120+ except socket .timeout as e :
121+ delta = time .time () - t1
122+ break
123+ else :
124+ self .fail ('socket.timeout was not raised' )
125+ # These checks should account for timing unprecision
126+ self .assertLess (delta , timeout + self .fuzz )
127+ self .assertGreater (delta , timeout - 1.0 )
106128
107129
108130class TCPTimeoutTestCase (TimeoutTestCase ):
@@ -112,75 +134,58 @@ def setUp(self):
112134 self .sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
113135 self .addr_remote = ('www.python.org.' , 80 )
114136
137+ def tearDown (self ):
138+ self .sock .close ()
139+
115140 def testConnectTimeout (self ):
116141 # Choose a private address that is unlikely to exist to prevent
117142 # failures due to the connect succeeding before the timeout.
118143 # Use a dotted IP address to avoid including the DNS lookup time
119144 # with the connect time. This avoids failing the assertion that
120145 # the timeout occurred fast enough.
121146 addr = ('10.0.0.0' , 12345 )
122-
123- # Test connect() timeout
124- _timeout = 0.001
125- self .sock .settimeout (_timeout )
126-
127- _t1 = time .time ()
128- self .assertRaises (socket .error , self .sock .connect , addr )
129- _t2 = time .time ()
130-
131- _delta = abs (_t1 - _t2 )
132- self .assertTrue (_delta < _timeout + self .fuzz ,
133- "timeout (%g) is more than %g seconds more than expected (%g)"
134- % (_delta , self .fuzz , _timeout ))
147+ with support .transient_internet (addr [0 ]):
148+ self ._sock_operation (1 , 0.001 , 'connect' , addr )
135149
136150 def testRecvTimeout (self ):
137151 # Test recv() timeout
138- _timeout = 0.02
139-
140152 with support .transient_internet (self .addr_remote [0 ]):
141153 self .sock .connect (self .addr_remote )
142- self .sock .settimeout (_timeout )
143-
144- _t1 = time .time ()
145- self .assertRaises (socket .timeout , self .sock .recv , 1024 )
146- _t2 = time .time ()
147-
148- _delta = abs (_t1 - _t2 )
149- self .assertTrue (_delta < _timeout + self .fuzz ,
150- "timeout (%g) is %g seconds more than expected (%g)"
151- % (_delta , self .fuzz , _timeout ))
154+ self ._sock_operation (1 , 1.5 , 'recv' , 1024 )
152155
153156 def testAcceptTimeout (self ):
154157 # Test accept() timeout
155- _timeout = 2
156- self .sock .settimeout (_timeout )
157- # Prevent "Address already in use" socket exceptions
158158 support .bind_port (self .sock , self .localhost )
159159 self .sock .listen (5 )
160-
161- _t1 = time .time ()
162- self .assertRaises (socket .error , self .sock .accept )
163- _t2 = time .time ()
164-
165- _delta = abs (_t1 - _t2 )
166- self .assertTrue (_delta < _timeout + self .fuzz ,
167- "timeout (%g) is %g seconds more than expected (%g)"
168- % (_delta , self .fuzz , _timeout ))
160+ self ._sock_operation (1 , 1.5 , 'accept' )
169161
170162 def testSend (self ):
171163 # Test send() timeout
172- # couldn't figure out how to test it
173- pass
164+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as serv :
165+ support .bind_port (serv , self .localhost )
166+ serv .listen (5 )
167+ self .sock .connect (serv .getsockname ())
168+ # Send a lot of data in order to bypass buffering in the TCP stack.
169+ self ._sock_operation (100 , 1.5 , 'send' , b"X" * 200000 )
174170
175171 def testSendto (self ):
176172 # Test sendto() timeout
177- # couldn't figure out how to test it
178- pass
173+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as serv :
174+ support .bind_port (serv , self .localhost )
175+ serv .listen (5 )
176+ self .sock .connect (serv .getsockname ())
177+ # The address argument is ignored since we already connected.
178+ self ._sock_operation (100 , 1.5 , 'sendto' , b"X" * 200000 ,
179+ serv .getsockname ())
179180
180181 def testSendall (self ):
181182 # Test sendall() timeout
182- # couldn't figure out how to test it
183- pass
183+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as serv :
184+ support .bind_port (serv , self .localhost )
185+ serv .listen (5 )
186+ self .sock .connect (serv .getsockname ())
187+ # Send a lot of data in order to bypass buffering in the TCP stack.
188+ self ._sock_operation (100 , 1.5 , 'sendall' , b"X" * 200000 )
184189
185190
186191class UDPTimeoutTestCase (TimeoutTestCase ):
@@ -189,21 +194,14 @@ class UDPTimeoutTestCase(TimeoutTestCase):
189194 def setUp (self ):
190195 self .sock = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
191196
197+ def tearDown (self ):
198+ self .sock .close ()
199+
192200 def testRecvfromTimeout (self ):
193201 # Test recvfrom() timeout
194- _timeout = 2
195- self .sock .settimeout (_timeout )
196202 # Prevent "Address already in use" socket exceptions
197203 support .bind_port (self .sock , self .localhost )
198-
199- _t1 = time .time ()
200- self .assertRaises (socket .error , self .sock .recvfrom , 8192 )
201- _t2 = time .time ()
202-
203- _delta = abs (_t1 - _t2 )
204- self .assertTrue (_delta < _timeout + self .fuzz ,
205- "timeout (%g) is %g seconds more than expected (%g)"
206- % (_delta , self .fuzz , _timeout ))
204+ self ._sock_operation (1 , 1.5 , 'recvfrom' , 1024 )
207205
208206
209207def test_main ():
0 commit comments