Unify timeout values in test suite
The goal is to be able to to tweak the timeout values globally, and to
use larger timeouts on CI where running time is less predictable.
MODIFY
test/__init__.py
test/__init__.py
@@ -28,6 +28,16 @@ VALID_SOURCE_ADDRESSES = [(("::1", 0), True), (("127.0.0.1", 0), False)]
# RFC 3849: 2001:db8::/32 is for documentation only.
INVALID_SOURCE_ADDRESSES = [("192.0.2.255", 0), ("2001:db8::1", 0)]
+# We use timeouts in three different ways in our tests
+#
+# 1. To make sure that the operation timeouts, we can use a short timeout.
+# 2. To make sure that the test does not hang even if the operation should succeed, we
+# want to use a long timeout, even more so on CI where tests can be really slow
+# 3. To test our timeout logic by using two different values, eg. by using different
+# values at the pool level and at the request level.
+SHORT_TIMEOUT = 0.001
+LONG_TIMEOUT = 0.5 if os.environ.get("CI") else 0.01
+
def clear_warnings(cls=HTTPWarning):
new_filters = []

MODIFY
test/appengine/test_gae_manager.py
test/appengine/test_gae_manager.py
@@ -7,6 +7,7 @@ import urllib3.util.url
import urllib3.util.retry
from test.with_dummyserver import test_connectionpool
+from test import SHORT_TIMEOUT
# This class is used so we can re-use the tests from the connection pool.
@@ -46,7 +47,11 @@ class TestGAEConnectionManager(test_connectionpool.TestConnectionPool):
def test_exceptions(self):
# DeadlineExceededError -> TimeoutError
with pytest.raises(urllib3.exceptions.TimeoutError):
- self.pool.request("GET", "/sleep?seconds=0.005", timeout=0.001)
+ self.pool.request(
+ "GET",
+ "/sleep?seconds={}".format(5 * SHORT_TIMEOUT),
+ timeout=SHORT_TIMEOUT,
+ )
# InvalidURLError -> ProtocolError
with pytest.raises(urllib3.exceptions.ProtocolError):

MODIFY
test/contrib/test_socks.py
test/contrib/test_socks.py
@@ -8,6 +8,7 @@ from dummyserver.server import DEFAULT_CERTS, DEFAULT_CA
from dummyserver.testcase import IPV4SocketDummyServerTestCase
import pytest
+from test import SHORT_TIMEOUT
try:
import ssl
@@ -314,7 +315,9 @@ class TestSocks5Proxy(IPV4SocketDummyServerTestCase):
proxy_url = "socks5h://%s:%s" % (self.host, self.port)
with socks.SOCKSProxyManager(proxy_url) as pm:
with pytest.raises(ConnectTimeoutError):
- pm.request("GET", "http://example.com", timeout=0.001, retries=False)
+ pm.request(
+ "GET", "http://example.com", timeout=SHORT_TIMEOUT, retries=False
+ )
event.set()
def test_connection_failure(self):

MODIFY
test/test_connectionpool.py
test/test_connectionpool.py
@@ -31,6 +31,7 @@ from socket import error as SocketError
from ssl import SSLError as BaseSSLError
from dummyserver.server import DEFAULT_CA
+from test import SHORT_TIMEOUT
class HTTPUnixConnection(HTTPConnection):
@@ -212,13 +213,13 @@ class TestConnectionPool(object):
def test_max_connections(self):
with HTTPConnectionPool(host="localhost", maxsize=1, block=True) as pool:
- pool._get_conn(timeout=0.01)
+ pool._get_conn(timeout=SHORT_TIMEOUT)
with pytest.raises(EmptyPoolError):
- pool._get_conn(timeout=0.01)
+ pool._get_conn(timeout=SHORT_TIMEOUT)
with pytest.raises(EmptyPoolError):
- pool.request("GET", "/", pool_timeout=0.01)
+ pool.request("GET", "/", pool_timeout=SHORT_TIMEOUT)
assert pool.num_connections == 1
@@ -288,7 +289,7 @@ class TestConnectionPool(object):
# See: https://github.com/urllib3/urllib3/issues/76
pool._make_request = lambda *args, **kwargs: _raise(HTTPException)
with pytest.raises(MaxRetryError):
- pool.request("GET", "/", retries=1, pool_timeout=0.01)
+ pool.request("GET", "/", retries=1, pool_timeout=SHORT_TIMEOUT)
assert pool.pool.qsize() == POOL_SIZE
def test_assert_same_host(self):
@@ -348,9 +349,9 @@ class TestConnectionPool(object):
assert pool.timeout._connect == Timeout.DEFAULT_TIMEOUT
assert pool.timeout.total is None
- pool = HTTPConnectionPool(host="localhost", timeout=3)
- assert pool.timeout._read == 3
- assert pool.timeout._connect == 3
+ pool = HTTPConnectionPool(host="localhost", timeout=SHORT_TIMEOUT)
+ assert pool.timeout._read == SHORT_TIMEOUT
+ assert pool.timeout._connect == SHORT_TIMEOUT
assert pool.timeout.total is None
def test_no_host(self):

