Skip to content

Commit

Permalink
Merge branch 'master' into issue-10
Browse files Browse the repository at this point in the history
  • Loading branch information
shazow committed Dec 10, 2011
2 parents f57ecdb + e3a54fd commit 34119d0
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 49 deletions.
98 changes: 53 additions & 45 deletions test/with_dummyserver/test_connectionpool.py
Expand Up @@ -17,29 +17,29 @@
class TestConnectionPool(HTTPDummyServerTestCase):

def setUp(self):
self._pool = HTTPConnectionPool(self.host, self.port)
self.pool = HTTPConnectionPool(self.host, self.port)

def test_get(self):
r = self._pool.request('GET', '/specific_method',
r = self.pool.request('GET', '/specific_method',
fields={'method': 'GET'})
self.assertEqual(r.status, 200, r.data)

def test_post_url(self):
r = self._pool.request('POST', '/specific_method',
r = self.pool.request('POST', '/specific_method',
fields={'method': 'POST'})
self.assertEqual(r.status, 200, r.data)

def test_urlopen_put(self):
r = self._pool.urlopen('PUT', '/specific_method?method=PUT')
r = self.pool.urlopen('PUT', '/specific_method?method=PUT')
self.assertEqual(r.status, 200, r.data)

def test_wrong_specific_method(self):
# To make sure the dummy server is actually returning failed responses
r = self._pool.request('GET', '/specific_method',
r = self.pool.request('GET', '/specific_method',
fields={'method': 'POST'})
self.assertEqual(r.status, 400, r.data)

r = self._pool.request('POST', '/specific_method',
r = self.pool.request('POST', '/specific_method',
fields={'method': 'GET'})
self.assertEqual(r.status, 400, r.data)

Expand All @@ -52,7 +52,7 @@ def test_upload(self):
'filefield': ('lolcat.txt', data),
}

r = self._pool.request('POST', '/upload', fields=fields)
r = self.pool.request('POST', '/upload', fields=fields)
self.assertEqual(r.status, 200, r.data)

def test_unicode_upload(self):
Expand All @@ -68,7 +68,7 @@ def test_unicode_upload(self):
fieldname: (filename, data),
}

r = self._pool.request('POST', '/upload', fields=fields)
r = self.pool.request('POST', '/upload', fields=fields)
self.assertEqual(r.status, 200, r.data)

def test_timeout(self):
Expand All @@ -81,19 +81,19 @@ def test_timeout(self):
pass

def test_redirect(self):
r = self._pool.request('GET', '/redirect',
r = self.pool.request('GET', '/redirect',
fields={'target': '/'},
redirect=False)
self.assertEqual(r.status, 303)

r = self._pool.request('GET', '/redirect',
r = self.pool.request('GET', '/redirect',
fields={'target': '/'})
self.assertEqual(r.status, 200)
self.assertEqual(r.data, 'Dummy server!')

def test_maxretry(self):
try:
self._pool.request('GET', '/redirect',
self.pool.request('GET', '/redirect',
fields={'target': '/'},
retries=0)
self.fail("Failed to raise MaxRetryError exception")
Expand Down Expand Up @@ -164,14 +164,14 @@ def test_keepalive_close(self):

def test_post_with_urlencode(self):
data = {'banana': 'hammock', 'lol': 'cat'}
r = self._pool.request('POST', '/echo',
r = self.pool.request('POST', '/echo',
fields=data,
encode_multipart=False)
self.assertEqual(r.data, urllib.urlencode(data))

def test_post_with_multipart(self):
data = {'banana': 'hammock', 'lol': 'cat'}
r = self._pool.request('POST', '/echo',
r = self.pool.request('POST', '/echo',
fields=data,
encode_multipart=True)
body = r.data.split('\r\n')
Expand All @@ -195,34 +195,34 @@ def test_post_with_multipart(self):
self.assertEqual(body[i], expected_body[i])

def test_check_gzip(self):
r = self._pool.request('GET', '/encodingrequest',
r = self.pool.request('GET', '/encodingrequest',
headers={'accept-encoding': 'gzip'})
self.assertEqual(r.headers.get('content-encoding'), 'gzip')
self.assertEqual(r.data, 'hello, world!')

def test_check_deflate(self):
r = self._pool.request('GET', '/encodingrequest',
r = self.pool.request('GET', '/encodingrequest',
headers={'accept-encoding': 'deflate'})
self.assertEqual(r.headers.get('content-encoding'), 'deflate')
self.assertEqual(r.data, 'hello, world!')

def test_connection_count(self):
http_pool = HTTPConnectionPool(self.host, self.port, maxsize=1)
pool = HTTPConnectionPool(self.host, self.port, maxsize=1)

http_pool.request('GET', '/')
http_pool.request('GET', '/')
http_pool.request('GET', '/')
pool.request('GET', '/')
pool.request('GET', '/')
pool.request('GET', '/')

self.assertEqual(http_pool.num_connections, 1)
self.assertEqual(http_pool.num_requests, 3)
self.assertEqual(pool.num_connections, 1)
self.assertEqual(pool.num_requests, 3)

def test_partial_response(self):
http_pool = HTTPConnectionPool(self.host, self.port, maxsize=1)
pool = HTTPConnectionPool(self.host, self.port, maxsize=1)

req_data = {'lol': 'cat'}
resp_data = urllib.urlencode(req_data)

r = http_pool.request('GET', '/echo', fields=req_data, preload_content=False)
r = pool.request('GET', '/echo', fields=req_data, preload_content=False)

self.assertEqual(r.read(5), resp_data[:5])
self.assertEqual(r.read(), resp_data[5:])
Expand All @@ -231,7 +231,7 @@ def test_lazy_load_twice(self):
# This test is sad and confusing. Need to figure out what's
# going on with partial reads and socket reuse.

http_pool = HTTPConnectionPool(self.host, self.port, block=True, maxsize=1, timeout=2)
pool = HTTPConnectionPool(self.host, self.port, block=True, maxsize=1, timeout=2)

payload_size = 1024 * 2
first_chunk = 512
Expand All @@ -244,12 +244,12 @@ def test_lazy_load_twice(self):
req2_data = {'count': 'b' * payload_size}
resp2_data = encode_multipart_formdata(req2_data, boundary=boundary)[0]

r1 = http_pool.request('POST', '/echo', fields=req_data, multipart_boundary=boundary, preload_content=False)
r1 = pool.request('POST', '/echo', fields=req_data, multipart_boundary=boundary, preload_content=False)

self.assertEqual(r1.read(first_chunk), resp_data[:first_chunk])

try:
r2 = http_pool.request('POST', '/echo', fields=req2_data, multipart_boundary=boundary,
r2 = pool.request('POST', '/echo', fields=req2_data, multipart_boundary=boundary,
preload_content=False, pool_timeout=0.001)

# This branch should generally bail here, but maybe someday it will
Expand All @@ -259,44 +259,52 @@ def test_lazy_load_twice(self):

self.assertEqual(r1.read(), resp_data[first_chunk:])
self.assertEqual(r2.read(), resp2_data[first_chunk:])
self.assertEqual(http_pool.num_requests, 2)
self.assertEqual(pool.num_requests, 2)

except EmptyPoolError:
self.assertEqual(r1.read(), resp_data[first_chunk:])
self.assertEqual(http_pool.num_requests, 1)
self.assertEqual(pool.num_requests, 1)

self.assertEqual(http_pool.num_connections, 1)
self.assertEqual(pool.num_connections, 1)

def test_for_double_release(self):
MAXSIZE=5

# Check default state
http_pool = HTTPConnectionPool(self.host, self.port, maxsize=MAXSIZE)
self.assertEqual(http_pool.num_connections, 0)
pool = HTTPConnectionPool(self.host, self.port, maxsize=MAXSIZE)
self.assertEqual(pool.num_connections, 0)
self.assertEqual(pool.pool.qsize(), MAXSIZE)

# Make an empty slot for testing
http_pool.pool.get()

self.assertEqual(http_pool.pool.qsize(), MAXSIZE-1)

pool.pool.get()
self.assertEqual(pool.pool.qsize(), MAXSIZE-1)

# Check state after simple request
http_pool.urlopen('GET', '/')
self.assertEqual(http_pool.pool.qsize(), MAXSIZE-1)
pool.urlopen('GET', '/')
self.assertEqual(pool.pool.qsize(), MAXSIZE-1)

# Check state without release
http_pool.urlopen('GET', '/', preload_content=False)
self.assertEqual(http_pool.pool.qsize(), MAXSIZE-2)
pool.urlopen('GET', '/', preload_content=False)
self.assertEqual(pool.pool.qsize(), MAXSIZE-2)

http_pool.urlopen('GET', '/')
self.assertEqual(http_pool.pool.qsize(), MAXSIZE-2)
pool.urlopen('GET', '/')
self.assertEqual(pool.pool.qsize(), MAXSIZE-2)

# Check state after read
http_pool.urlopen('GET', '/').data
self.assertEqual(http_pool.pool.qsize(), MAXSIZE-2)
pool.urlopen('GET', '/').data
self.assertEqual(pool.pool.qsize(), MAXSIZE-2)

pool.urlopen('GET', '/')
self.assertEqual(pool.pool.qsize(), MAXSIZE-2)

def test_release_conn_parameter(self):
MAXSIZE=5
pool = HTTPConnectionPool(self.host, self.port, maxsize=MAXSIZE)
self.assertEqual(pool.pool.qsize(), MAXSIZE)

http_pool.urlopen('GET', '/')
self.assertEqual(http_pool.pool.qsize(), MAXSIZE-2)
# Make request without releasing connection
pool.request('GET', '/', release_conn=False, preload_content=False)
self.assertEqual(pool.pool.qsize(), MAXSIZE-1)


if __name__ == '__main__':
Expand Down
17 changes: 13 additions & 4 deletions urllib3/connectionpool.py
Expand Up @@ -244,6 +244,13 @@ def urlopen(self, method, url, body=None, headers=None, retries=3,
More commonly, it's appropriate to use a convenience method provided
by :class:`.RequestMethods`, such as :meth:`.request`.
.. note::
`release_conn` will only behave as expected if
`preload_content=False` because we want to make
`preload_content=False` the default behaviour someday soon without
breaking backwards compatibility.
:param method:
HTTP request method (such as GET, POST, PUT, etc.)
Expand Down Expand Up @@ -279,10 +286,12 @@ def urlopen(self, method, url, body=None, headers=None, retries=3,
:param release_conn:
If False, then the urlopen call will not release the connection
back into the pool once a response is received. This is useful if
you're not preloading the response's content immediately. You will
need to call ``r.release_conn()`` on the response ``r`` to return
the connection back into the pool. If None, it takes the value of
back into the pool once a response is received (but will release if
you read the entire contents of the response such as when
`preload_content=True`). This is useful if you're not preloading
the response's content immediately. You will need to call
``r.release_conn()`` on the response ``r`` to return the connection
back into the pool. If None, it takes the value of
``response_kw.get('preload_content', True)``.
:param \**response_kw:
Expand Down

0 comments on commit 34119d0

Please sign in to comment.