Correctly handle keys starting with the delimiter.

When processing keys where the names start with the delimiter
character, swift should list only the delimiter character. To get the
list of nested keys, the caller should also supply the prefix which is
equal to the delimiter.

Added a functional test and unit tests to verify this behavior.

Fixes Bug: 1475018

Change-Id: I27701a31bfa22842c272b7781738e8c546b82cbc
This commit is contained in:
Timur Alperovich 2015-07-15 14:22:45 -07:00 committed by Timur Alperovich
parent a3570877d8
commit 432e280aef
4 changed files with 42 additions and 1 deletions

View File

@ -674,7 +674,7 @@ class ContainerBroker(DatabaseBroker):
marker = name[:end] + chr(ord(delimiter) + 1)
curs.close()
break
elif end > 0:
elif end >= 0:
if reverse:
end_marker = name[:end + 1]
else:

View File

@ -610,6 +610,20 @@ class TestContainer(Base):
'reverse': 'yes'})
self.assertEqual(results, ['baza', 'bar'])
def testLeadingDelimiter(self):
cont = self.env.account.container(Utils.create_name())
self.assertTrue(cont.create())
delimiter = '/'
files = ['test', delimiter.join(['', 'test', 'bar']),
delimiter.join(['', 'test', 'bar', 'foo'])]
for f in files:
file_item = cont.file(f)
self.assertTrue(file_item.write_random())
results = cont.files(parms={'delimiter': delimiter})
self.assertEqual(results, [delimiter, 'test'])
def testCreate(self):
cont = self.env.account.container(Utils.create_name())
self.assertTrue(cont.create())

View File

@ -1187,6 +1187,9 @@ class TestContainerBroker(unittest.TestCase):
listing = broker.list_objects_iter(100, None, None, '/pets/fish/', '/')
self.assertEqual([row[0] for row in listing],
['/pets/fish/a', '/pets/fish/b'])
listing = broker.list_objects_iter(100, None, None, None, '/')
self.assertEqual([row[0] for row in listing],
['/'])
def test_list_objects_iter_order_and_reverse(self):
# Test ContainerBroker.list_objects_iter

View File

@ -2093,6 +2093,30 @@ class TestContainerController(unittest.TestCase):
{"subdir": "US-TX-"},
{"subdir": "US-UT-"}])
def test_GET_leading_delimiter(self):
req = Request.blank(
'/sda1/p/a/c', environ={'REQUEST_METHOD': 'PUT',
'HTTP_X_TIMESTAMP': '0'})
resp = req.get_response(self.controller)
for i in ('US-TX-A', 'US-TX-B', '-UK', '-CH'):
req = Request.blank(
'/sda1/p/a/c/%s' % i,
environ={
'REQUEST_METHOD': 'PUT', 'HTTP_X_TIMESTAMP': '1',
'HTTP_X_CONTENT_TYPE': 'text/plain', 'HTTP_X_ETAG': 'x',
'HTTP_X_SIZE': 0})
self._update_object_put_headers(req)
resp = req.get_response(self.controller)
self.assertEqual(resp.status_int, 201)
req = Request.blank(
'/sda1/p/a/c?delimiter=-&format=json',
environ={'REQUEST_METHOD': 'GET'})
resp = req.get_response(self.controller)
self.assertEqual(
json.loads(resp.body),
[{"subdir": "-"},
{"subdir": "US-"}])
def test_GET_delimiter_xml(self):
req = Request.blank(
'/sda1/p/a/c', environ={'REQUEST_METHOD': 'PUT',