MODIFY
test/with_dummyserver/test_connectionpool.py
test/with_dummyserver/test_connectionpool.py
@@ -25,6 +25,7 @@ from urllib3.packages.six.moves.urllib.parse import urlencode
from urllib3.util.retry import Retry, RequestHistory
from urllib3.util.timeout import Timeout
+from test import SHORT_TIMEOUT, LONG_TIMEOUT
from dummyserver.testcase import HTTPDummyServerTestCase, SocketDummyServerTestCase
from dummyserver.server import NoIPv6Warning, HAS_IPV6_AND_DNS
@@ -37,10 +38,6 @@ log.setLevel(logging.NOTSET)
log.addHandler(logging.StreamHandler(sys.stdout))
-SHORT_TIMEOUT = 0.001
-LONG_TIMEOUT = 0.03
-
-
def wait_for_socket(ready_event):
ready_event.wait()
ready_event.clear()
@@ -51,19 +48,16 @@ class TestConnectionPoolTimeouts(SocketDummyServerTestCase):
block_event = Event()
ready_event = self.start_basic_handler(block_send=block_event, num=2)
- # Pool-global timeout
- with HTTPConnectionPool(
- self.host, self.port, timeout=SHORT_TIMEOUT, retries=False
- ) as pool:
+ with HTTPConnectionPool(self.host, self.port, retries=False) as pool:
wait_for_socket(ready_event)
with pytest.raises(ReadTimeoutError):
- pool.request("GET", "/")
+ pool.request("GET", "/", timeout=SHORT_TIMEOUT)
block_event.set() # Release block
# Shouldn't raise this time
wait_for_socket(ready_event)
block_event.set() # Pre-release block
- pool.request("GET", "/")
+ pool.request("GET", "/", timeout=LONG_TIMEOUT)
def test_conn_closed(self):
block_event = Event()

MODIFY
test/with_dummyserver/test_https.py
test/with_dummyserver/test_https.py
@@ -39,6 +39,8 @@ from test import (
requiresTLSv1_2,
requiresTLSv1_3,
TARPIT_HOST,
+ SHORT_TIMEOUT,
+ LONG_TIMEOUT,
)
from urllib3 import HTTPSConnectionPool
from urllib3.connection import VerifiedHTTPSConnection, RECENT_DATE
@@ -503,7 +505,7 @@ class TestHTTPS(HTTPSDummyServerTestCase):
@requires_network
def test_https_timeout(self):
- timeout = Timeout(total=None, connect=0.001)
+ timeout = Timeout(total=None, connect=SHORT_TIMEOUT)
with HTTPSConnectionPool(
TARPIT_HOST,
self.port,
@@ -553,7 +555,7 @@ class TestHTTPS(HTTPSDummyServerTestCase):
with HTTPSConnectionPool(
TARPIT_HOST,
self.port,
- timeout=Timeout(connect=0.001),
+ timeout=Timeout(connect=SHORT_TIMEOUT),
retries=False,
cert_reqs="CERT_REQUIRED",
) as https_pool:
@@ -569,12 +571,12 @@ class TestHTTPS(HTTPSDummyServerTestCase):
with HTTPSConnectionPool(
TARPIT_HOST,
self.port,
- timeout=Timeout(connect=5),
+ timeout=Timeout(connect=LONG_TIMEOUT),
retries=False,
cert_reqs="CERT_REQUIRED",
) as https_pool:
with pytest.raises(ConnectTimeoutError):
- https_pool.request("GET", "/", timeout=Timeout(connect=0.001))
+ https_pool.request("GET", "/", timeout=Timeout(connect=SHORT_TIMEOUT))
with HTTPSConnectionPool(
TARPIT_HOST,
@@ -587,7 +589,7 @@ class TestHTTPS(HTTPSDummyServerTestCase):
try:
with pytest.raises(ConnectTimeoutError):
https_pool.request(
- "GET", "/", timeout=Timeout(total=None, connect=0.001)
+ "GET", "/", timeout=Timeout(total=None, connect=SHORT_TIMEOUT)
)
finally:
conn.close()

MODIFY
test/with_dummyserver/test_poolmanager.py
test/with_dummyserver/test_poolmanager.py
@@ -9,6 +9,8 @@ from urllib3.connectionpool import port_by_scheme
from urllib3.exceptions import MaxRetryError
from urllib3.util.retry import Retry
+from test import LONG_TIMEOUT
+
# Retry failed tests
pytestmark = pytest.mark.flaky
@@ -88,7 +90,7 @@ class TestPoolManager(HTTPDummyServerTestCase):
"GET",
"%s/redirect" % self.base_url,
fields={"target": cross_host_location},
- timeout=1,
+ timeout=LONG_TIMEOUT,
retries=0,
)
@@ -96,7 +98,7 @@ class TestPoolManager(HTTPDummyServerTestCase):
"GET",
"%s/redirect" % self.base_url,
fields={"target": "%s/echo?a=b" % self.base_url_alt},
- timeout=1,
+ timeout=LONG_TIMEOUT,
retries=1,
)

