Add one more test for ssync_receiver

To prevent 409 conflict on a primary node during ssyncing,
ssync-receiver should add x-ssync-backend-frag-index generated from
x-ssync-backend-node-index of the SSYNC replication request header.
The change is done by previous work[1], but we need more test for that.

This patch addes one more assertion if the x-ssync-backend-frag-index
is in the ssync subrequest correctly.

*BONUS*
Fix some weird mock and add some sanities.

1: https://review.openstack.org/#/c/191521/

Change-Id: I27aff713c69017c0bc4c60b4833184e1285595d7
This commit is contained in:
Kota Tsuyuzaki 2015-06-22 23:24:19 -07:00
parent 66db3bc2ce
commit 81ceee056d

View File

@ -1064,7 +1064,7 @@ class TestReceiver(unittest.TestCase):
@server.public @server.public
def _DELETE(request): def _DELETE(request):
if request.path == '/device/partition/a/c/works': if request.path == '/device/partition/a/c/works':
return swob.HTTPOk() return swob.HTTPNoContent()
else: else:
return swob.HTTPInternalServerError() return swob.HTTPInternalServerError()
@ -1179,7 +1179,7 @@ class TestReceiver(unittest.TestCase):
def _PUT(request): def _PUT(request):
_PUT_request[0] = request _PUT_request[0] = request
request.read_body = request.environ['wsgi.input'].read() request.read_body = request.environ['wsgi.input'].read()
return swob.HTTPOk() return swob.HTTPCreated()
with mock.patch.object(self.controller, 'PUT', _PUT): with mock.patch.object(self.controller, 'PUT', _PUT):
self.controller.logger = mock.MagicMock() self.controller.logger = mock.MagicMock()
@ -1204,6 +1204,7 @@ class TestReceiver(unittest.TestCase):
self.assertEqual(resp.status_int, 200) self.assertEqual(resp.status_int, 200)
self.assertFalse(self.controller.logger.exception.called) self.assertFalse(self.controller.logger.exception.called)
self.assertFalse(self.controller.logger.error.called) self.assertFalse(self.controller.logger.error.called)
self.assertEquals(len(_PUT_request), 1) # sanity
req = _PUT_request[0] req = _PUT_request[0]
self.assertEqual(req.path, '/device/partition/a/c/o') self.assertEqual(req.path, '/device/partition/a/c/o')
self.assertEqual(req.content_length, 1) self.assertEqual(req.content_length, 1)
@ -1231,7 +1232,7 @@ class TestReceiver(unittest.TestCase):
def _PUT(request): def _PUT(request):
_PUT_request[0] = request _PUT_request[0] = request
request.read_body = request.environ['wsgi.input'].read() request.read_body = request.environ['wsgi.input'].read()
return swob.HTTPOk() return swob.HTTPCreated()
with mock.patch.object(self.controller, 'PUT', _PUT): with mock.patch.object(self.controller, 'PUT', _PUT):
self.controller.logger = mock.MagicMock() self.controller.logger = mock.MagicMock()
@ -1257,6 +1258,7 @@ class TestReceiver(unittest.TestCase):
self.assertEqual(resp.status_int, 200) self.assertEqual(resp.status_int, 200)
self.assertFalse(self.controller.logger.exception.called) self.assertFalse(self.controller.logger.exception.called)
self.assertFalse(self.controller.logger.error.called) self.assertFalse(self.controller.logger.error.called)
self.assertEquals(len(_PUT_request), 1) # sanity
req = _PUT_request[0] req = _PUT_request[0]
self.assertEqual(req.path, '/device/partition/a/c/o') self.assertEqual(req.path, '/device/partition/a/c/o')
self.assertEqual(req.content_length, 1) self.assertEqual(req.content_length, 1)
@ -1274,13 +1276,71 @@ class TestReceiver(unittest.TestCase):
'content-encoding specialty-header')}) 'content-encoding specialty-header')})
self.assertEqual(req.read_body, '1') self.assertEqual(req.read_body, '1')
def test_UPDATES_PUT_with_storage_policy_and_node_index(self):
# update router post policy patch
self.controller._diskfile_router = diskfile.DiskFileRouter(
self.conf, self.controller.logger)
_PUT_request = [None]
@server.public
def _PUT(request):
_PUT_request[0] = request
request.read_body = request.environ['wsgi.input'].read()
return swob.HTTPCreated()
with mock.patch.object(self.controller, 'PUT', _PUT):
self.controller.logger = mock.MagicMock()
req = swob.Request.blank(
'/device/partition',
environ={'REQUEST_METHOD': 'SSYNC',
'HTTP_X_BACKEND_SSYNC_NODE_INDEX': '7',
'HTTP_X_BACKEND_SSYNC_FRAG_INDEX': '7',
'HTTP_X_BACKEND_STORAGE_POLICY_INDEX': '0'},
body=':MISSING_CHECK: START\r\n:MISSING_CHECK: END\r\n'
':UPDATES: START\r\n'
'PUT /a/c/o\r\n'
'Content-Length: 1\r\n'
'X-Timestamp: 1364456113.12344\r\n'
'X-Object-Meta-Test1: one\r\n'
'Content-Encoding: gzip\r\n'
'Specialty-Header: value\r\n'
'\r\n'
'1')
resp = req.get_response(self.controller)
self.assertEqual(
self.body_lines(resp.body),
[':MISSING_CHECK: START', ':MISSING_CHECK: END',
':UPDATES: START', ':UPDATES: END'])
self.assertEqual(resp.status_int, 200)
self.assertFalse(self.controller.logger.exception.called)
self.assertFalse(self.controller.logger.error.called)
self.assertEquals(len(_PUT_request), 1) # sanity
req = _PUT_request[0]
self.assertEqual(req.path, '/device/partition/a/c/o')
self.assertEqual(req.content_length, 1)
self.assertEqual(req.headers, {
'Content-Length': '1',
'X-Timestamp': '1364456113.12344',
'X-Object-Meta-Test1': 'one',
'Content-Encoding': 'gzip',
'Specialty-Header': 'value',
'Host': 'localhost:80',
'X-Backend-Storage-Policy-Index': '0',
'X-Backend-Ssync-Frag-Index': '7',
'X-Backend-Replication': 'True',
'X-Backend-Replication-Headers': (
'content-length x-timestamp x-object-meta-test1 '
'content-encoding specialty-header')})
self.assertEqual(req.read_body, '1')
def test_UPDATES_DELETE(self): def test_UPDATES_DELETE(self):
_DELETE_request = [None] _DELETE_request = [None]
@server.public @server.public
def _DELETE(request): def _DELETE(request):
_DELETE_request[0] = request _DELETE_request[0] = request
return swob.HTTPOk() return swob.HTTPNoContent()
with mock.patch.object(self.controller, 'DELETE', _DELETE): with mock.patch.object(self.controller, 'DELETE', _DELETE):
self.controller.logger = mock.MagicMock() self.controller.logger = mock.MagicMock()
@ -1300,6 +1360,7 @@ class TestReceiver(unittest.TestCase):
self.assertEqual(resp.status_int, 200) self.assertEqual(resp.status_int, 200)
self.assertFalse(self.controller.logger.exception.called) self.assertFalse(self.controller.logger.exception.called)
self.assertFalse(self.controller.logger.error.called) self.assertFalse(self.controller.logger.error.called)
self.assertEquals(len(_DELETE_request), 1) # sanity
req = _DELETE_request[0] req = _DELETE_request[0]
self.assertEqual(req.path, '/device/partition/a/c/o') self.assertEqual(req.path, '/device/partition/a/c/o')
self.assertEqual(req.headers, { self.assertEqual(req.headers, {
@ -1335,6 +1396,7 @@ class TestReceiver(unittest.TestCase):
self.assertEqual(resp.status_int, 200) self.assertEqual(resp.status_int, 200)
self.controller.logger.exception.assert_called_once_with( self.controller.logger.exception.assert_called_once_with(
'None/device/partition EXCEPTION in replication.Receiver') 'None/device/partition EXCEPTION in replication.Receiver')
self.assertEquals(len(_BONK_request), 1) # sanity
self.assertEqual(_BONK_request[0], None) self.assertEqual(_BONK_request[0], None)
def test_UPDATES_multiple(self): def test_UPDATES_multiple(self):
@ -1344,12 +1406,12 @@ class TestReceiver(unittest.TestCase):
def _PUT(request): def _PUT(request):
_requests.append(request) _requests.append(request)
request.read_body = request.environ['wsgi.input'].read() request.read_body = request.environ['wsgi.input'].read()
return swob.HTTPOk() return swob.HTTPCreated()
@server.public @server.public
def _DELETE(request): def _DELETE(request):
_requests.append(request) _requests.append(request)
return swob.HTTPOk() return swob.HTTPNoContent()
with contextlib.nested( with contextlib.nested(
mock.patch.object(self.controller, 'PUT', _PUT), mock.patch.object(self.controller, 'PUT', _PUT),
@ -1395,6 +1457,7 @@ class TestReceiver(unittest.TestCase):
self.assertEqual(resp.status_int, 200) self.assertEqual(resp.status_int, 200)
self.assertFalse(self.controller.logger.exception.called) self.assertFalse(self.controller.logger.exception.called)
self.assertFalse(self.controller.logger.error.called) self.assertFalse(self.controller.logger.error.called)
self.assertEquals(len(_requests), 6) # sanity
req = _requests.pop(0) req = _requests.pop(0)
self.assertEqual(req.method, 'PUT') self.assertEqual(req.method, 'PUT')
self.assertEqual(req.path, '/device/partition/a/c/o1') self.assertEqual(req.path, '/device/partition/a/c/o1')
@ -1519,6 +1582,7 @@ class TestReceiver(unittest.TestCase):
self.assertEqual(resp.status_int, 200) self.assertEqual(resp.status_int, 200)
self.assertFalse(self.controller.logger.exception.called) self.assertFalse(self.controller.logger.exception.called)
self.assertFalse(self.controller.logger.error.called) self.assertFalse(self.controller.logger.error.called)
self.assertEquals(len(_requests), 2) # sanity
req = _requests.pop(0) req = _requests.pop(0)
self.assertEqual(req.path, '/device/partition/a/c/o1') self.assertEqual(req.path, '/device/partition/a/c/o1')
self.assertEqual(req.content_length, 3) self.assertEqual(req.content_length, 3)