Merge "py3: fix up listings on sharded containers"
This commit is contained in:
commit
3ec6ce2a0f
@ -16,6 +16,7 @@
|
|||||||
from swift import gettext_ as _
|
from swift import gettext_ as _
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
import six
|
||||||
from six.moves.urllib.parse import unquote
|
from six.moves.urllib.parse import unquote
|
||||||
|
|
||||||
from swift.common.utils import public, private, csv_append, Timestamp, \
|
from swift.common.utils import public, private, csv_append, Timestamp, \
|
||||||
@ -27,7 +28,8 @@ from swift.proxy.controllers.base import Controller, delay_denial, \
|
|||||||
cors_validation, set_info_cache, clear_info_cache
|
cors_validation, set_info_cache, clear_info_cache
|
||||||
from swift.common.storage_policy import POLICIES
|
from swift.common.storage_policy import POLICIES
|
||||||
from swift.common.swob import HTTPBadRequest, HTTPForbidden, \
|
from swift.common.swob import HTTPBadRequest, HTTPForbidden, \
|
||||||
HTTPNotFound, HTTPServiceUnavailable, str_to_wsgi, wsgi_to_bytes
|
HTTPNotFound, HTTPServiceUnavailable, str_to_wsgi, wsgi_to_str, \
|
||||||
|
bytes_to_wsgi
|
||||||
|
|
||||||
|
|
||||||
class ContainerController(Controller):
|
class ContainerController(Controller):
|
||||||
@ -162,8 +164,8 @@ class ContainerController(Controller):
|
|||||||
params.pop('states', None)
|
params.pop('states', None)
|
||||||
req.headers.pop('X-Backend-Record-Type', None)
|
req.headers.pop('X-Backend-Record-Type', None)
|
||||||
reverse = config_true_value(params.get('reverse'))
|
reverse = config_true_value(params.get('reverse'))
|
||||||
marker = params.get('marker')
|
marker = wsgi_to_str(params.get('marker'))
|
||||||
end_marker = params.get('end_marker')
|
end_marker = wsgi_to_str(params.get('end_marker'))
|
||||||
|
|
||||||
limit = req_limit
|
limit = req_limit
|
||||||
for shard_range in shard_ranges:
|
for shard_range in shard_ranges:
|
||||||
@ -176,9 +178,9 @@ class ContainerController(Controller):
|
|||||||
if objects:
|
if objects:
|
||||||
last_name = objects[-1].get('name',
|
last_name = objects[-1].get('name',
|
||||||
objects[-1].get('subdir', u''))
|
objects[-1].get('subdir', u''))
|
||||||
params['marker'] = last_name.encode('utf-8')
|
params['marker'] = bytes_to_wsgi(last_name.encode('utf-8'))
|
||||||
elif marker:
|
elif marker:
|
||||||
params['marker'] = marker
|
params['marker'] = str_to_wsgi(marker)
|
||||||
else:
|
else:
|
||||||
params['marker'] = ''
|
params['marker'] = ''
|
||||||
# Always set end_marker to ensure that misplaced objects beyond the
|
# Always set end_marker to ensure that misplaced objects beyond the
|
||||||
@ -186,7 +188,7 @@ class ContainerController(Controller):
|
|||||||
# object obscuring correctly placed objects in the next shard
|
# object obscuring correctly placed objects in the next shard
|
||||||
# range.
|
# range.
|
||||||
if end_marker and end_marker in shard_range:
|
if end_marker and end_marker in shard_range:
|
||||||
params['end_marker'] = end_marker
|
params['end_marker'] = str_to_wsgi(end_marker)
|
||||||
elif reverse:
|
elif reverse:
|
||||||
params['end_marker'] = str_to_wsgi(shard_range.lower_str)
|
params['end_marker'] = str_to_wsgi(shard_range.lower_str)
|
||||||
else:
|
else:
|
||||||
@ -213,13 +215,13 @@ class ContainerController(Controller):
|
|||||||
|
|
||||||
if limit <= 0:
|
if limit <= 0:
|
||||||
break
|
break
|
||||||
if (end_marker and reverse and
|
last_name = objects[-1].get('name',
|
||||||
(wsgi_to_bytes(end_marker) >=
|
objects[-1].get('subdir', u''))
|
||||||
objects[-1]['name'].encode('utf-8'))):
|
if six.PY2:
|
||||||
|
last_name = last_name.encode('utf8')
|
||||||
|
if end_marker and reverse and end_marker >= last_name:
|
||||||
break
|
break
|
||||||
if (end_marker and not reverse and
|
if end_marker and not reverse and end_marker <= last_name:
|
||||||
(wsgi_to_bytes(end_marker) <=
|
|
||||||
objects[-1]['name'].encode('utf-8'))):
|
|
||||||
break
|
break
|
||||||
|
|
||||||
resp.body = json.dumps(objects).encode('ascii')
|
resp.body = json.dumps(objects).encode('ascii')
|
||||||
|
@ -19,14 +19,15 @@ import socket
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from eventlet import Timeout
|
from eventlet import Timeout
|
||||||
|
import six
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
from swift.common.constraints import CONTAINER_LISTING_LIMIT
|
from swift.common.constraints import CONTAINER_LISTING_LIMIT
|
||||||
from swift.common.swob import Request
|
from swift.common.swob import Request, bytes_to_wsgi, str_to_wsgi, wsgi_quote
|
||||||
from swift.common.utils import ShardRange, Timestamp
|
from swift.common.utils import ShardRange, Timestamp
|
||||||
from swift.proxy import server as proxy_server
|
from swift.proxy import server as proxy_server
|
||||||
from swift.proxy.controllers.base import headers_to_container_info, Controller, \
|
from swift.proxy.controllers.base import headers_to_container_info, \
|
||||||
get_container_info
|
Controller, get_container_info
|
||||||
from test import annotate_failure
|
from test import annotate_failure
|
||||||
from test.unit import fake_http_connect, FakeRing, FakeMemcache, \
|
from test.unit import fake_http_connect, FakeRing, FakeMemcache, \
|
||||||
make_timestamp_iter
|
make_timestamp_iter
|
||||||
@ -435,13 +436,21 @@ class TestContainerController(TestRingBase):
|
|||||||
self._assert_responses('POST', POST_TEST_CASES)
|
self._assert_responses('POST', POST_TEST_CASES)
|
||||||
|
|
||||||
def _make_shard_objects(self, shard_range):
|
def _make_shard_objects(self, shard_range):
|
||||||
lower = ord(shard_range.lower[0]) if shard_range.lower else ord('@')
|
if six.PY2:
|
||||||
upper = ord(shard_range.upper[0]) if shard_range.upper else ord('z')
|
lower = ord(shard_range.lower.decode('utf8')[0]
|
||||||
|
if shard_range.lower else '@')
|
||||||
|
upper = ord(shard_range.upper.decode('utf8')[0]
|
||||||
|
if shard_range.upper else u'\U0001ffff')
|
||||||
|
else:
|
||||||
|
lower = ord(shard_range.lower[0] if shard_range.lower else '@')
|
||||||
|
upper = ord(shard_range.upper[0] if shard_range.upper
|
||||||
|
else '\U0001ffff')
|
||||||
|
|
||||||
objects = [{'name': chr(i), 'bytes': i, 'hash': 'hash%s' % chr(i),
|
objects = [{'name': six.unichr(i), 'bytes': i,
|
||||||
|
'hash': 'hash%s' % six.unichr(i),
|
||||||
'content_type': 'text/plain', 'deleted': 0,
|
'content_type': 'text/plain', 'deleted': 0,
|
||||||
'last_modified': next(self.ts_iter).isoformat}
|
'last_modified': next(self.ts_iter).isoformat}
|
||||||
for i in range(lower + 1, upper + 1)]
|
for i in range(lower + 1, upper + 1)][:1024]
|
||||||
return objects
|
return objects
|
||||||
|
|
||||||
def _check_GET_shard_listing(self, mock_responses, expected_objects,
|
def _check_GET_shard_listing(self, mock_responses, expected_objects,
|
||||||
@ -484,9 +493,12 @@ class TestContainerController(TestRingBase):
|
|||||||
with annotate_failure('Request check at index %d.' % i):
|
with annotate_failure('Request check at index %d.' % i):
|
||||||
# strip off /sdx/0/ from path
|
# strip off /sdx/0/ from path
|
||||||
self.assertEqual(exp_path, req['path'][7:])
|
self.assertEqual(exp_path, req['path'][7:])
|
||||||
self.assertEqual(
|
if six.PY2:
|
||||||
dict(exp_params, format='json'),
|
got_params = dict(urllib.parse.parse_qsl(req['qs'], True))
|
||||||
dict(urllib.parse.parse_qsl(req['qs'], True)))
|
else:
|
||||||
|
got_params = dict(urllib.parse.parse_qsl(
|
||||||
|
req['qs'], True, encoding='latin1'))
|
||||||
|
self.assertEqual(dict(exp_params, format='json'), got_params)
|
||||||
for k, v in exp_headers.items():
|
for k, v in exp_headers.items():
|
||||||
self.assertIn(k, req['headers'])
|
self.assertIn(k, req['headers'])
|
||||||
self.assertEqual(v, req['headers'][k])
|
self.assertEqual(v, req['headers'][k])
|
||||||
@ -517,10 +529,11 @@ class TestContainerController(TestRingBase):
|
|||||||
self.assertEqual(headers_to_container_info(info_hdrs), info)
|
self.assertEqual(headers_to_container_info(info_hdrs), info)
|
||||||
|
|
||||||
def test_GET_sharded_container(self):
|
def test_GET_sharded_container(self):
|
||||||
shard_bounds = (('', 'ham'), ('ham', 'pie'), ('pie', ''))
|
# Don't worry, ShardRange._encode takes care of unicode/bytes issues
|
||||||
|
shard_bounds = ('', 'ham', 'pie', u'\N{SNOWMAN}', u'\U0001F334', '')
|
||||||
shard_ranges = [
|
shard_ranges = [
|
||||||
ShardRange('.shards_a/c_%s' % upper, Timestamp.now(), lower, upper)
|
ShardRange('.shards_a/c_%s' % upper, Timestamp.now(), lower, upper)
|
||||||
for lower, upper in shard_bounds]
|
for lower, upper in zip(shard_bounds[:-1], shard_bounds[1:])]
|
||||||
sr_dicts = [dict(sr) for sr in shard_ranges]
|
sr_dicts = [dict(sr) for sr in shard_ranges]
|
||||||
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
|
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
|
||||||
shard_resp_hdrs = [
|
shard_resp_hdrs = [
|
||||||
@ -530,7 +543,7 @@ class TestContainerController(TestRingBase):
|
|||||||
sum([obj['bytes'] for obj in sr_objs[i]]),
|
sum([obj['bytes'] for obj in sr_objs[i]]),
|
||||||
'X-Container-Meta-Flavour': 'flavour%d' % i,
|
'X-Container-Meta-Flavour': 'flavour%d' % i,
|
||||||
'X-Backend-Storage-Policy-Index': 0}
|
'X-Backend-Storage-Policy-Index': 0}
|
||||||
for i in range(3)]
|
for i, _ in enumerate(shard_ranges)]
|
||||||
|
|
||||||
all_objects = []
|
all_objects = []
|
||||||
for objects in sr_objs:
|
for objects in sr_objs:
|
||||||
@ -556,7 +569,9 @@ class TestContainerController(TestRingBase):
|
|||||||
(200, sr_dicts, root_shard_resp_hdrs),
|
(200, sr_dicts, root_shard_resp_hdrs),
|
||||||
(200, sr_objs[0], shard_resp_hdrs[0]),
|
(200, sr_objs[0], shard_resp_hdrs[0]),
|
||||||
(200, sr_objs[1], shard_resp_hdrs[1]),
|
(200, sr_objs[1], shard_resp_hdrs[1]),
|
||||||
(200, sr_objs[2], shard_resp_hdrs[2])
|
(200, sr_objs[2], shard_resp_hdrs[2]),
|
||||||
|
(200, sr_objs[3], shard_resp_hdrs[3]),
|
||||||
|
(200, sr_objs[4], shard_resp_hdrs[4]),
|
||||||
]
|
]
|
||||||
expected_requests = [
|
expected_requests = [
|
||||||
# path, headers, params
|
# path, headers, params
|
||||||
@ -564,15 +579,29 @@ class TestContainerController(TestRingBase):
|
|||||||
dict(states='listing')), # 404
|
dict(states='listing')), # 404
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(states='listing')), # 200
|
dict(states='listing')), # 200
|
||||||
(shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
|
(wsgi_quote(str_to_wsgi(shard_ranges[0].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
dict(marker='', end_marker='ham\x00', limit=str(limit),
|
dict(marker='', end_marker='ham\x00', limit=str(limit),
|
||||||
states='listing')), # 200
|
states='listing')), # 200
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
|
(wsgi_quote(str_to_wsgi(shard_ranges[1].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
dict(marker='h', end_marker='pie\x00', states='listing',
|
dict(marker='h', end_marker='pie\x00', states='listing',
|
||||||
limit=str(limit - len(sr_objs[0])))), # 200
|
limit=str(limit - len(sr_objs[0])))), # 200
|
||||||
(shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
|
(wsgi_quote(str_to_wsgi(shard_ranges[2].name)),
|
||||||
dict(marker='p', end_marker='', states='listing',
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
limit=str(limit - len(sr_objs[0] + sr_objs[1])))) # 200
|
dict(marker='p', end_marker='\xe2\x98\x83\x00', states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[0] + sr_objs[1])))), # 200
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
|
dict(marker='\xd1\xb0', end_marker='\xf0\x9f\x8c\xb4\x00',
|
||||||
|
states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[0] + sr_objs[1]
|
||||||
|
+ sr_objs[2])))), # 200
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[4].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
|
dict(marker='\xe2\xa8\x83', end_marker='', states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[0] + sr_objs[1] + sr_objs[2]
|
||||||
|
+ sr_objs[3])))), # 200
|
||||||
]
|
]
|
||||||
|
|
||||||
resp = self._check_GET_shard_listing(
|
resp = self._check_GET_shard_listing(
|
||||||
@ -588,7 +617,7 @@ class TestContainerController(TestRingBase):
|
|||||||
(200, sr_dicts[:2] + [dict(root_range)], root_shard_resp_hdrs),
|
(200, sr_dicts[:2] + [dict(root_range)], root_shard_resp_hdrs),
|
||||||
(200, sr_objs[0], shard_resp_hdrs[0]),
|
(200, sr_objs[0], shard_resp_hdrs[0]),
|
||||||
(200, sr_objs[1], shard_resp_hdrs[1]),
|
(200, sr_objs[1], shard_resp_hdrs[1]),
|
||||||
(200, sr_objs[2], root_resp_hdrs)
|
(200, sr_objs[2] + sr_objs[3] + sr_objs[4], root_resp_hdrs)
|
||||||
]
|
]
|
||||||
expected_requests = [
|
expected_requests = [
|
||||||
# path, headers, params
|
# path, headers, params
|
||||||
@ -615,6 +644,8 @@ class TestContainerController(TestRingBase):
|
|||||||
mock_responses = [
|
mock_responses = [
|
||||||
# status, body, headers
|
# status, body, headers
|
||||||
(200, list(reversed(sr_dicts)), root_shard_resp_hdrs),
|
(200, list(reversed(sr_dicts)), root_shard_resp_hdrs),
|
||||||
|
(200, list(reversed(sr_objs[4])), shard_resp_hdrs[4]),
|
||||||
|
(200, list(reversed(sr_objs[3])), shard_resp_hdrs[3]),
|
||||||
(200, list(reversed(sr_objs[2])), shard_resp_hdrs[2]),
|
(200, list(reversed(sr_objs[2])), shard_resp_hdrs[2]),
|
||||||
(200, list(reversed(sr_objs[1])), shard_resp_hdrs[1]),
|
(200, list(reversed(sr_objs[1])), shard_resp_hdrs[1]),
|
||||||
(200, list(reversed(sr_objs[0])), shard_resp_hdrs[0]),
|
(200, list(reversed(sr_objs[0])), shard_resp_hdrs[0]),
|
||||||
@ -623,15 +654,31 @@ class TestContainerController(TestRingBase):
|
|||||||
# path, headers, params
|
# path, headers, params
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(states='listing', reverse='true')),
|
dict(states='listing', reverse='true')),
|
||||||
(shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
|
(wsgi_quote(str_to_wsgi(shard_ranges[4].name)),
|
||||||
dict(marker='', end_marker='pie', reverse='true',
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
limit=str(limit), states='listing')), # 200
|
dict(marker='', end_marker='\xf0\x9f\x8c\xb4', states='listing',
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
|
reverse='true', limit=str(limit))), # 200
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
|
dict(marker='\xf0\x9f\x8c\xb5', end_marker='\xe2\x98\x83',
|
||||||
|
states='listing', reverse='true',
|
||||||
|
limit=str(limit - len(sr_objs[4])))), # 200
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[2].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
|
dict(marker='\xe2\x98\x84', end_marker='pie', states='listing',
|
||||||
|
reverse='true',
|
||||||
|
limit=str(limit - len(sr_objs[4] + sr_objs[3])))), # 200
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[1].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
dict(marker='q', end_marker='ham', states='listing',
|
dict(marker='q', end_marker='ham', states='listing',
|
||||||
reverse='true', limit=str(limit - len(sr_objs[2])))), # 200
|
reverse='true',
|
||||||
(shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
|
limit=str(limit - len(sr_objs[4] + sr_objs[3]
|
||||||
|
+ sr_objs[2])))), # 200
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[0].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'},
|
||||||
dict(marker='i', end_marker='', states='listing', reverse='true',
|
dict(marker='i', end_marker='', states='listing', reverse='true',
|
||||||
limit=str(limit - len(sr_objs[2] + sr_objs[1])))), # 200
|
limit=str(limit - len(sr_objs[4] + sr_objs[3] + sr_objs[2]
|
||||||
|
+ sr_objs[1])))), # 200
|
||||||
]
|
]
|
||||||
|
|
||||||
resp = self._check_GET_shard_listing(
|
resp = self._check_GET_shard_listing(
|
||||||
@ -656,15 +703,18 @@ class TestContainerController(TestRingBase):
|
|||||||
dict(limit=str(limit), states='listing')), # 404
|
dict(limit=str(limit), states='listing')), # 404
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(limit=str(limit), states='listing')), # 200
|
dict(limit=str(limit), states='listing')), # 200
|
||||||
(shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
(wsgi_quote(str_to_wsgi(shard_ranges[0].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
dict(marker='', end_marker='ham\x00', states='listing',
|
dict(marker='', end_marker='ham\x00', states='listing',
|
||||||
limit=str(limit))),
|
limit=str(limit))),
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
(wsgi_quote(str_to_wsgi(shard_ranges[1].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
dict(marker='h', end_marker='pie\x00', states='listing',
|
dict(marker='h', end_marker='pie\x00', states='listing',
|
||||||
limit=str(limit - len(sr_objs[0])))),
|
limit=str(limit - len(sr_objs[0])))),
|
||||||
(shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
(wsgi_quote(str_to_wsgi(shard_ranges[2].name)),
|
||||||
dict(marker='p', end_marker='', states='listing',
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
limit=str(limit - len(sr_objs[0] + sr_objs[1]))))
|
dict(marker='p', end_marker='\xe2\x98\x83\x00', states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[0] + sr_objs[1])))),
|
||||||
]
|
]
|
||||||
resp = self._check_GET_shard_listing(
|
resp = self._check_GET_shard_listing(
|
||||||
mock_responses, expected_objects, expected_requests,
|
mock_responses, expected_objects, expected_requests,
|
||||||
@ -672,31 +722,35 @@ class TestContainerController(TestRingBase):
|
|||||||
self.check_response(resp, root_resp_hdrs)
|
self.check_response(resp, root_resp_hdrs)
|
||||||
|
|
||||||
# GET with marker
|
# GET with marker
|
||||||
marker = sr_objs[1][2]['name']
|
marker = bytes_to_wsgi(sr_objs[3][2]['name'].encode('utf8'))
|
||||||
first_included = len(sr_objs[0]) + 2
|
first_included = (len(sr_objs[0]) + len(sr_objs[1])
|
||||||
|
+ len(sr_objs[2]) + 2)
|
||||||
limit = CONTAINER_LISTING_LIMIT
|
limit = CONTAINER_LISTING_LIMIT
|
||||||
expected_objects = all_objects[first_included:]
|
expected_objects = all_objects[first_included:]
|
||||||
mock_responses = [
|
mock_responses = [
|
||||||
(404, '', {}),
|
(404, '', {}),
|
||||||
(200, sr_dicts[1:], root_shard_resp_hdrs),
|
(200, sr_dicts[3:], root_shard_resp_hdrs),
|
||||||
(404, '', {}),
|
(404, '', {}),
|
||||||
(200, sr_objs[1][2:], shard_resp_hdrs[1]),
|
(200, sr_objs[3][2:], shard_resp_hdrs[3]),
|
||||||
(200, sr_objs[2], shard_resp_hdrs[2])
|
(200, sr_objs[4], shard_resp_hdrs[4]),
|
||||||
]
|
]
|
||||||
expected_requests = [
|
expected_requests = [
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(marker=marker, states='listing')), # 404
|
dict(marker=marker, states='listing')), # 404
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(marker=marker, states='listing')), # 200
|
dict(marker=marker, states='listing')), # 200
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 404
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
dict(marker=marker, end_marker='pie\x00', states='listing',
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
limit=str(limit))),
|
dict(marker=marker, end_marker='\xf0\x9f\x8c\xb4\x00',
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
states='listing', limit=str(limit))),
|
||||||
dict(marker=marker, end_marker='pie\x00', states='listing',
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
limit=str(limit))),
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
(shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
dict(marker=marker, end_marker='\xf0\x9f\x8c\xb4\x00',
|
||||||
dict(marker='p', end_marker='', states='listing',
|
states='listing', limit=str(limit))),
|
||||||
limit=str(limit - len(sr_objs[1][2:])))),
|
(wsgi_quote(str_to_wsgi(shard_ranges[4].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
|
dict(marker='\xe2\xa8\x83', end_marker='', states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[3][2:])))),
|
||||||
]
|
]
|
||||||
resp = self._check_GET_shard_listing(
|
resp = self._check_GET_shard_listing(
|
||||||
mock_responses, expected_objects, expected_requests,
|
mock_responses, expected_objects, expected_requests,
|
||||||
@ -704,30 +758,51 @@ class TestContainerController(TestRingBase):
|
|||||||
self.check_response(resp, root_resp_hdrs)
|
self.check_response(resp, root_resp_hdrs)
|
||||||
|
|
||||||
# GET with end marker
|
# GET with end marker
|
||||||
end_marker = sr_objs[1][6]['name']
|
end_marker = bytes_to_wsgi(sr_objs[3][6]['name'].encode('utf8'))
|
||||||
first_excluded = len(sr_objs[0]) + 6
|
first_excluded = (len(sr_objs[0]) + len(sr_objs[1])
|
||||||
|
+ len(sr_objs[2]) + 6)
|
||||||
expected_objects = all_objects[:first_excluded]
|
expected_objects = all_objects[:first_excluded]
|
||||||
mock_responses = [
|
mock_responses = [
|
||||||
(404, '', {}),
|
(404, '', {}),
|
||||||
(200, sr_dicts[:2], root_shard_resp_hdrs),
|
(200, sr_dicts[:4], root_shard_resp_hdrs),
|
||||||
(200, sr_objs[0], shard_resp_hdrs[0]),
|
(200, sr_objs[0], shard_resp_hdrs[0]),
|
||||||
(404, '', {}),
|
(404, '', {}),
|
||||||
(200, sr_objs[1][:6], shard_resp_hdrs[1])
|
(200, sr_objs[1], shard_resp_hdrs[1]),
|
||||||
|
(200, sr_objs[2], shard_resp_hdrs[2]),
|
||||||
|
(404, '', {}),
|
||||||
|
(200, sr_objs[3][:6], shard_resp_hdrs[3]),
|
||||||
]
|
]
|
||||||
expected_requests = [
|
expected_requests = [
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(end_marker=end_marker, states='listing')), # 404
|
dict(end_marker=end_marker, states='listing')), # 404
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(end_marker=end_marker, states='listing')), # 200
|
dict(end_marker=end_marker, states='listing')), # 200
|
||||||
(shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
(wsgi_quote(str_to_wsgi(shard_ranges[0].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
dict(marker='', end_marker='ham\x00', states='listing',
|
dict(marker='', end_marker='ham\x00', states='listing',
|
||||||
limit=str(limit))),
|
limit=str(limit))),
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 404
|
(wsgi_quote(str_to_wsgi(shard_ranges[1].name)),
|
||||||
dict(marker='h', end_marker=end_marker, states='listing',
|
{'X-Backend-Record-Type': 'auto'}, # 404
|
||||||
|
dict(marker='h', end_marker='pie\x00', states='listing',
|
||||||
limit=str(limit - len(sr_objs[0])))),
|
limit=str(limit - len(sr_objs[0])))),
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
(wsgi_quote(str_to_wsgi(shard_ranges[1].name)),
|
||||||
dict(marker='h', end_marker=end_marker, states='listing',
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
|
dict(marker='h', end_marker='pie\x00', states='listing',
|
||||||
limit=str(limit - len(sr_objs[0])))),
|
limit=str(limit - len(sr_objs[0])))),
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[2].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
|
dict(marker='p', end_marker='\xe2\x98\x83\x00', states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[0] + sr_objs[1])))),
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 404
|
||||||
|
dict(marker='\xd1\xb0', end_marker=end_marker, states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[0] + sr_objs[1]
|
||||||
|
+ sr_objs[2])))),
|
||||||
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
|
dict(marker='\xd1\xb0', end_marker=end_marker, states='listing',
|
||||||
|
limit=str(limit - len(sr_objs[0] + sr_objs[1]
|
||||||
|
+ sr_objs[2])))),
|
||||||
]
|
]
|
||||||
resp = self._check_GET_shard_listing(
|
resp = self._check_GET_shard_listing(
|
||||||
mock_responses, expected_objects, expected_requests,
|
mock_responses, expected_objects, expected_requests,
|
||||||
@ -738,14 +813,15 @@ class TestContainerController(TestRingBase):
|
|||||||
limit = 2
|
limit = 2
|
||||||
expected_objects = all_objects[first_included:first_excluded]
|
expected_objects = all_objects[first_included:first_excluded]
|
||||||
mock_responses = [
|
mock_responses = [
|
||||||
(200, sr_dicts[1:2], root_shard_resp_hdrs),
|
(200, sr_dicts[3:4], root_shard_resp_hdrs),
|
||||||
(200, sr_objs[1][2:6], shard_resp_hdrs[1])
|
(200, sr_objs[3][2:6], shard_resp_hdrs[1])
|
||||||
]
|
]
|
||||||
expected_requests = [
|
expected_requests = [
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(states='listing', limit=str(limit),
|
dict(states='listing', limit=str(limit),
|
||||||
marker=marker, end_marker=end_marker)), # 200
|
marker=marker, end_marker=end_marker)), # 200
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
dict(marker=marker, end_marker=end_marker, states='listing',
|
dict(marker=marker, end_marker=end_marker, states='listing',
|
||||||
limit=str(limit))),
|
limit=str(limit))),
|
||||||
]
|
]
|
||||||
@ -758,14 +834,15 @@ class TestContainerController(TestRingBase):
|
|||||||
# reverse with marker, end_marker
|
# reverse with marker, end_marker
|
||||||
expected_objects.reverse()
|
expected_objects.reverse()
|
||||||
mock_responses = [
|
mock_responses = [
|
||||||
(200, sr_dicts[1:2], root_shard_resp_hdrs),
|
(200, sr_dicts[3:4], root_shard_resp_hdrs),
|
||||||
(200, list(reversed(sr_objs[1][2:6])), shard_resp_hdrs[1])
|
(200, list(reversed(sr_objs[3][2:6])), shard_resp_hdrs[1])
|
||||||
]
|
]
|
||||||
expected_requests = [
|
expected_requests = [
|
||||||
('a/c', {'X-Backend-Record-Type': 'auto'},
|
('a/c', {'X-Backend-Record-Type': 'auto'},
|
||||||
dict(marker=end_marker, reverse='true', end_marker=marker,
|
dict(marker=end_marker, reverse='true', end_marker=marker,
|
||||||
limit=str(limit), states='listing',)), # 200
|
limit=str(limit), states='listing',)), # 200
|
||||||
(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
|
(wsgi_quote(str_to_wsgi(shard_ranges[3].name)),
|
||||||
|
{'X-Backend-Record-Type': 'auto'}, # 200
|
||||||
dict(marker=end_marker, end_marker=marker, states='listing',
|
dict(marker=end_marker, end_marker=marker, states='listing',
|
||||||
limit=str(limit), reverse='true')),
|
limit=str(limit), reverse='true')),
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user