MODIFY
test/with_dummyserver/test_proxy_poolmanager.py
test/with_dummyserver/test_proxy_poolmanager.py
@@ -12,6 +12,8 @@ from urllib3.poolmanager import proxy_from_url, ProxyManager
from urllib3.exceptions import MaxRetryError, SSLError, ProxyError, ConnectTimeoutError
from urllib3.connectionpool import connection_from_url, VerifiedHTTPSConnection
+from test import SHORT_TIMEOUT, LONG_TIMEOUT
+
# Retry failed tests
pytestmark = pytest.mark.flaky
@@ -54,7 +56,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
def test_proxy_conn_fail(self):
host, port = get_unreachable_address()
with proxy_from_url(
- "http://%s:%s/" % (host, port), retries=1, timeout=0.05
+ "http://%s:%s/" % (host, port), retries=1, timeout=LONG_TIMEOUT
) as http:
with pytest.raises(MaxRetryError):
http.request("GET", "%s/" % self.https_url)
@@ -134,7 +136,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
"GET",
"%s/redirect" % self.http_url,
fields={"target": cross_host_location},
- timeout=1,
+ timeout=LONG_TIMEOUT,
retries=0,
)
@@ -142,7 +144,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
"GET",
"%s/redirect" % self.http_url,
fields={"target": "%s/echo?a=b" % self.http_url_alt},
- timeout=1,
+ timeout=LONG_TIMEOUT,
retries=1,
)
assert r._pool.host != self.http_host_alt
@@ -155,7 +157,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
"GET",
"%s/redirect" % self.http_url,
fields={"target": cross_protocol_location},
- timeout=1,
+ timeout=LONG_TIMEOUT,
retries=0,
)
@@ -163,7 +165,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
"GET",
"%s/redirect" % self.http_url,
fields={"target": "%s/echo?a=b" % self.https_url},
- timeout=1,
+ timeout=LONG_TIMEOUT,
retries=1,
)
assert r._pool.host == self.https_host
@@ -321,14 +323,14 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
def test_https_proxy_timeout(self):
with proxy_from_url("https://{host}".format(host=TARPIT_HOST)) as https:
with pytest.raises(MaxRetryError) as e:
- https.request("GET", self.http_url, timeout=0.001)
+ https.request("GET", self.http_url, timeout=SHORT_TIMEOUT)
assert type(e.value.reason) == ConnectTimeoutError
@pytest.mark.timeout(0.5)
@requires_network
def test_https_proxy_pool_timeout(self):
with proxy_from_url(
- "https://{host}".format(host=TARPIT_HOST), timeout=0.001
+ "https://{host}".format(host=TARPIT_HOST), timeout=SHORT_TIMEOUT
) as https:
with pytest.raises(MaxRetryError) as e:
https.request("GET", self.http_url)

