aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/test_connectionpool.py11
-rw-r--r--test/test_poolmanager.py5
-rw-r--r--test/test_response.py5
-rw-r--r--test/test_retry.py156
-rw-r--r--test/test_util.py30
5 files changed, 195 insertions, 12 deletions
diff --git a/test/test_connectionpool.py b/test/test_connectionpool.py
index 02229cf..28fb89b 100644
--- a/test/test_connectionpool.py
+++ b/test/test_connectionpool.py
@@ -5,13 +5,15 @@ from urllib3.connectionpool import (
HTTPConnection,
HTTPConnectionPool,
)
-from urllib3.util import Timeout
+from urllib3.util.timeout import Timeout
from urllib3.packages.ssl_match_hostname import CertificateError
from urllib3.exceptions import (
ClosedPoolError,
EmptyPoolError,
HostChangedError,
+ LocationValueError,
MaxRetryError,
+ ProtocolError,
SSLError,
)
@@ -127,7 +129,7 @@ class TestConnectionPool(unittest.TestCase):
HTTPConnectionPool(host='localhost'), "Test.", err)),
"HTTPConnectionPool(host='localhost', port=None): "
"Max retries exceeded with url: Test. "
- "(Caused by {0}: Test)".format(str(err.__class__)))
+ "(Caused by %r)" % err)
def test_pool_size(self):
@@ -186,7 +188,6 @@ class TestConnectionPool(unittest.TestCase):
self.assertRaises(Empty, old_pool_queue.get, block=False)
-
def test_pool_timeouts(self):
pool = HTTPConnectionPool(host='localhost')
conn = pool._new_conn()
@@ -201,6 +202,10 @@ class TestConnectionPool(unittest.TestCase):
self.assertEqual(pool.timeout._connect, 3)
self.assertEqual(pool.timeout.total, None)
+ def test_no_host(self):
+ self.assertRaises(LocationValueError, HTTPConnectionPool, None)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/test/test_poolmanager.py b/test/test_poolmanager.py
index 759b5e3..754ee8a 100644
--- a/test/test_poolmanager.py
+++ b/test/test_poolmanager.py
@@ -4,7 +4,7 @@ from urllib3.poolmanager import PoolManager
from urllib3 import connection_from_url
from urllib3.exceptions import (
ClosedPoolError,
- LocationParseError,
+ LocationValueError,
)
@@ -68,7 +68,8 @@ class TestPoolManager(unittest.TestCase):
def test_nohost(self):
p = PoolManager(5)
- self.assertRaises(LocationParseError, p.connection_from_url, 'http://@')
+ self.assertRaises(LocationValueError, p.connection_from_url, 'http://@')
+ self.assertRaises(LocationValueError, p.connection_from_url, None)
if __name__ == '__main__':
diff --git a/test/test_response.py b/test/test_response.py
index ecfcbee..ad134ee 100644
--- a/test/test_response.py
+++ b/test/test_response.py
@@ -131,6 +131,11 @@ class TestResponse(unittest.TestCase):
self.assertEqual(r.read(1), b'f')
self.assertEqual(r.read(2), b'oo')
+ def test_body_blob(self):
+ resp = HTTPResponse(b'foo')
+ self.assertEqual(resp.data, b'foo')
+ self.assertTrue(resp.closed)
+
def test_io(self):
import socket
try:
diff --git a/test/test_retry.py b/test/test_retry.py
new file mode 100644
index 0000000..7a3aa40
--- /dev/null
+++ b/test/test_retry.py
@@ -0,0 +1,156 @@
+import unittest
+
+from urllib3.packages.six.moves import xrange
+from urllib3.util.retry import Retry
+from urllib3.exceptions import (
+ ConnectTimeoutError,
+ ReadTimeoutError,
+ MaxRetryError
+)
+
+
+class RetryTest(unittest.TestCase):
+
+ def test_string(self):
+ """ Retry string representation looks the way we expect """
+ retry = Retry()
+ self.assertEqual(str(retry), 'Retry(total=10, connect=None, read=None, redirect=None)')
+ for _ in range(3):
+ retry = retry.increment()
+ self.assertEqual(str(retry), 'Retry(total=7, connect=None, read=None, redirect=None)')
+
+ def test_retry_both_specified(self):
+ """Total can win if it's lower than the connect value"""
+ error = ConnectTimeoutError()
+ retry = Retry(connect=3, total=2)
+ retry = retry.increment(error=error)
+ retry = retry.increment(error=error)
+ try:
+ retry.increment(error=error)
+ self.fail("Failed to raise error.")
+ except MaxRetryError as e:
+ self.assertEqual(e.reason, error)
+
+ def test_retry_higher_total_loses(self):
+ """ A lower connect timeout than the total is honored """
+ error = ConnectTimeoutError()
+ retry = Retry(connect=2, total=3)
+ retry = retry.increment(error=error)
+ retry = retry.increment(error=error)
+ self.assertRaises(MaxRetryError, retry.increment, error=error)
+
+ def test_retry_higher_total_loses_vs_read(self):
+ """ A lower read timeout than the total is honored """
+ error = ReadTimeoutError(None, "/", "read timed out")
+ retry = Retry(read=2, total=3)
+ retry = retry.increment(error=error)
+ retry = retry.increment(error=error)
+ self.assertRaises(MaxRetryError, retry.increment, error=error)
+
+ def test_retry_total_none(self):
+ """ if Total is none, connect error should take precedence """
+ error = ConnectTimeoutError()
+ retry = Retry(connect=2, total=None)
+ retry = retry.increment(error=error)
+ retry = retry.increment(error=error)
+ try:
+ retry.increment(error=error)
+ self.fail("Failed to raise error.")
+ except MaxRetryError as e:
+ self.assertEqual(e.reason, error)
+
+ error = ReadTimeoutError(None, "/", "read timed out")
+ retry = Retry(connect=2, total=None)
+ retry = retry.increment(error=error)
+ retry = retry.increment(error=error)
+ retry = retry.increment(error=error)
+ self.assertFalse(retry.is_exhausted())
+
+ def test_retry_default(self):
+ """ If no value is specified, should retry connects 3 times """
+ retry = Retry()
+ self.assertEqual(retry.total, 10)
+ self.assertEqual(retry.connect, None)
+ self.assertEqual(retry.read, None)
+ self.assertEqual(retry.redirect, None)
+
+ error = ConnectTimeoutError()
+ retry = Retry(connect=1)
+ retry = retry.increment(error=error)
+ self.assertRaises(MaxRetryError, retry.increment, error=error)
+
+ retry = Retry(connect=1)
+ retry = retry.increment(error=error)
+ self.assertFalse(retry.is_exhausted())
+
+ self.assertTrue(Retry(0).raise_on_redirect)
+ self.assertFalse(Retry(False).raise_on_redirect)
+
+ def test_retry_read_zero(self):
+ """ No second chances on read timeouts, by default """
+ error = ReadTimeoutError(None, "/", "read timed out")
+ retry = Retry(read=0)
+ try:
+ retry.increment(error=error)
+ self.fail("Failed to raise error.")
+ except MaxRetryError as e:
+ self.assertEqual(e.reason, error)
+
+ def test_backoff(self):
+ """ Backoff is computed correctly """
+ max_backoff = Retry.BACKOFF_MAX
+
+ retry = Retry(total=100, backoff_factor=0.2)
+ self.assertEqual(retry.get_backoff_time(), 0) # First request
+
+ retry = retry.increment()
+ self.assertEqual(retry.get_backoff_time(), 0) # First retry
+
+ retry = retry.increment()
+ self.assertEqual(retry.backoff_factor, 0.2)
+ self.assertEqual(retry.total, 98)
+ self.assertEqual(retry.get_backoff_time(), 0.4) # Start backoff
+
+ retry = retry.increment()
+ self.assertEqual(retry.get_backoff_time(), 0.8)
+
+ retry = retry.increment()
+ self.assertEqual(retry.get_backoff_time(), 1.6)
+
+ for i in xrange(10):
+ retry = retry.increment()
+
+ self.assertEqual(retry.get_backoff_time(), max_backoff)
+
+ def test_zero_backoff(self):
+ retry = Retry()
+ self.assertEqual(retry.get_backoff_time(), 0)
+ retry = retry.increment()
+ retry = retry.increment()
+ self.assertEqual(retry.get_backoff_time(), 0)
+
+ def test_sleep(self):
+ # sleep a very small amount of time so our code coverage is happy
+ retry = Retry(backoff_factor=0.0001)
+ retry = retry.increment()
+ retry = retry.increment()
+ retry.sleep()
+
+ def test_status_forcelist(self):
+ retry = Retry(status_forcelist=xrange(500,600))
+ self.assertFalse(retry.is_forced_retry('GET', status_code=200))
+ self.assertFalse(retry.is_forced_retry('GET', status_code=400))
+ self.assertTrue(retry.is_forced_retry('GET', status_code=500))
+
+ retry = Retry(total=1, status_forcelist=[418])
+ self.assertFalse(retry.is_forced_retry('GET', status_code=400))
+ self.assertTrue(retry.is_forced_retry('GET', status_code=418))
+
+ def test_exhausted(self):
+ self.assertFalse(Retry(0).is_exhausted())
+ self.assertTrue(Retry(-1).is_exhausted())
+ self.assertEqual(Retry(1).increment().total, 0)
+
+ def test_disabled(self):
+ self.assertRaises(MaxRetryError, Retry(-1).increment)
+ self.assertRaises(MaxRetryError, Retry(0).increment)
diff --git a/test/test_util.py b/test/test_util.py
index 944d90f..388d877 100644
--- a/test/test_util.py
+++ b/test/test_util.py
@@ -1,20 +1,27 @@
+import warnings
import logging
import unittest
import ssl
from mock import patch
-from urllib3 import add_stderr_logger
-from urllib3.util import (
+from urllib3 import add_stderr_logger, disable_warnings
+from urllib3.util.request import make_headers
+from urllib3.util.timeout import Timeout
+from urllib3.util.url import (
get_host,
- make_headers,
- split_first,
parse_url,
- Timeout,
+ split_first,
Url,
- resolve_cert_reqs,
)
-from urllib3.exceptions import LocationParseError, TimeoutStateError
+from urllib3.util.ssl_ import resolve_cert_reqs
+from urllib3.exceptions import (
+ LocationParseError,
+ TimeoutStateError,
+ InsecureRequestWarning,
+)
+
+from . import clear_warnings
# This number represents a time in seconds, it doesn't mean anything in
# isolation. Setting to a high-ish value to avoid conflicts with the smaller
@@ -203,6 +210,15 @@ class TestUtil(unittest.TestCase):
logger.debug('Testing add_stderr_logger')
logger.removeHandler(handler)
+ def test_disable_warnings(self):
+ with warnings.catch_warnings(record=True) as w:
+ clear_warnings()
+ warnings.warn('This is a test.', InsecureRequestWarning)
+ self.assertEqual(len(w), 1)
+ disable_warnings()
+ warnings.warn('This is a test.', InsecureRequestWarning)
+ self.assertEqual(len(w), 1)
+
def _make_time_pass(self, seconds, timeout, time_mock):
""" Make some time pass for the timeout object """
time_mock.return_value = TIMEOUT_EPOCH