summaryrefslogtreecommitdiff
path: root/tests/functional/test_swiftclient.py
diff options
context:
space:
mode:
authorStuart McLaren <stuart.mclaren@hp.com>2015-03-04 14:31:00 +0000
committerAlistair Coles <alistair.coles@hpe.com>2016-01-08 17:12:02 +0000
commit4af623bcf171a63240849b84b9359a4f74471455 (patch)
tree5d44a4d43577cb71fa74ba70fd9d5b1ff84c42b5 /tests/functional/test_swiftclient.py
parentd1e310958801c1e058a933a43b2c7e9552e85772 (diff)
downloadpython-swiftclient-4af623bcf171a63240849b84b9359a4f74471455.tar.gz
Retry download of object body
Currently the swift client retries establishing a connection to the server (by default up to 5 times). However, when downloading an object, once the connection has been established and the inital headers have been returned, no attempt is made to retry. So, for example, if 99MB of a 100MB object have been downloaded and the connection is then lost, the download will fail. This patch changes the behaviour to re-establish the connection and fetch the remaining bytes using the 'Range' header to offset. Data retry is not yet supported if the original request is for a subset of the object data (ie uses the 'Range' header), or if resp_chunk_size has not been set. The object's etag is checked using If-Match to make sure the object data hasn't changed since the start of the download. Change-Id: Iab47f10081ff39f6d344dbc2479cbc3bfd1c5b29
Diffstat (limited to 'tests/functional/test_swiftclient.py')
-rw-r--r--tests/functional/test_swiftclient.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/tests/functional/test_swiftclient.py b/tests/functional/test_swiftclient.py
index ef1b9d5..5f9e271 100644
--- a/tests/functional/test_swiftclient.py
+++ b/tests/functional/test_swiftclient.py
@@ -333,6 +333,58 @@ class TestFunctional(testtools.TestCase):
hdrs, body = self.conn.get_object(self.containername, self.objectname)
self.assertEqual("should tolerate empty chunks", body)
+ def test_download_object_retry_chunked(self):
+ resp_chunk_size = 2
+ hdrs, body = self.conn.get_object(self.containername,
+ self.objectname,
+ resp_chunk_size=resp_chunk_size)
+ data = next(body)
+ self.assertEqual(self.test_data[:resp_chunk_size], data)
+ self.assertTrue(1, self.conn.attempts)
+ for chunk in body.resp:
+ # Flush remaining data from underlying response
+ # (simulate a dropped connection)
+ pass
+ # Trigger the retry
+ for chunk in body:
+ data += chunk
+ self.assertEqual(self.test_data, data)
+ self.assertEqual(2, self.conn.attempts)
+
+ def test_download_object_retry_chunked_auth_failure(self):
+ resp_chunk_size = 2
+ self.conn.token = 'invalid'
+ hdrs, body = self.conn.get_object(self.containername,
+ self.objectname,
+ resp_chunk_size=resp_chunk_size)
+ self.assertEqual(2, self.conn.attempts)
+ for chunk in body.resp:
+ # Flush remaining data from underlying response
+ # (simulate a dropped connection)
+ pass
+
+ self.conn.token = 'invalid'
+ data = next(body)
+ self.assertEqual(4, self.conn.attempts)
+
+ for chunk in body:
+ data += chunk
+
+ self.assertEqual(self.test_data, data)
+ self.assertEqual(4, self.conn.attempts)
+
+ def test_download_object_non_chunked(self):
+ hdrs, body = self.conn.get_object(self.containername, self.objectname)
+ data = body
+ self.assertEqual(self.test_data, data)
+ self.assertTrue(1, self.conn.attempts)
+
+ hdrs, body = self.conn.get_object(self.containername, self.objectname,
+ resp_chunk_size=0)
+ data = body
+ self.assertEqual(self.test_data, data)
+ self.assertTrue(1, self.conn.attempts)
+
def test_post_account(self):
self.conn.post_account({'x-account-meta-data': 'Something'})
headers = self.conn.head_account()