diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/test_response.py | 33 | ||||
-rw-r--r-- | test/test_util.py | 1 | ||||
-rw-r--r-- | test/with_dummyserver/test_connectionpool.py | 35 | ||||
-rw-r--r-- | test/with_dummyserver/test_https.py | 21 | ||||
-rw-r--r-- | test/with_dummyserver/test_socketlevel.py | 48 |
5 files changed, 122 insertions, 16 deletions
diff --git a/test/test_response.py b/test/test_response.py index e74fd5d3..2e2be0ec 100644 --- a/test/test_response.py +++ b/test/test_response.py @@ -418,6 +418,29 @@ class TestResponse(unittest.TestCase): self.assertEqual(c, stream[i]) i += 1 + def test_mock_gzipped_transfer_encoding_chunked_decoded(self): + """Show that we can decode the gizpped and chunked body.""" + def stream(): + # Set up a generator to chunk the gzipped body + import zlib + compress = zlib.compressobj(6, zlib.DEFLATED, 16 + zlib.MAX_WBITS) + data = compress.compress(b'foobar') + data += compress.flush() + for i in range(0, len(data), 2): + yield data[i:i+2] + + fp = MockChunkedEncodingResponse(list(stream())) + r = httplib.HTTPResponse(MockSock) + r.fp = fp + headers = {'transfer-encoding': 'chunked', 'content-encoding': 'gzip'} + resp = HTTPResponse(r, preload_content=False, headers=headers) + + data = b'' + for c in resp.stream(decode_content=True): + data += c + + self.assertEqual(b'foobar', data) + def test_mock_transfer_encoding_chunked_custom_read(self): stream = [b"foooo", b"bbbbaaaaar"] fp = MockChunkedEncodingResponse(stream) @@ -517,7 +540,9 @@ class MockChunkedEncodingResponse(object): @staticmethod def _encode_chunk(chunk): - return '%X\r\n%s\r\n' % (len(chunk), chunk.decode()) + # In the general case, we can't decode the chunk to unicode + length = '%X\r\n' % len(chunk) + return length.encode() + chunk + b'\r\n' def _pop_new_chunk(self): if self.chunks_exhausted: @@ -529,8 +554,10 @@ class MockChunkedEncodingResponse(object): self.chunks_exhausted = True else: self.index += 1 - encoded_chunk = self._encode_chunk(chunk) - return encoded_chunk.encode() + chunk = self._encode_chunk(chunk) + if not isinstance(chunk, bytes): + chunk = chunk.encode() + return chunk def pop_current_chunk(self, amt=-1, till_crlf=False): if amt > 0 and till_crlf: diff --git a/test/test_util.py b/test/test_util.py index ba26af5a..19ba57e3 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -97,6 +97,7 @@ class TestUtil(unittest.TestCase): parse_url_host_map = { 'http://google.com/mail': Url('http', host='google.com', path='/mail'), 'http://google.com/mail/': Url('http', host='google.com', path='/mail/'), + 'http://google.com/mail': Url('http', host='google.com', path='mail'), 'google.com/mail': Url(host='google.com', path='/mail'), 'http://google.com/': Url('http', host='google.com', path='/'), 'http://google.com': Url('http', host='google.com'), diff --git a/test/with_dummyserver/test_connectionpool.py b/test/with_dummyserver/test_connectionpool.py index a789e9bd..d6cb1622 100644 --- a/test/with_dummyserver/test_connectionpool.py +++ b/test/with_dummyserver/test_connectionpool.py @@ -618,13 +618,34 @@ class TestConnectionPool(HTTPDummyServerTestCase): self.assertRaises(ProtocolError, pool.request, 'GET', '/source_address') - @onlyPy3 - def test_httplib_headers_case_insensitive(self): - HEADERS = {'Content-Length': '0', 'Content-type': 'text/plain', - 'Server': 'TornadoServer/%s' % tornado.version} - r = self.pool.request('GET', '/specific_method', - fields={'method': 'GET'}) - self.assertEqual(HEADERS, dict(r.headers.items())) # to preserve case sensitivity + def test_stream_keepalive(self): + x = 2 + + for _ in range(x): + response = self.pool.request( + 'GET', + '/chunked', + headers={ + 'Connection': 'keep-alive', + }, + preload_content=False, + retries=False, + ) + for chunk in response.stream(): + self.assertEqual(chunk, b'123') + + self.assertEqual(self.pool.num_connections, 1) + self.assertEqual(self.pool.num_requests, x) + + def test_chunked_gzip(self): + response = self.pool.request( + 'GET', + '/chunked_gzip', + preload_content=False, + decode_content=True, + ) + + self.assertEqual(b'123' * 4, response.read()) class TestRetry(HTTPDummyServerTestCase): diff --git a/test/with_dummyserver/test_https.py b/test/with_dummyserver/test_https.py index f3e00acf..992b8ef1 100644 --- a/test/with_dummyserver/test_https.py +++ b/test/with_dummyserver/test_https.py @@ -32,9 +32,15 @@ from urllib3.exceptions import ( SystemTimeWarning, InsecurePlatformWarning, ) +from urllib3.packages import six from urllib3.util.timeout import Timeout +ResourceWarning = getattr( + six.moves.builtins, + 'ResourceWarning', type('ResourceWarning', (), {})) + + log = logging.getLogger('urllib3.connectionpool') log.setLevel(logging.NOTSET) log.addHandler(logging.StreamHandler(sys.stdout)) @@ -362,10 +368,8 @@ class TestHTTPS(HTTPSDummyServerTestCase): def test_ssl_correct_system_time(self): self._pool.cert_reqs = 'CERT_REQUIRED' self._pool.ca_certs = DEFAULT_CA - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - self._pool.request('GET', '/') + w = self._request_without_resource_warnings('GET', '/') self.assertEqual([], w) def test_ssl_wrong_system_time(self): @@ -374,9 +378,7 @@ class TestHTTPS(HTTPSDummyServerTestCase): with mock.patch('urllib3.connection.datetime') as mock_date: mock_date.date.today.return_value = datetime.date(1970, 1, 1) - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - self._pool.request('GET', '/') + w = self._request_without_resource_warnings('GET', '/') self.assertEqual(len(w), 1) warning = w[0] @@ -384,6 +386,13 @@ class TestHTTPS(HTTPSDummyServerTestCase): self.assertEqual(SystemTimeWarning, warning.category) self.assertTrue(str(RECENT_DATE) in warning.message.args[0]) + def _request_without_resource_warnings(self, method, url): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + self._pool.request(method, url) + + return [x for x in w if not isinstance(x.message, ResourceWarning)] + class TestHTTPS_TLSv1(HTTPSDummyServerTestCase): certs = DEFAULT_CERTS.copy() diff --git a/test/with_dummyserver/test_socketlevel.py b/test/with_dummyserver/test_socketlevel.py index db481d30..6c996538 100644 --- a/test/with_dummyserver/test_socketlevel.py +++ b/test/with_dummyserver/test_socketlevel.py @@ -18,6 +18,8 @@ from dummyserver.testcase import SocketDummyServerTestCase from dummyserver.server import ( DEFAULT_CERTS, DEFAULT_CA, get_unreachable_address) +from .. import onlyPy3 + from nose.plugins.skip import SkipTest from threading import Event import socket @@ -598,3 +600,49 @@ class TestErrorWrapping(SocketDummyServerTestCase): self._start_server(handler) pool = HTTPConnectionPool(self.host, self.port, retries=False) self.assertRaises(ProtocolError, pool.request, 'GET', '/') + +class TestHeaders(SocketDummyServerTestCase): + + @onlyPy3 + def test_httplib_headers_case_insensitive(self): + handler = create_response_handler( + b'HTTP/1.1 200 OK\r\n' + b'Content-Length: 0\r\n' + b'Content-type: text/plain\r\n' + b'\r\n' + ) + self._start_server(handler) + pool = HTTPConnectionPool(self.host, self.port, retries=False) + HEADERS = {'Content-Length': '0', 'Content-type': 'text/plain'} + r = pool.request('GET', '/') + self.assertEqual(HEADERS, dict(r.headers.items())) # to preserve case sensitivity + + +class TestHEAD(SocketDummyServerTestCase): + def test_chunked_head_response_does_not_hang(self): + handler = create_response_handler( + b'HTTP/1.1 200 OK\r\n' + b'Transfer-Encoding: chunked\r\n' + b'Content-type: text/plain\r\n' + b'\r\n' + ) + self._start_server(handler) + pool = HTTPConnectionPool(self.host, self.port, retries=False) + r = pool.request('HEAD', '/', timeout=1, preload_content=False) + + # stream will use the read_chunked method here. + self.assertEqual([], list(r.stream())) + + def test_empty_head_response_does_not_hang(self): + handler = create_response_handler( + b'HTTP/1.1 200 OK\r\n' + b'Content-Length: 256\r\n' + b'Content-type: text/plain\r\n' + b'\r\n' + ) + self._start_server(handler) + pool = HTTPConnectionPool(self.host, self.port, retries=False) + r = pool.request('HEAD', '/', timeout=1, preload_content=False) + + # stream will use the read method here. + self.assertEqual([], list(r.stream())) |