diff options
Diffstat (limited to 'test/with_dummyserver/test_socketlevel.py')
-rw-r--r-- | test/with_dummyserver/test_socketlevel.py | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/test/with_dummyserver/test_socketlevel.py b/test/with_dummyserver/test_socketlevel.py index d09002b..1e6113f 100644 --- a/test/with_dummyserver/test_socketlevel.py +++ b/test/with_dummyserver/test_socketlevel.py @@ -30,6 +30,7 @@ except ImportError: class MimeToolMessage(object): pass from threading import Event +import select import socket import ssl @@ -366,6 +367,72 @@ class TestSocketClosing(SocketDummyServerTestCase): self.assertRaises(ProtocolError, response.read) self.assertEqual(poolsize, pool.pool.qsize()) + def test_connection_closed_on_read_timeout_preload_false(self): + timed_out = Event() + + def socket_handler(listener): + sock = listener.accept()[0] + + # Consume request + buf = b'' + while not buf.endswith(b'\r\n\r\n'): + buf = sock.recv(65535) + + # Send partial chunked response and then hang. + sock.send(( + 'HTTP/1.1 200 OK\r\n' + 'Content-Type: text/plain\r\n' + 'Transfer-Encoding: chunked\r\n' + '\r\n' + '8\r\n' + '12345678\r\n').encode('utf-8') + ) + timed_out.wait(5) + + # Expect a new request, but keep hold of the old socket to avoid + # leaking it. Because we don't want to hang this thread, we + # actually use select.select to confirm that a new request is + # coming in: this lets us time the thread out. + rlist, _, _ = select.select([listener], [], [], 1) + assert rlist + new_sock = listener.accept()[0] + + # Consume request + buf = b'' + while not buf.endswith(b'\r\n\r\n'): + buf = new_sock.recv(65535) + + # Send complete chunked response. + new_sock.send(( + 'HTTP/1.1 200 OK\r\n' + 'Content-Type: text/plain\r\n' + 'Transfer-Encoding: chunked\r\n' + '\r\n' + '8\r\n' + '12345678\r\n' + '0\r\n\r\n').encode('utf-8') + ) + + new_sock.close() + sock.close() + + self._start_server(socket_handler) + with HTTPConnectionPool(self.host, self.port) as pool: + # First request should fail. + response = pool.urlopen('GET', '/', retries=0, + preload_content=False, + timeout=Timeout(connect=1, read=0.001)) + try: + self.assertRaises(ReadTimeoutError, response.read) + finally: + timed_out.set() + + # Second should succeed. + response = pool.urlopen('GET', '/', retries=0, + preload_content=False, + timeout=Timeout(connect=1, read=0.1)) + self.assertEqual(len(response.read()), 8) + class TestProxyManager(SocketDummyServerTestCase): @@ -437,6 +504,8 @@ class TestProxyManager(SocketDummyServerTestCase): self.assertTrue(b'For The Proxy: YEAH!\r\n' in r.data) def test_retries(self): + close_event = Event() + def echo_socket_handler(listener): sock = listener.accept()[0] # First request, which should fail @@ -455,6 +524,7 @@ class TestProxyManager(SocketDummyServerTestCase): '\r\n' '%s' % (len(buf), buf.decode('utf-8'))).encode('utf-8')) sock.close() + close_event.set() self._start_server(echo_socket_handler) base_url = 'http://%s:%d' % (self.host, self.port) @@ -466,6 +536,7 @@ class TestProxyManager(SocketDummyServerTestCase): assert_same_host=False, retries=1) self.assertEqual(r.status, 200) + close_event.wait(timeout=1) self.assertRaises(ProxyError, conn.urlopen, 'GET', 'http://www.google.com', assert_same_host=False, retries=False) |