Don't trust X-Object-Meta-Mtime

Still use it if we can, but stop throwing ValueErrors if it's garbage.

Change-Id: I2cf25b535ad62cfacb7561954a92a4a73d91000a
This commit is contained in:
Tim Burke 2016-01-29 16:50:15 -08:00
parent 6f431ee065
commit 337570a03a
2 changed files with 99 additions and 4 deletions
swiftclient
tests/unit

@ -1162,11 +1162,15 @@ class SwiftService(object):
if fp is not None:
fp.close()
if 'x-object-meta-mtime' in headers and not no_file:
mtime = float(headers['x-object-meta-mtime'])
if options['out_file']:
utime(options['out_file'], (mtime, mtime))
try:
mtime = float(headers['x-object-meta-mtime'])
except ValueError:
pass # no real harm; couldn't trust it anyway
else:
utime(path, (mtime, mtime))
if options['out_file']:
utime(options['out_file'], (mtime, mtime))
else:
utime(path, (mtime, mtime))
res = {
'action': 'download_object',

@ -1535,6 +1535,97 @@ class TestServiceDownload(_TestServiceBase):
)
self._assertDictEqual(expected_r, actual_r)
def test_download_object_job_with_mtime(self):
mock_conn = self._get_mock_connection()
objcontent = six.BytesIO(b'objcontent')
mock_conn.get_object.side_effect = [
({'content-type': 'text/plain',
'etag': '2cbbfe139a744d6abbe695e17f3c1991',
'x-object-meta-mtime': '1454113727.682512'},
objcontent)
]
expected_r = self._get_expected({
'success': True,
'start_time': 1,
'finish_time': 2,
'headers_receipt': 3,
'auth_end_time': 4,
'read_length': len(b'objcontent'),
})
with mock.patch.object(builtins, 'open') as mock_open, \
mock.patch('swiftclient.service.utime') as mock_utime:
written_content = Mock()
mock_open.return_value = written_content
s = SwiftService()
_opts = self.opts.copy()
_opts['no_download'] = False
actual_r = s._download_object_job(
mock_conn, 'test_c', 'test_o', _opts)
actual_r = dict( # Need to override the times we got from the call
actual_r,
**{
'start_time': 1,
'finish_time': 2,
'headers_receipt': 3
}
)
mock_open.assert_called_once_with('test_o', 'wb')
mock_utime.assert_called_once_with(
'test_o', (1454113727.682512, 1454113727.682512))
written_content.write.assert_called_once_with(b'objcontent')
mock_conn.get_object.assert_called_once_with(
'test_c', 'test_o', resp_chunk_size=65536, headers={},
response_dict={}
)
self._assertDictEqual(expected_r, actual_r)
def test_download_object_job_bad_mtime(self):
mock_conn = self._get_mock_connection()
objcontent = six.BytesIO(b'objcontent')
mock_conn.get_object.side_effect = [
({'content-type': 'text/plain',
'etag': '2cbbfe139a744d6abbe695e17f3c1991',
'x-object-meta-mtime': 'foo'},
objcontent)
]
expected_r = self._get_expected({
'success': True,
'start_time': 1,
'finish_time': 2,
'headers_receipt': 3,
'auth_end_time': 4,
'read_length': len(b'objcontent'),
})
with mock.patch.object(builtins, 'open') as mock_open, \
mock.patch('swiftclient.service.utime') as mock_utime:
written_content = Mock()
mock_open.return_value = written_content
s = SwiftService()
_opts = self.opts.copy()
_opts['no_download'] = False
actual_r = s._download_object_job(
mock_conn, 'test_c', 'test_o', _opts)
actual_r = dict( # Need to override the times we got from the call
actual_r,
**{
'start_time': 1,
'finish_time': 2,
'headers_receipt': 3
}
)
mock_open.assert_called_once_with('test_o', 'wb')
self.assertEqual(0, len(mock_utime.mock_calls))
written_content.write.assert_called_once_with(b'objcontent')
mock_conn.get_object.assert_called_once_with(
'test_c', 'test_o', resp_chunk_size=65536, headers={},
response_dict={}
)
self._assertDictEqual(expected_r, actual_r)
def test_download_object_job_exception(self):
mock_conn = self._get_mock_connection()
mock_conn.get_object = Mock(side_effect=self.exc)