diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/test_connectionpool.py | 11 | ||||
-rw-r--r-- | test/test_poolmanager.py | 5 | ||||
-rw-r--r-- | test/test_response.py | 5 | ||||
-rw-r--r-- | test/test_retry.py | 156 | ||||
-rw-r--r-- | test/test_util.py | 30 |
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 |