MODIFY
test/with_dummyserver/test_socketlevel.py
test/with_dummyserver/test_socketlevel.py
@@ -47,7 +47,12 @@ import mock
import pytest
-from test import fails_on_travis_gce, requires_ssl_context_keyfile_password
+from test import (
+ fails_on_travis_gce,
+ requires_ssl_context_keyfile_password,
+ SHORT_TIMEOUT,
+ LONG_TIMEOUT,
+)
# Retry failed tests
pytestmark = pytest.mark.flaky
@@ -374,7 +379,12 @@ class TestSocketClosing(SocketDummyServerTestCase):
self._start_server(socket_handler)
with HTTPConnectionPool(
- self.host, self.port, timeout=0.01, retries=False, maxsize=3, block=True
+ self.host,
+ self.port,
+ timeout=SHORT_TIMEOUT,
+ retries=False,
+ maxsize=3,
+ block=True,
) as http:
try:
with pytest.raises(ReadTimeoutError):
@@ -395,7 +405,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
self._start_server(socket_handler)
with HTTPConnectionPool(
- self.host, self.port, timeout=0.01, retries=True
+ self.host, self.port, timeout=SHORT_TIMEOUT, retries=True
) as pool:
try:
with pytest.raises(ReadTimeoutError):
@@ -417,7 +427,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
self._start_server(socket_handler)
with HTTPSConnectionPool(
- self.host, self.port, timeout=0.01, retries=False
+ self.host, self.port, timeout=SHORT_TIMEOUT, retries=False
) as pool:
try:
with pytest.raises(ReadTimeoutError):
@@ -461,7 +471,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
try:
self._start_server(socket_handler)
- t = Timeout(connect=0.001, read=0.01)
+ t = Timeout(connect=SHORT_TIMEOUT, read=LONG_TIMEOUT)
with HTTPConnectionPool(self.host, self.port, timeout=t) as pool:
response = pool.request("GET", "/", retries=1)
assert response.status == 200
@@ -498,7 +508,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
"/",
retries=0,
preload_content=False,
- timeout=Timeout(connect=1, read=0.01),
+ timeout=Timeout(connect=1, read=SHORT_TIMEOUT),
)
try:
with pytest.raises(ReadTimeoutError):
@@ -531,9 +541,8 @@ class TestSocketClosing(SocketDummyServerTestCase):
with HTTPConnectionPool(self.host, self.port) as pool:
try:
with pytest.raises(ReadTimeoutError):
- pool.urlopen(
- "GET", "/", retries=False, timeout=Timeout(connect=1, read=0.01)
- )
+ timeout = Timeout(connect=LONG_TIMEOUT, read=SHORT_TIMEOUT)
+ pool.urlopen("GET", "/", retries=False, timeout=timeout)
finally:
timed_out.set()
@@ -641,12 +650,9 @@ class TestSocketClosing(SocketDummyServerTestCase):
self._start_server(socket_handler)
with HTTPConnectionPool(self.host, self.port) as pool:
poolsize = pool.pool.qsize()
+ timeout = Timeout(connect=LONG_TIMEOUT, read=SHORT_TIMEOUT)
response = pool.urlopen(
- "GET",
- "/",
- retries=0,
- preload_content=False,
- timeout=Timeout(connect=1, read=0.01),
+ "GET", "/", retries=0, preload_content=False, timeout=timeout
)
try:
with pytest.raises(ReadTimeoutError):
@@ -745,11 +751,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
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.1),
+ "GET", "/", retries=0, preload_content=False, timeout=LONG_TIMEOUT
)
try:
with pytest.raises(ReadTimeoutError):
@@ -759,11 +761,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
# Second should succeed.
response = pool.urlopen(
- "GET",
- "/",
- retries=0,
- preload_content=False,
- timeout=Timeout(connect=1, read=1),
+ "GET", "/", retries=0, preload_content=False, timeout=LONG_TIMEOUT
)
assert len(response.read()) == 8
@@ -788,11 +786,11 @@ class TestSocketClosing(SocketDummyServerTestCase):
)
# Wait for the socket to close.
- done_closing.wait(timeout=1)
+ done_closing.wait(timeout=LONG_TIMEOUT)
# Look for the empty string to show that the connection got closed.
# Don't get stuck in a timeout.
- sock.settimeout(1)
+ sock.settimeout(LONG_TIMEOUT)
new_data = sock.recv(65536)
assert not new_data
sock.close()
@@ -805,7 +803,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
response.close()
done_closing.set() # wait until the socket in our pool gets closed
- successful = complete.wait(timeout=1)
+ successful = complete.wait(timeout=LONG_TIMEOUT)
assert successful, "Timed out waiting for connection close"
def test_release_conn_param_is_respected_after_timeout_retry(self):
@@ -863,7 +861,7 @@ class TestSocketClosing(SocketDummyServerTestCase):
retries=1,
release_conn=False,
preload_content=False,
- timeout=Timeout(connect=1, read=0.01),
+ timeout=Timeout(connect=LONG_TIMEOUT, read=SHORT_TIMEOUT),
)
# The connection should still be on the response object, and none
@@ -991,7 +989,7 @@ class TestProxyManager(SocketDummyServerTestCase):
)
assert r.status == 200
- close_event.wait(timeout=1)
+ close_event.wait(timeout=LONG_TIMEOUT)
with pytest.raises(ProxyError):
conn.urlopen(
"GET",
@@ -1180,11 +1178,7 @@ class TestSSL(SocketDummyServerTestCase):
self._start_server(socket_handler)
with HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA) as pool:
response = pool.urlopen(
- "GET",
- "/",
- retries=0,
- preload_content=False,
- timeout=Timeout(connect=1, read=0.01),
+ "GET", "/", retries=0, preload_content=False, timeout=LONG_TIMEOUT
)
try:
with pytest.raises(ReadTimeoutError):
@@ -1223,12 +1217,9 @@ class TestSSL(SocketDummyServerTestCase):
self.host, self.port, assert_fingerprint=fingerprint
)
try:
+ timeout = Timeout(connect=LONG_TIMEOUT, read=SHORT_TIMEOUT)
response = pool.urlopen(
- "GET",
- "/",
- preload_content=False,
- timeout=Timeout(connect=1, read=0.01),
- retries=0,
+ "GET", "/", preload_content=False, retries=0, timeout=timeout
)
response.read()
finally:
@@ -1327,7 +1318,7 @@ class TestSSL(SocketDummyServerTestCase):
self._start_server(socket_handler)
with HTTPSConnectionPool(self.host, self.port) as pool:
with pytest.raises(MaxRetryError):
- pool.request("GET", "/", timeout=0.01)
+ pool.request("GET", "/", timeout=SHORT_TIMEOUT)
context.load_default_certs.assert_called_with()
def test_ssl_dont_load_default_certs_when_given(self):
@@ -1375,7 +1366,7 @@ class TestSSL(SocketDummyServerTestCase):
with HTTPSConnectionPool(self.host, self.port, **kwargs) as pool:
with pytest.raises(MaxRetryError):
- pool.request("GET", "/", timeout=0.01)
+ pool.request("GET", "/", timeout=SHORT_TIMEOUT)
context.load_default_certs.assert_not_called()
@@ -1631,7 +1622,7 @@ class TestHEAD(SocketDummyServerTestCase):
b"\r\n"
)
with HTTPConnectionPool(self.host, self.port, retries=False) as pool:
- r = pool.request("HEAD", "/", timeout=1, preload_content=False)
+ r = pool.request("HEAD", "/", timeout=LONG_TIMEOUT, preload_content=False)
# stream will use the read_chunked method here.
assert [] == list(r.stream())
@@ -1644,7 +1635,7 @@ class TestHEAD(SocketDummyServerTestCase):
b"\r\n"
)
with HTTPConnectionPool(self.host, self.port, retries=False) as pool:
- r = pool.request("HEAD", "/", timeout=1, preload_content=False)
+ r = pool.request("HEAD", "/", timeout=LONG_TIMEOUT, preload_content=False)
# stream will use the read method here.
assert [] == list(r.stream())
@@ -1673,7 +1664,7 @@ class TestStream(SocketDummyServerTestCase):
self._start_server(socket_handler)
with HTTPConnectionPool(self.host, self.port, retries=False) as pool:
- r = pool.request("GET", "/", timeout=1, preload_content=False)
+ r = pool.request("GET", "/", timeout=LONG_TIMEOUT, preload_content=False)
# Stream should read to the end.
assert [b"hello, world"] == list(r.stream(None))
@@ -1699,7 +1690,7 @@ class TestBadContentLength(SocketDummyServerTestCase):
b"\r\n"
b"hello, world"
)
- done_event.wait(1)
+ done_event.wait(LONG_TIMEOUT)
sock.close()
self._start_server(socket_handler)

Unify timeout values in test suite (#1717)

The goal is to be able to to tweak the timeout values globally, and to
use larger timeouts on CI where running time is less predictable.