summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/__init__.py36
-rw-r--r--test/functional/swift_test_client.py97
-rw-r--r--test/functional/tests.py668
-rw-r--r--test/functionalnosetests/swift_testing.py42
-rwxr-xr-xtest/functionalnosetests/test_account.py43
-rwxr-xr-xtest/functionalnosetests/test_container.py149
-rwxr-xr-xtest/functionalnosetests/test_object.py211
-rw-r--r--test/unit/__init__.py103
-rw-r--r--test/unit/common/test_fs_utils.py73
-rw-r--r--test/unit/obj/test_diskfile.py431
-rw-r--r--test/unit/proxy/controllers/test_account.py24
-rw-r--r--test/unit/proxy/controllers/test_base.py160
-rw-r--r--test/unit/proxy/controllers/test_container.py24
-rwxr-xr-xtest/unit/proxy/controllers/test_obj.py64
-rw-r--r--test/unit/proxy/test_server.py904
15 files changed, 1811 insertions, 1218 deletions
diff --git a/test/__init__.py b/test/__init__.py
index 9095348..7eb5f47 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -1,13 +1,43 @@
+# Copyright (c) 2010-2012 OpenStack Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
# See http://code.google.com/p/python-nose/issues/detail?id=373
# The code below enables nosetests to work with i18n _() blocks
-import __builtin__
import sys
import os
+try:
+ from unittest.util import safe_repr
+except ImportError:
+ # Probably py26
+ _MAX_LENGTH = 80
-from swift.common.utils import readconf
+ def safe_repr(obj, short=False):
+ try:
+ result = repr(obj)
+ except Exception:
+ result = object.__repr__(obj)
+ if not short or len(result) < _MAX_LENGTH:
+ return result
+ return result[:_MAX_LENGTH] + ' [truncated]...'
-setattr(__builtin__, '_', lambda x: x)
+# make unittests pass on all locale
+import swift
+setattr(swift, 'gettext_', lambda x: x)
+
+from swift.common.utils import readconf
# Work around what seems to be a Python bug.
diff --git a/test/functional/swift_test_client.py b/test/functional/swift_test_client.py
index daea902..2a161ac 100644
--- a/test/functional/swift_test_client.py
+++ b/test/functional/swift_test_client.py
@@ -1,19 +1,4 @@
-# Copyright (c) 2010-2013 OpenStack, LLC.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Copyright (c) 2013 Red Hat, Inc.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -43,6 +28,8 @@ from nose import SkipTest
from xml.dom import minidom
from swiftclient import get_auth
+from test import safe_repr
+
class AuthenticationFailed(Exception):
pass
@@ -146,12 +133,10 @@ class Connection(object):
auth_netloc = "%s:%d" % (self.auth_host, self.auth_port)
auth_url = auth_scheme + auth_netloc + auth_path
- (storage_url, storage_token) = get_auth(auth_url,
- auth_user, self.password,
- snet=False,
- tenant_name=self.account,
- auth_version=self.auth_version,
- os_options={})
+ (storage_url, storage_token) = get_auth(
+ auth_url, auth_user, self.password, snet=False,
+ tenant_name=self.account, auth_version=self.auth_version,
+ os_options={})
if not (storage_url and storage_token):
raise AuthenticationFailed()
@@ -233,18 +218,22 @@ class Connection(object):
self.response = None
try_count = 0
+ fail_messages = []
while try_count < 5:
try_count += 1
try:
self.response = try_request()
- except httplib.HTTPException:
+ except httplib.HTTPException as e:
+ fail_messages.append(safe_repr(e))
continue
if self.response.status == 401:
+ fail_messages.append("Response 401")
self.authenticate()
continue
elif self.response.status == 503:
+ fail_messages.append("Response 503")
if try_count != 5:
time.sleep(5)
continue
@@ -254,7 +243,11 @@ class Connection(object):
if self.response:
return self.response.status
- raise RequestError('Unable to complete http request')
+ request = "{method} {path} headers: {headers} data: {data}".format(
+ method=method, path=path, headers=headers, data=data)
+ raise RequestError('Unable to complete http request: %s. '
+ 'Attempts: %s, Failures: %s' %
+ (request, len(fail_messages), fail_messages))
def put_start(self, path, hdrs={}, parms={}, cfg={}, chunked=False):
self.http_connect()
@@ -329,21 +322,21 @@ class Account(Base):
return Container(self.conn, self.name, container_name)
def containers(self, hdrs={}, parms={}, cfg={}):
- format = parms.get('format', None)
- if format not in [None, 'json', 'xml']:
- raise RequestError('Invalid format: %s' % format)
- if format is None and 'format' in parms:
+ format_type = parms.get('format', None)
+ if format_type not in [None, 'json', 'xml']:
+ raise RequestError('Invalid format: %s' % format_type)
+ if format_type is None and 'format' in parms:
del parms['format']
status = self.conn.make_request('GET', self.path, hdrs=hdrs,
parms=parms, cfg=cfg)
if status == 200:
- if format == 'json':
+ if format_type == 'json':
conts = json.loads(self.conn.response.read())
for cont in conts:
cont['name'] = cont['name'].encode('utf-8')
return conts
- elif format == 'xml':
+ elif format_type == 'xml':
conts = []
tree = minidom.parseString(self.conn.response.read())
for x in tree.getElementsByTagName('container'):
@@ -406,8 +399,8 @@ class Container(Base):
def delete_files(self):
for f in listing_items(self.files):
- file = self.file(f)
- if not file.delete():
+ file_item = self.file(f)
+ if not file_item.delete():
return False
return listing_empty(self.files)
@@ -419,37 +412,39 @@ class Container(Base):
return File(self.conn, self.account, self.name, file_name)
def files(self, hdrs={}, parms={}, cfg={}):
- format = parms.get('format', None)
- if format not in [None, 'json', 'xml']:
- raise RequestError('Invalid format: %s' % format)
- if format is None and 'format' in parms:
+ format_type = parms.get('format', None)
+ if format_type not in [None, 'json', 'xml']:
+ raise RequestError('Invalid format: %s' % format_type)
+ if format_type is None and 'format' in parms:
del parms['format']
status = self.conn.make_request('GET', self.path, hdrs=hdrs,
parms=parms, cfg=cfg)
if status == 200:
- if format == 'json':
+ if format_type == 'json':
files = json.loads(self.conn.response.read())
- for file in files:
- file['name'] = file['name'].encode('utf-8')
- file['content_type'] = file['content_type'].encode('utf-8')
+ for file_item in files:
+ file_item['name'] = file_item['name'].encode('utf-8')
+ file_item['content_type'] = file_item['content_type'].\
+ encode('utf-8')
return files
- elif format == 'xml':
+ elif format_type == 'xml':
files = []
tree = minidom.parseString(self.conn.response.read())
for x in tree.getElementsByTagName('object'):
- file = {}
+ file_item = {}
for key in ['name', 'hash', 'bytes', 'content_type',
'last_modified']:
- file[key] = x.getElementsByTagName(key)[0].\
+ file_item[key] = x.getElementsByTagName(key)[0].\
childNodes[0].nodeValue
- files.append(file)
+ files.append(file_item)
- for file in files:
- file['name'] = file['name'].encode('utf-8')
- file['content_type'] = file['content_type'].encode('utf-8')
+ for file_item in files:
+ file_item['name'] = file_item['name'].encode('utf-8')
+ file_item['content_type'] = file_item['content_type'].\
+ encode('utf-8')
return files
else:
content = self.conn.response.read()
@@ -616,11 +611,11 @@ class File(Base):
callback=None, cfg={}):
if size > 0:
- range = 'bytes=%d-%d' % (offset, (offset + size) - 1)
+ range_string = 'bytes=%d-%d' % (offset, (offset + size) - 1)
if hdrs:
- hdrs['Range'] = range
+ hdrs['Range'] = range_string
else:
- hdrs = {'Range': range}
+ hdrs = {'Range': range_string}
status = self.conn.make_request('GET', self.path, hdrs=hdrs,
cfg=cfg)
@@ -736,7 +731,7 @@ class File(Base):
callback(transferred, self.size)
self.conn.put_end()
- except socket.timeout, err:
+ except socket.timeout as err:
raise err
if (self.conn.response.status < 200) or \
diff --git a/test/functional/tests.py b/test/functional/tests.py
index dcd8b51..e5ccda2 100644
--- a/test/functional/tests.py
+++ b/test/functional/tests.py
@@ -1,5 +1,5 @@
#!/usr/bin/python -u
-# Copyright (c) 2010-2013 OpenStack, LLC.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,20 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Copyright (c) 2013 Red Hat, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# Modifications by Red Hat, Inc.
from datetime import datetime
import os
@@ -89,6 +76,7 @@ web_front_end = config.get('web_front_end', 'integral')
normalized_urls = config.get('normalized_urls', False)
set_object_name_component_length()
+
def load_constraint(name):
c = config[name]
if not isinstance(c, int):
@@ -143,7 +131,7 @@ def timeout(seconds, method, *args, **kwargs):
def run(self):
try:
self.method(*self.args, **self.kwargs)
- except Exception, e:
+ except Exception as e:
self.exception = e
t = TimeoutThread(method, *args, **kwargs)
@@ -304,23 +292,24 @@ class TestAccount(Base):
info = {'bytes': 0}
info['count'] = random.randint(10, 30)
for i in range(info['count']):
- file = container.file(Utils.create_name())
+ file_item = container.file(Utils.create_name())
bytes = random.randint(1, 32768)
- file.write_random(bytes)
+ file_item.write_random(bytes)
info['bytes'] += bytes
container_info[container.name] = info
- for format in ['json', 'xml']:
- for a in self.env.account.containers(parms={'format': format}):
+ for format_type in ['json', 'xml']:
+ for a in self.env.account.containers(
+ parms={'format': format_type}):
self.assert_(a['count'] >= 0)
self.assert_(a['bytes'] >= 0)
headers = dict(self.env.conn.response.getheaders())
- if format == 'json':
+ if format_type == 'json':
self.assertEquals(headers['content-type'],
'application/json; charset=utf-8')
- elif format == 'xml':
+ elif format_type == 'xml':
self.assertEquals(headers['content-type'],
'application/xml; charset=utf-8')
@@ -340,8 +329,8 @@ class TestAccount(Base):
def testContainerListing(self):
a = sorted([c.name for c in self.env.containers])
- for format in [None, 'json', 'xml']:
- b = self.env.account.containers(parms={'format': format})
+ for format_type in [None, 'json', 'xml']:
+ b = self.env.account.containers(parms={'format': format_type})
if isinstance(b[0], dict):
b = [x['name'] for x in b]
@@ -354,27 +343,29 @@ class TestAccount(Base):
self.assert_status(401)
def testLastContainerMarker(self):
- for format in [None, 'json', 'xml']:
- containers = self.env.account.containers({'format': format})
+ for format_type in [None, 'json', 'xml']:
+ containers = self.env.account.containers({'format': format_type})
self.assertEquals(len(containers), len(self.env.containers))
self.assert_status(200)
containers = self.env.account.containers(
- parms={'format': format, 'marker': containers[-1]})
+ parms={'format': format_type, 'marker': containers[-1]})
self.assertEquals(len(containers), 0)
- if format is None:
+ if format_type is None:
self.assert_status(204)
else:
self.assert_status(200)
def testMarkerLimitContainerList(self):
- for format in [None, 'json', 'xml']:
+ for format_type in [None, 'json', 'xml']:
for marker in ['0', 'A', 'I', 'R', 'Z', 'a', 'i', 'r', 'z',
'abc123', 'mnop', 'xyz']:
limit = random.randint(2, 9)
containers = self.env.account.containers(
- parms={'format': format, 'marker': marker, 'limit': limit})
+ parms={'format': format_type,
+ 'marker': marker,
+ 'limit': limit})
self.assert_(len(containers) <= limit)
if containers:
if isinstance(containers[0], dict):
@@ -382,9 +373,9 @@ class TestAccount(Base):
self.assert_(locale.strcoll(containers[0], marker) > 0)
def testContainersOrderedByName(self):
- for format in [None, 'json', 'xml']:
+ for format_type in [None, 'json', 'xml']:
containers = self.env.account.containers(
- parms={'format': format})
+ parms={'format': format_type})
if isinstance(containers[0], dict):
containers = [x['name'] for x in containers]
self.assertEquals(sorted(containers, cmp=locale.strcoll),
@@ -410,11 +401,11 @@ class TestAccountNoContainers(Base):
set_up = False
def testGetRequest(self):
- for format in [None, 'json', 'xml']:
+ for format_type in [None, 'json', 'xml']:
self.assert_(not self.env.account.containers(
- parms={'format': format}))
+ parms={'format': format_type}))
- if format is None:
+ if format_type is None:
self.assert_status(204)
else:
self.assert_status(200)
@@ -441,9 +432,9 @@ class TestContainerEnv:
cls.file_size = 128
cls.files = list()
for x in range(cls.file_count):
- file = cls.container.file(Utils.create_name())
- file.write_random(cls.file_size)
- cls.files.append(file.name)
+ file_item = cls.container.file(Utils.create_name())
+ file_item.write_random(cls.file_size)
+ cls.files.append(file_item.name)
class TestContainerDev(Base):
@@ -475,12 +466,12 @@ class TestContainer(Base):
def testFileThenContainerDelete(self):
cont = self.env.account.container(Utils.create_name())
self.assert_(cont.create())
- file = cont.file(Utils.create_name())
- self.assert_(file.write_random())
+ file_item = cont.file(Utils.create_name())
+ self.assert_(file_item.write_random())
- self.assert_(file.delete())
+ self.assert_(file_item.delete())
self.assert_status(204)
- self.assert_(file.name not in cont.files())
+ self.assert_(file_item.name not in cont.files())
self.assert_(cont.delete())
self.assert_status(204)
@@ -492,8 +483,8 @@ class TestContainer(Base):
files = sorted([Utils.create_name() for x in xrange(10)])
for f in files:
- file = cont.file(f)
- self.assert_(file.write_random())
+ file_item = cont.file(f)
+ self.assert_(file_item.write_random())
for i in xrange(len(files)):
f = files[i]
@@ -518,23 +509,23 @@ class TestContainer(Base):
prefix_files[prefix] = []
for i in range(prefix_file_count):
- file = cont.file(prefix + Utils.create_name())
- file.write()
- prefix_files[prefix].append(file.name)
+ file_item = cont.file(prefix + Utils.create_name())
+ file_item.write()
+ prefix_files[prefix].append(file_item.name)
- for format in [None, 'json', 'xml']:
+ for format_type in [None, 'json', 'xml']:
for prefix in prefixs:
files = cont.files(parms={'prefix': prefix})
self.assertEquals(files, sorted(prefix_files[prefix]))
- for format in [None, 'json', 'xml']:
+ for format_type in [None, 'json', 'xml']:
for prefix in prefixs:
files = cont.files(parms={'limit': limit_count,
'prefix': prefix})
self.assertEquals(len(files), limit_count)
- for file in files:
- self.assert_(file.startswith(prefix))
+ for file_item in files:
+ self.assert_(file_item.startswith(prefix))
def testCreate(self):
cont = self.env.account.container(Utils.create_name())
@@ -543,10 +534,10 @@ class TestContainer(Base):
self.assert_(cont.name in self.env.account.containers())
def testContainerFileListOnContainerThatDoesNotExist(self):
- for format in [None, 'json', 'xml']:
+ for format_type in [None, 'json', 'xml']:
container = self.env.account.container(Utils.create_name())
self.assertRaises(ResponseError, container.files,
- parms={'format': format})
+ parms={'format': format_type})
self.assert_status(404)
def testUtf8Container(self):
@@ -606,52 +597,52 @@ class TestContainer(Base):
def testDeleteOnContainerWithFiles(self):
cont = self.env.account.container(Utils.create_name())
self.assert_(cont.create())
- file = cont.file(Utils.create_name())
- file.write_random(self.env.file_size)
- self.assert_(file.name in cont.files())
+ file_item = cont.file(Utils.create_name())
+ file_item.write_random(self.env.file_size)
+ self.assert_(file_item.name in cont.files())
self.assert_(not cont.delete())
self.assert_status(409)
def testFileCreateInContainerThatDoesNotExist(self):
- file = File(self.env.conn, self.env.account, Utils.create_name(),
- Utils.create_name())
- self.assertRaises(ResponseError, file.write)
+ file_item = File(self.env.conn, self.env.account, Utils.create_name(),
+ Utils.create_name())
+ self.assertRaises(ResponseError, file_item.write)
self.assert_status(404)
def testLastFileMarker(self):
- for format in [None, 'json', 'xml']:
- files = self.env.container.files({'format': format})
+ for format_type in [None, 'json', 'xml']:
+ files = self.env.container.files({'format': format_type})
self.assertEquals(len(files), len(self.env.files))
self.assert_status(200)
files = self.env.container.files(
- parms={'format': format, 'marker': files[-1]})
+ parms={'format': format_type, 'marker': files[-1]})
self.assertEquals(len(files), 0)
- if format is None:
+ if format_type is None:
self.assert_status(204)
else:
self.assert_status(200)
def testContainerFileList(self):
- for format in [None, 'json', 'xml']:
- files = self.env.container.files(parms={'format': format})
+ for format_type in [None, 'json', 'xml']:
+ files = self.env.container.files(parms={'format': format_type})
self.assert_status(200)
if isinstance(files[0], dict):
files = [x['name'] for x in files]
- for file in self.env.files:
- self.assert_(file in files)
+ for file_item in self.env.files:
+ self.assert_(file_item in files)
- for file in files:
- self.assert_(file in self.env.files)
+ for file_item in files:
+ self.assert_(file_item in self.env.files)
def testMarkerLimitFileList(self):
- for format in [None, 'json', 'xml']:
+ for format_type in [None, 'json', 'xml']:
for marker in ['0', 'A', 'I', 'R', 'Z', 'a', 'i', 'r', 'z',
'abc123', 'mnop', 'xyz']:
limit = random.randint(2, self.env.file_count - 1)
- files = self.env.container.files(parms={'format': format,
+ files = self.env.container.files(parms={'format': format_type,
'marker': marker,
'limit': limit})
@@ -668,8 +659,8 @@ class TestContainer(Base):
self.assert_(locale.strcoll(files[0], marker) > 0)
def testFileOrder(self):
- for format in [None, 'json', 'xml']:
- files = self.env.container.files(parms={'format': format})
+ for format_type in [None, 'json', 'xml']:
+ files = self.env.container.files(parms={'format': format_type})
if isinstance(files[0], dict):
files = [x['name'] for x in files]
self.assertEquals(sorted(files, cmp=locale.strcoll), files)
@@ -687,8 +678,8 @@ class TestContainer(Base):
self.assert_status(404)
def testContainerFileListWithLimit(self):
- for format in [None, 'json', 'xml']:
- files = self.env.container.files(parms={'format': format,
+ for format_type in [None, 'json', 'xml']:
+ files = self.env.container.files(parms={'format': format_type,
'limit': 2})
self.assertEquals(len(files), 2)
@@ -707,8 +698,8 @@ class TestContainer(Base):
cont = self.env.account.container(Utils.create_name())
self.assertRaises(ResponseError, cont.files)
self.assert_(cont.create())
- file = cont.file(Utils.create_name())
- file.write_random()
+ file_item = cont.file(Utils.create_name())
+ file_item.write_random()
class TestContainerUTF8(Base2, TestContainer):
@@ -775,12 +766,13 @@ class TestContainerPathsEnv:
stored_files = set()
for f in cls.files:
- file = cls.container.file(f)
+ file_item = cls.container.file(f)
if f.endswith('/'):
- file.write(hdrs={'Content-Type': 'application/directory'})
+ file_item.write(hdrs={'Content-Type': 'application/directory'})
else:
- file.write_random(cls.file_size, hdrs={'Content-Type':
- 'application/directory'})
+ file_item.write_random(cls.file_size,
+ hdrs={'Content-Type':
+ 'application/directory'})
if (normalized_urls):
nfile = '/'.join(filter(None, f.split('/')))
if (f[-1] == '/'):
@@ -791,8 +783,6 @@ class TestContainerPathsEnv:
cls.stored_files = sorted(stored_files)
-
-
class TestContainerPaths(Base):
env = TestContainerPathsEnv
set_up = False
@@ -805,61 +795,62 @@ class TestContainerPaths(Base):
if count > 10:
raise ValueError('too deep recursion')
- for file in self.env.container.files(parms={'path': path}):
- self.assert_(file.startswith(path))
- if file.endswith('/'):
- recurse_path(file, count + 1)
- found_dirs.append(file)
+ for file_item in self.env.container.files(parms={'path': path}):
+ self.assert_(file_item.startswith(path))
+ if file_item.endswith('/'):
+ recurse_path(file_item, count + 1)
+ found_dirs.append(file_item)
else:
- found_files.append(file)
+ found_files.append(file_item)
recurse_path('')
- for file in self.env.stored_files:
- if file.startswith('/'):
- self.assert_(file not in found_dirs)
- self.assert_(file not in found_files)
- elif file.endswith('/'):
- self.assert_(file in found_dirs)
- self.assert_(file not in found_files)
+ for file_item in self.env.stored_files:
+ if file_item.startswith('/'):
+ self.assert_(file_item not in found_dirs)
+ self.assert_(file_item not in found_files)
+ elif file_item.endswith('/'):
+ self.assert_(file_item in found_dirs)
+ self.assert_(file_item not in found_files)
else:
- self.assert_(file in found_files)
- self.assert_(file not in found_dirs)
+ self.assert_(file_item in found_files)
+ self.assert_(file_item not in found_dirs)
found_files = []
found_dirs = []
recurse_path('/')
- for file in self.env.stored_files:
- if not file.startswith('/'):
- self.assert_(file not in found_dirs)
- self.assert_(file not in found_files)
- elif file.endswith('/'):
- self.assert_(file in found_dirs)
- self.assert_(file not in found_files)
+ for file_item in self.env.stored_files:
+ if not file_item.startswith('/'):
+ self.assert_(file_item not in found_dirs)
+ self.assert_(file_item not in found_files)
+ elif file_item.endswith('/'):
+ self.assert_(file_item in found_dirs)
+ self.assert_(file_item not in found_files)
else:
- self.assert_(file in found_files)
- self.assert_(file not in found_dirs)
+ self.assert_(file_item in found_files)
+ self.assert_(file_item not in found_dirs)
def testContainerListing(self):
- for format in (None, 'json', 'xml'):
- files = self.env.container.files(parms={'format': format})
+ for format_type in (None, 'json', 'xml'):
+ files = self.env.container.files(parms={'format': format_type})
if isinstance(files[0], dict):
files = [str(x['name']) for x in files]
self.assertEquals(files, self.env.stored_files)
- for format in ('json', 'xml'):
- for file in self.env.container.files(parms={'format': format}):
- self.assert_(int(file['bytes']) >= 0)
- self.assert_('last_modified' in file)
- if file['name'].endswith('/'):
- self.assertEquals(file['content_type'],
+ for format_type in ('json', 'xml'):
+ for file_item in self.env.container.files(parms={'format':
+ format_type}):
+ self.assert_(int(file_item['bytes']) >= 0)
+ self.assert_('last_modified' in file_item)
+ if file_item['name'].endswith('/'):
+ self.assertEquals(file_item['content_type'],
'application/directory')
def testStructure(self):
- def assert_listing(path, list):
+ def assert_listing(path, file_list):
files = self.env.container.files(parms={'path': path})
- self.assertEquals(sorted(list, cmp=locale.strcoll), files)
+ self.assertEquals(sorted(file_list, cmp=locale.strcoll), files)
if not normalized_urls:
assert_listing('/', ['/dir1/', '/dir2/', '/file1', '/file A'])
assert_listing('/dir1',
@@ -927,14 +918,14 @@ class TestFile(Base):
def testCopy(self):
# makes sure to test encoded characters"
source_filename = 'dealde%2Fl04 011e%204c8df/flash.png'
- file = self.env.container.file(source_filename)
+ file_item = self.env.container.file(source_filename)
metadata = {}
for i in range(1):
metadata[Utils.create_ascii_name()] = Utils.create_name()
- data = file.write_random()
- file.sync_metadata(metadata)
+ data = file_item.write_random()
+ file_item.sync_metadata(metadata)
dest_cont = self.env.account.container(Utils.create_name())
self.assert_(dest_cont.create())
@@ -945,21 +936,21 @@ class TestFile(Base):
for prefix in ('', '/'):
dest_filename = Utils.create_name()
- file = self.env.container.file(source_filename)
- file.copy('%s%s' % (prefix, cont), dest_filename)
+ file_item = self.env.container.file(source_filename)
+ file_item.copy('%s%s' % (prefix, cont), dest_filename)
self.assert_(dest_filename in cont.files())
- file = cont.file(dest_filename)
+ file_item = cont.file(dest_filename)
- self.assert_(data == file.read())
- self.assert_(file.initialize())
- self.assert_(metadata == file.metadata)
+ self.assert_(data == file_item.read())
+ self.assert_(file_item.initialize())
+ self.assert_(metadata == file_item.metadata)
def testCopy404s(self):
source_filename = Utils.create_name()
- file = self.env.container.file(source_filename)
- file.write_random()
+ file_item = self.env.container.file(source_filename)
+ file_item.write_random()
dest_cont = self.env.account.container(Utils.create_name())
self.assert_(dest_cont.create())
@@ -967,60 +958,65 @@ class TestFile(Base):
for prefix in ('', '/'):
# invalid source container
source_cont = self.env.account.container(Utils.create_name())
- file = source_cont.file(source_filename)
- self.assert_(not file.copy('%s%s' % (prefix, self.env.container),
- Utils.create_name()))
+ file_item = source_cont.file(source_filename)
+ self.assert_(not file_item.copy(
+ '%s%s' % (prefix, self.env.container),
+ Utils.create_name()))
self.assert_status(404)
- self.assert_(not file.copy('%s%s' % (prefix, dest_cont),
- Utils.create_name()))
+ self.assert_(not file_item.copy('%s%s' % (prefix, dest_cont),
+ Utils.create_name()))
self.assert_status(404)
# invalid source object
- file = self.env.container.file(Utils.create_name())
- self.assert_(not file.copy('%s%s' % (prefix, self.env.container),
- Utils.create_name()))
+ file_item = self.env.container.file(Utils.create_name())
+ self.assert_(not file_item.copy(
+ '%s%s' % (prefix, self.env.container),
+ Utils.create_name()))
self.assert_status(404)
- self.assert_(not file.copy('%s%s' % (prefix, dest_cont),
- Utils.create_name()))
+ self.assert_(not file_item.copy('%s%s' % (prefix, dest_cont),
+ Utils.create_name()))
self.assert_status(404)
# invalid destination container
- file = self.env.container.file(source_filename)
- self.assert_(not file.copy('%s%s' % (prefix, Utils.create_name()),
- Utils.create_name()))
+ file_item = self.env.container.file(source_filename)
+ self.assert_(not file_item.copy(
+ '%s%s' % (prefix, Utils.create_name()),
+ Utils.create_name()))
def testCopyNoDestinationHeader(self):
source_filename = Utils.create_name()
- file = self.env.container.file(source_filename)
- file.write_random()
+ file_item = self.env.container.file(source_filename)
+ file_item.write_random()
- file = self.env.container.file(source_filename)
- self.assert_(not file.copy(Utils.create_name(), Utils.create_name(),
+ file_item = self.env.container.file(source_filename)
+ self.assert_(not file_item.copy(Utils.create_name(),
+ Utils.create_name(),
cfg={'no_destination': True}))
self.assert_status(412)
def testCopyDestinationSlashProblems(self):
source_filename = Utils.create_name()
- file = self.env.container.file(source_filename)
- file.write_random()
+ file_item = self.env.container.file(source_filename)
+ file_item.write_random()
# no slash
- self.assert_(not file.copy(Utils.create_name(), Utils.create_name(),
+ self.assert_(not file_item.copy(Utils.create_name(),
+ Utils.create_name(),
cfg={'destination': Utils.create_name()}))
self.assert_status(412)
def testCopyFromHeader(self):
source_filename = Utils.create_name()
- file = self.env.container.file(source_filename)
+ file_item = self.env.container.file(source_filename)
metadata = {}
for i in range(1):
metadata[Utils.create_ascii_name()] = Utils.create_name()
- file.metadata = metadata
+ file_item.metadata = metadata
- data = file.write_random()
+ data = file_item.write_random()
dest_cont = self.env.account.container(Utils.create_name())
self.assert_(dest_cont.create())
@@ -1031,35 +1027,35 @@ class TestFile(Base):
for prefix in ('', '/'):
dest_filename = Utils.create_name()
- file = cont.file(dest_filename)
- file.write(hdrs={'X-Copy-From': '%s%s/%s' % (prefix,
- self.env.container.name, source_filename)})
+ file_item = cont.file(dest_filename)
+ file_item.write(hdrs={'X-Copy-From': '%s%s/%s' % (
+ prefix, self.env.container.name, source_filename)})
self.assert_(dest_filename in cont.files())
- file = cont.file(dest_filename)
+ file_item = cont.file(dest_filename)
- self.assert_(data == file.read())
- self.assert_(file.initialize())
- self.assert_(metadata == file.metadata)
+ self.assert_(data == file_item.read())
+ self.assert_(file_item.initialize())
+ self.assert_(metadata == file_item.metadata)
def testCopyFromHeader404s(self):
source_filename = Utils.create_name()
- file = self.env.container.file(source_filename)
- file.write_random()
+ file_item = self.env.container.file(source_filename)
+ file_item.write_random()
for prefix in ('', '/'):
# invalid source container
- file = self.env.container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.write,
+ file_item = self.env.container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.write,
hdrs={'X-Copy-From': '%s%s/%s' %
(prefix,
Utils.create_name(), source_filename)})
self.assert_status(404)
# invalid source object
- file = self.env.container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.write,
+ file_item = self.env.container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.write,
hdrs={'X-Copy-From': '%s%s/%s' %
(prefix,
self.env.container.name, Utils.create_name())})
@@ -1067,8 +1063,8 @@ class TestFile(Base):
# invalid destination container
dest_cont = self.env.account.container(Utils.create_name())
- file = dest_cont.file(Utils.create_name())
- self.assertRaises(ResponseError, file.write,
+ file_item = dest_cont.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.write,
hdrs={'X-Copy-From': '%s%s/%s' %
(prefix,
self.env.container.name, source_filename)})
@@ -1078,13 +1074,13 @@ class TestFile(Base):
limit = load_constraint('max_object_name_length')
for l in (1, 10, limit / 2, limit - 1, limit, limit + 1, limit * 2):
- file = self.env.container.file(create_limit_filename(l))
+ file_item = self.env.container.file(create_limit_filename(l))
if l <= limit:
- self.assert_(file.write())
+ self.assert_(file_item.write())
self.assert_status(201)
else:
- self.assertRaises(ResponseError, file.write)
+ self.assertRaises(ResponseError, file_item.write)
self.assert_status(400)
def testQuestionMarkInName(self):
@@ -1095,30 +1091,32 @@ class TestFile(Base):
else:
file_name = Utils.create_name(6) + '?' + Utils.create_name(6)
- file = self.env.container.file(file_name)
- self.assert_(file.write(cfg={'no_path_quote': True}))
+ file_item = self.env.container.file(file_name)
+ self.assert_(file_item.write(cfg={'no_path_quote': True}))
self.assert_(file_name not in self.env.container.files())
self.assert_(file_name.split('?')[0] in self.env.container.files())
def testDeleteThen404s(self):
- file = self.env.container.file(Utils.create_name())
- self.assert_(file.write_random())
+ file_item = self.env.container.file(Utils.create_name())
+ self.assert_(file_item.write_random())
self.assert_status(201)
- self.assert_(file.delete())
+ self.assert_(file_item.delete())
self.assert_status(204)
- file.metadata = {Utils.create_ascii_name(): Utils.create_name()}
+ file_item.metadata = {Utils.create_ascii_name(): Utils.create_name()}
- for method in (file.info, file.read, file.sync_metadata,
- file.delete):
+ for method in (file_item.info,
+ file_item.read,
+ file_item.sync_metadata,
+ file_item.delete):
self.assertRaises(ResponseError, method)
self.assert_status(404)
def testBlankMetadataName(self):
- file = self.env.container.file(Utils.create_name())
- file.metadata = {'': Utils.create_name()}
- self.assertRaises(ResponseError, file.write_random)
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.metadata = {'': Utils.create_name()}
+ self.assertRaises(ResponseError, file_item.write_random)
self.assert_status(400)
def testMetadataNumberLimit(self):
@@ -1143,22 +1141,22 @@ class TestFile(Base):
size += len(key) + len(val)
metadata[key] = val
- file = self.env.container.file(Utils.create_name())
- file.metadata = metadata
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.metadata = metadata
if i <= number_limit:
- self.assert_(file.write())
+ self.assert_(file_item.write())
self.assert_status(201)
- self.assert_(file.sync_metadata())
+ self.assert_(file_item.sync_metadata())
self.assert_status((201, 202))
else:
- self.assertRaises(ResponseError, file.write)
+ self.assertRaises(ResponseError, file_item.write)
self.assert_status(400)
- file.metadata = {}
- self.assert_(file.write())
+ file_item.metadata = {}
+ self.assert_(file_item.write())
self.assert_status(201)
- file.metadata = metadata
- self.assertRaises(ResponseError, file.sync_metadata)
+ file_item.metadata = metadata
+ self.assertRaises(ResponseError, file_item.sync_metadata)
self.assert_status(400)
def testContentTypeGuessing(self):
@@ -1169,8 +1167,8 @@ class TestFile(Base):
self.assert_(container.create())
for i in file_types.keys():
- file = container.file(Utils.create_name() + '.' + i)
- file.write('', cfg={'no_content_type': True})
+ file_item = container.file(Utils.create_name() + '.' + i)
+ file_item.write('', cfg={'no_content_type': True})
file_types_read = {}
for i in container.files(parms={'format': 'json'}):
@@ -1181,13 +1179,13 @@ class TestFile(Base):
def testRangedGets(self):
file_length = 10000
range_size = file_length / 10
- file = self.env.container.file(Utils.create_name())
- data = file.write_random(file_length)
+ file_item = self.env.container.file(Utils.create_name())
+ data = file_item.write_random(file_length)
for i in range(0, file_length, range_size):
range_string = 'bytes=%d-%d' % (i, i + range_size - 1)
hdrs = {'Range': range_string}
- self.assert_(data[i: i + range_size] == file.read(hdrs=hdrs),
+ self.assert_(data[i: i + range_size] == file_item.read(hdrs=hdrs),
range_string)
range_string = 'bytes=-%d' % (i)
@@ -1198,45 +1196,45 @@ class TestFile(Base):
# least one suffix-byte-range-spec with a NON-ZERO
# suffix-length, then the byte-range-set is satisfiable.
# Otherwise, the byte-range-set is unsatisfiable.
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(416)
else:
- self.assertEquals(file.read(hdrs=hdrs), data[-i:])
+ self.assertEquals(file_item.read(hdrs=hdrs), data[-i:])
range_string = 'bytes=%d-' % (i)
hdrs = {'Range': range_string}
- self.assert_(file.read(hdrs=hdrs) == data[i - file_length:],
+ self.assert_(file_item.read(hdrs=hdrs) == data[i - file_length:],
range_string)
range_string = 'bytes=%d-%d' % (file_length + 1000, file_length + 2000)
hdrs = {'Range': range_string}
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(416)
range_string = 'bytes=%d-%d' % (file_length - 1000, file_length + 2000)
hdrs = {'Range': range_string}
- self.assert_(file.read(hdrs=hdrs) == data[-1000:], range_string)
+ self.assert_(file_item.read(hdrs=hdrs) == data[-1000:], range_string)
hdrs = {'Range': '0-4'}
- self.assert_(file.read(hdrs=hdrs) == data, range_string)
+ self.assert_(file_item.read(hdrs=hdrs) == data, range_string)
# RFC 2616 14.35.1
# "If the entity is shorter than the specified suffix-length, the
# entire entity-body is used."
range_string = 'bytes=-%d' % (file_length + 10)
hdrs = {'Range': range_string}
- self.assert_(file.read(hdrs=hdrs) == data, range_string)
+ self.assert_(file_item.read(hdrs=hdrs) == data, range_string)
def testRangedGetsWithLWSinHeader(self):
#Skip this test until webob 1.2 can tolerate LWS in Range header.
file_length = 10000
- file = self.env.container.file(Utils.create_name())
- data = file.write_random(file_length)
+ file_item = self.env.container.file(Utils.create_name())
+ data = file_item.write_random(file_length)
for r in ('BYTES=0-999', 'bytes = 0-999', 'BYTES = 0 - 999',
'bytes = 0 - 999', 'bytes=0 - 999', 'bytes=0-999 '):
- self.assert_(file.read(hdrs={'Range': r}) == data[0:1000])
+ self.assert_(file_item.read(hdrs={'Range': r}) == data[0:1000])
def testFileSizeLimit(self):
limit = load_constraint('max_file_size')
@@ -1245,39 +1243,40 @@ class TestFile(Base):
for i in (limit - 100, limit - 10, limit - 1, limit, limit + 1,
limit + 10, limit + 100):
- file = self.env.container.file(Utils.create_name())
+ file_item = self.env.container.file(Utils.create_name())
if i <= limit:
- self.assert_(timeout(tsecs, file.write,
+ self.assert_(timeout(tsecs, file_item.write,
cfg={'set_content_length': i}))
else:
self.assertRaises(ResponseError, timeout, tsecs,
- file.write, cfg={'set_content_length': i})
+ file_item.write,
+ cfg={'set_content_length': i})
def testNoContentLengthForPut(self):
- file = self.env.container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.write, 'testing',
+ file_item = self.env.container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.write, 'testing',
cfg={'no_content_length': True})
self.assert_status(411)
def testDelete(self):
- file = self.env.container.file(Utils.create_name())
- file.write_random(self.env.file_size)
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.write_random(self.env.file_size)
- self.assert_(file.name in self.env.container.files())
- self.assert_(file.delete())
- self.assert_(file.name not in self.env.container.files())
+ self.assert_(file_item.name in self.env.container.files())
+ self.assert_(file_item.delete())
+ self.assert_(file_item.name not in self.env.container.files())
def testBadHeaders(self):
file_length = 100
# no content type on puts should be ok
- file = self.env.container.file(Utils.create_name())
- file.write_random(file_length, cfg={'no_content_type': True})
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.write_random(file_length, cfg={'no_content_type': True})
self.assert_status(201)
# content length x
- self.assertRaises(ResponseError, file.write_random, file_length,
+ self.assertRaises(ResponseError, file_item.write_random, file_length,
hdrs={'Content-Length': 'X'},
cfg={'no_content_length': True})
self.assert_status(400)
@@ -1290,7 +1289,7 @@ class TestFile(Base):
self.assert_status(405)
# bad range headers
- self.assert_(len(file.read(hdrs={'Range': 'parsecs=8-12'})) ==
+ self.assert_(len(file_item.read(hdrs={'Range': 'parsecs=8-12'})) ==
file_length)
self.assert_status(200)
@@ -1304,49 +1303,49 @@ class TestFile(Base):
for l in lengths:
metadata = {'a' * l[0]: 'b' * l[1]}
- file = self.env.container.file(Utils.create_name())
- file.metadata = metadata
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.metadata = metadata
if l[0] <= key_limit and l[1] <= value_limit:
- self.assert_(file.write())
+ self.assert_(file_item.write())
self.assert_status(201)
- self.assert_(file.sync_metadata())
+ self.assert_(file_item.sync_metadata())
else:
- self.assertRaises(ResponseError, file.write)
+ self.assertRaises(ResponseError, file_item.write)
self.assert_status(400)
- file.metadata = {}
- self.assert_(file.write())
+ file_item.metadata = {}
+ self.assert_(file_item.write())
self.assert_status(201)
- file.metadata = metadata
- self.assertRaises(ResponseError, file.sync_metadata)
+ file_item.metadata = metadata
+ self.assertRaises(ResponseError, file_item.sync_metadata)
self.assert_status(400)
def testEtagWayoff(self):
- file = self.env.container.file(Utils.create_name())
+ file_item = self.env.container.file(Utils.create_name())
hdrs = {'etag': 'reallylonganddefinitelynotavalidetagvalue'}
- self.assertRaises(ResponseError, file.write_random, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.write_random, hdrs=hdrs)
self.assert_status(422)
def testFileCreate(self):
for i in range(10):
- file = self.env.container.file(Utils.create_name())
- data = file.write_random()
+ file_item = self.env.container.file(Utils.create_name())
+ data = file_item.write_random()
self.assert_status(201)
- self.assert_(data == file.read())
+ self.assert_(data == file_item.read())
self.assert_status(200)
def testHead(self):
file_name = Utils.create_name()
content_type = Utils.create_name()
- file = self.env.container.file(file_name)
- file.content_type = content_type
- file.write_random(self.env.file_size)
+ file_item = self.env.container.file(file_name)
+ file_item.content_type = content_type
+ file_item.write_random(self.env.file_size)
- md5 = file.md5
+ md5 = file_item.md5
- file = self.env.container.file(file_name)
- info = file.info()
+ file_item = self.env.container.file(file_name)
+ info = file_item.info()
self.assert_status(200)
self.assertEquals(info['content_length'], self.env.file_size)
@@ -1356,83 +1355,83 @@ class TestFile(Base):
def testDeleteOfFileThatDoesNotExist(self):
# in container that exists
- file = self.env.container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.delete)
+ file_item = self.env.container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.delete)
self.assert_status(404)
# in container that does not exist
container = self.env.account.container(Utils.create_name())
- file = container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.delete)
+ file_item = container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.delete)
self.assert_status(404)
def testHeadOnFileThatDoesNotExist(self):
# in container that exists
- file = self.env.container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.info)
+ file_item = self.env.container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.info)
self.assert_status(404)
# in container that does not exist
container = self.env.account.container(Utils.create_name())
- file = container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.info)
+ file_item = container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.info)
self.assert_status(404)
def testMetadataOnPost(self):
- file = self.env.container.file(Utils.create_name())
- file.write_random(self.env.file_size)
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.write_random(self.env.file_size)
for i in range(10):
metadata = {}
- for i in range(10):
+ for j in range(10):
metadata[Utils.create_ascii_name()] = Utils.create_name()
- file.metadata = metadata
- self.assert_(file.sync_metadata())
+ file_item.metadata = metadata
+ self.assert_(file_item.sync_metadata())
self.assert_status((201, 202))
- file = self.env.container.file(file.name)
- self.assert_(file.initialize())
+ file_item = self.env.container.file(file_item.name)
+ self.assert_(file_item.initialize())
self.assert_status(200)
- self.assertEquals(file.metadata, metadata)
+ self.assertEquals(file_item.metadata, metadata)
def testGetContentType(self):
file_name = Utils.create_name()
content_type = Utils.create_name()
- file = self.env.container.file(file_name)
- file.content_type = content_type
- file.write_random()
+ file_item = self.env.container.file(file_name)
+ file_item.content_type = content_type
+ file_item.write_random()
- file = self.env.container.file(file_name)
- file.read()
+ file_item = self.env.container.file(file_name)
+ file_item.read()
- self.assertEquals(content_type, file.content_type)
+ self.assertEquals(content_type, file_item.content_type)
def testGetOnFileThatDoesNotExist(self):
# in container that exists
- file = self.env.container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.read)
+ file_item = self.env.container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.read)
self.assert_status(404)
# in container that does not exist
container = self.env.account.container(Utils.create_name())
- file = container.file(Utils.create_name())
- self.assertRaises(ResponseError, file.read)
+ file_item = container.file(Utils.create_name())
+ self.assertRaises(ResponseError, file_item.read)
self.assert_status(404)
def testPostOnFileThatDoesNotExist(self):
# in container that exists
- file = self.env.container.file(Utils.create_name())
- file.metadata['Field'] = 'Value'
- self.assertRaises(ResponseError, file.sync_metadata)
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.metadata['Field'] = 'Value'
+ self.assertRaises(ResponseError, file_item.sync_metadata)
self.assert_status(404)
# in container that does not exist
container = self.env.account.container(Utils.create_name())
- file = container.file(Utils.create_name())
- file.metadata['Field'] = 'Value'
- self.assertRaises(ResponseError, file.sync_metadata)
+ file_item = container.file(Utils.create_name())
+ file_item.metadata['Field'] = 'Value'
+ self.assertRaises(ResponseError, file_item.sync_metadata)
self.assert_status(404)
def testMetadataOnPut(self):
@@ -1441,14 +1440,14 @@ class TestFile(Base):
for j in range(10):
metadata[Utils.create_ascii_name()] = Utils.create_name()
- file = self.env.container.file(Utils.create_name())
- file.metadata = metadata
- file.write_random(self.env.file_size)
+ file_item = self.env.container.file(Utils.create_name())
+ file_item.metadata = metadata
+ file_item.write_random(self.env.file_size)
- file = self.env.container.file(file.name)
- self.assert_(file.initialize())
+ file_item = self.env.container.file(file_item.name)
+ self.assert_(file_item.initialize())
self.assert_status(200)
- self.assertEquals(file.metadata, metadata)
+ self.assertEquals(file_item.metadata, metadata)
def testSerialization(self):
container = self.env.account.container(Utils.create_name())
@@ -1461,28 +1460,29 @@ class TestFile(Base):
write_time = time.time()
for f in files:
- file = container.file(f['name'])
- file.content_type = f['content_type']
- file.write_random(f['bytes'])
+ file_item = container.file(f['name'])
+ file_item.content_type = f['content_type']
+ file_item.write_random(f['bytes'])
- f['hash'] = file.md5
+ f['hash'] = file_item.md5
f['json'] = False
f['xml'] = False
write_time = time.time() - write_time
- for format in ['json', 'xml']:
- for file in container.files(parms={'format': format}):
+ for format_type in ['json', 'xml']:
+ for file_item in container.files(parms={'format': format_type}):
found = False
for f in files:
- if f['name'] != file['name']:
+ if f['name'] != file_item['name']:
continue
- self.assertEquals(file['content_type'],
+ self.assertEquals(file_item['content_type'],
f['content_type'])
- self.assertEquals(int(file['bytes']), f['bytes'])
+ self.assertEquals(int(file_item['bytes']), f['bytes'])
- d = datetime.strptime(file['last_modified'].split('.')[0],
- "%Y-%m-%dT%H:%M:%S")
+ d = datetime.strptime(
+ file_item['last_modified'].split('.')[0],
+ "%Y-%m-%dT%H:%M:%S")
lm = time.mktime(d.timetuple())
if 'last_modified' in f:
@@ -1490,17 +1490,17 @@ class TestFile(Base):
else:
f['last_modified'] = lm
- f[format] = True
+ f[format_type] = True
found = True
self.assert_(found, 'Unexpected file %s found in '
- '%s listing' % (file['name'], format))
+ '%s listing' % (file_item['name'], format_type))
headers = dict(self.env.conn.response.getheaders())
- if format == 'json':
+ if format_type == 'json':
self.assertEquals(headers['content-type'],
'application/json; charset=utf-8')
- elif format == 'xml':
+ elif format_type == 'xml':
self.assertEquals(headers['content-type'],
'application/xml; charset=utf-8')
@@ -1510,35 +1510,35 @@ class TestFile(Base):
'modified times should be less than time to write files')
for f in files:
- for format in ['json', 'xml']:
- self.assert_(f[format], 'File %s not found in %s listing'
- % (f['name'], format))
+ for format_type in ['json', 'xml']:
+ self.assert_(f[format_type], 'File %s not found in %s listing'
+ % (f['name'], format_type))
def testStackedOverwrite(self):
- file = self.env.container.file(Utils.create_name())
+ file_item = self.env.container.file(Utils.create_name())
for i in range(1, 11):
- data = file.write_random(512)
- file.write(data)
+ data = file_item.write_random(512)
+ file_item.write(data)
- self.assert_(file.read() == data)
+ self.assert_(file_item.read() == data)
def testTooLongName(self):
- file = self.env.container.file('x' * 1025)
- self.assertRaises(ResponseError, file.write)
+ file_item = self.env.container.file('x' * 1025)
+ self.assertRaises(ResponseError, file_item.write)
self.assert_status(400)
def testZeroByteFile(self):
- file = self.env.container.file(Utils.create_name())
+ file_item = self.env.container.file(Utils.create_name())
- self.assert_(file.write(''))
- self.assert_(file.name in self.env.container.files())
- self.assert_(file.read() == '')
+ self.assert_(file_item.write(''))
+ self.assert_(file_item.name in self.env.container.files())
+ self.assert_(file_item.read() == '')
def testEtagResponse(self):
- file = self.env.container.file(Utils.create_name())
+ file_item = self.env.container.file(Utils.create_name())
- data = StringIO.StringIO(file.write_random(512))
+ data = StringIO.StringIO(file_item.write_random(512))
etag = File.compute_md5sum(data)
headers = dict(self.env.conn.response.getheaders())
@@ -1554,15 +1554,15 @@ class TestFile(Base):
etag = File.compute_md5sum(data)
for i in (1, 10, 100, 1000):
- file = self.env.container.file(Utils.create_name())
+ file_item = self.env.container.file(Utils.create_name())
for j in chunks(data, i):
- file.chunked_write(j)
+ file_item.chunked_write(j)
- self.assert_(file.chunked_write())
- self.assert_(data == file.read())
+ self.assert_(file_item.chunked_write())
+ self.assert_(data == file_item.read())
- info = file.info()
+ info = file_item.info()
self.assertEquals(etag, info['etag'])
@@ -1588,9 +1588,9 @@ class TestFileComparisonEnv:
cls.file_size = 128
cls.files = list()
for x in range(cls.file_count):
- file = cls.container.file(Utils.create_name())
- file.write_random(cls.file_size)
- cls.files.append(file)
+ file_item = cls.container.file(Utils.create_name())
+ file_item.write_random(cls.file_size)
+ cls.files.append(file_item)
cls.time_old = time.asctime(time.localtime(time.time() - 86400))
cls.time_new = time.asctime(time.localtime(time.time() + 86400))
@@ -1601,55 +1601,55 @@ class TestFileComparison(Base):
set_up = False
def testIfMatch(self):
- for file in self.env.files:
- hdrs = {'If-Match': file.md5}
- self.assert_(file.read(hdrs=hdrs))
+ for file_item in self.env.files:
+ hdrs = {'If-Match': file_item.md5}
+ self.assert_(file_item.read(hdrs=hdrs))
hdrs = {'If-Match': 'bogus'}
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(412)
def testIfNoneMatch(self):
- for file in self.env.files:
+ for file_item in self.env.files:
hdrs = {'If-None-Match': 'bogus'}
- self.assert_(file.read(hdrs=hdrs))
+ self.assert_(file_item.read(hdrs=hdrs))
- hdrs = {'If-None-Match': file.md5}
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ hdrs = {'If-None-Match': file_item.md5}
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(304)
def testIfModifiedSince(self):
- for file in self.env.files:
+ for file_item in self.env.files:
hdrs = {'If-Modified-Since': self.env.time_old}
- self.assert_(file.read(hdrs=hdrs))
+ self.assert_(file_item.read(hdrs=hdrs))
hdrs = {'If-Modified-Since': self.env.time_new}
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(304)
def testIfUnmodifiedSince(self):
- for file in self.env.files:
+ for file_item in self.env.files:
hdrs = {'If-Unmodified-Since': self.env.time_new}
- self.assert_(file.read(hdrs=hdrs))
+ self.assert_(file_item.read(hdrs=hdrs))
hdrs = {'If-Unmodified-Since': self.env.time_old}
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(412)
def testIfMatchAndUnmodified(self):
- for file in self.env.files:
- hdrs = {'If-Match': file.md5,
+ for file_item in self.env.files:
+ hdrs = {'If-Match': file_item.md5,
'If-Unmodified-Since': self.env.time_new}
- self.assert_(file.read(hdrs=hdrs))
+ self.assert_(file_item.read(hdrs=hdrs))
hdrs = {'If-Match': 'bogus',
'If-Unmodified-Since': self.env.time_new}
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(412)
- hdrs = {'If-Match': file.md5,
+ hdrs = {'If-Match': file_item.md5,
'If-Unmodified-Since': self.env.time_old}
- self.assertRaises(ResponseError, file.read, hdrs=hdrs)
+ self.assertRaises(ResponseError, file_item.read, hdrs=hdrs)
self.assert_status(412)
diff --git a/test/functionalnosetests/swift_testing.py b/test/functionalnosetests/swift_testing.py
index c49d9cd..50abc8e 100644
--- a/test/functionalnosetests/swift_testing.py
+++ b/test/functionalnosetests/swift_testing.py
@@ -1,19 +1,4 @@
-# Copyright (c) 2010-2013 OpenStack, LLC.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Copyright (c) 2013 Red Hat, Inc.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -28,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from httplib import HTTPException
import os
import socket
import sys
@@ -35,7 +21,7 @@ from time import sleep
from test import get_config
-from swiftclient import get_auth, http_connection, HTTPException
+from swiftclient import get_auth, http_connection
conf = get_config('func_test')
web_front_end = conf.get('web_front_end', 'integral')
@@ -57,8 +43,8 @@ if conf:
if 'auth_prefix' not in conf:
conf['auth_prefix'] = '/'
try:
- swift_test_auth += \
- '://%(auth_host)s:%(auth_port)s%(auth_prefix)s' % conf
+ suffix = '://%(auth_host)s:%(auth_port)s%(auth_prefix)s' % conf
+ swift_test_auth += suffix
except KeyError:
pass # skip
@@ -71,17 +57,17 @@ if conf:
swift_test_user[0] = '%(username)s' % conf
swift_test_key[0] = conf['password']
try:
- swift_test_user[1] = '%s%s' % \
- ('%s:' % conf['account2'] if 'account2' in conf else '',
+ swift_test_user[1] = '%s%s' % (
+ '%s:' % conf['account2'] if 'account2' in conf else '',
conf['username2'])
swift_test_key[1] = conf['password2']
- except KeyError, err:
+ except KeyError as err:
pass # old conf, no second account tests can be run
try:
swift_test_user[2] = '%s%s' % ('%s:' % conf['account'] if 'account'
in conf else '', conf['username3'])
swift_test_key[2] = conf['password3']
- except KeyError, err:
+ except KeyError as err:
pass # old conf, no third account tests can be run
for _ in range(3):
@@ -99,7 +85,8 @@ if conf:
swift_test_key[2] = conf['password3']
for _ in range(3):
- swift_test_perm[_] = swift_test_tenant[_] + ':' + swift_test_user[_]
+ swift_test_perm[_] = swift_test_tenant[_] + ':' \
+ + swift_test_user[_]
skip = not all([swift_test_auth, swift_test_user[0], swift_test_key[0]])
if skip:
@@ -108,12 +95,12 @@ if skip:
skip2 = not all([not skip, swift_test_user[1], swift_test_key[1]])
if not skip and skip2:
print >>sys.stderr, \
- 'SKIPPING SECOND ACCOUNT FUNCTIONAL TESTS DUE TO NO CONFIG FOR THEM'
+ 'SKIPPING SECOND ACCOUNT FUNCTIONAL TESTS DUE TO NO CONFIG FOR THEM'
skip3 = not all([not skip, swift_test_user[2], swift_test_key[2]])
if not skip and skip3:
print >>sys.stderr, \
- 'SKIPPING THIRD ACCOUNT FUNCTIONAL TESTS DUE TO NO CONFIG FOR THEM'
+ 'SKIPPING THIRD ACCOUNT FUNCTIONAL TESTS DUE TO NO CONFIG FOR THEM'
class AuthError(Exception):
@@ -160,7 +147,8 @@ def retry(func, *args, **kwargs):
parsed[use_account], conn[use_account] = \
http_connection(url[use_account])
return func(url[use_account], token[use_account],
- parsed[use_account], conn[use_account], *args, **kwargs)
+ parsed[use_account], conn[use_account],
+ *args, **kwargs)
except (socket.error, HTTPException):
if attempts > retries:
raise
diff --git a/test/functionalnosetests/test_account.py b/test/functionalnosetests/test_account.py
index d28ff2f..b2f743f 100755
--- a/test/functionalnosetests/test_account.py
+++ b/test/functionalnosetests/test_account.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# Copyright (c) 2010-2013 OpenStack, LLC.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,22 +15,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Copyright (c) 2013 Red Hat, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
import unittest
from nose import SkipTest
@@ -45,16 +29,20 @@ class TestAccount(unittest.TestCase):
def test_metadata(self):
if skip:
raise SkipTest
+
def post(url, token, parsed, conn, value):
conn.request('POST', parsed.path, '',
- {'X-Auth-Token': token, 'X-Account-Meta-Test': value})
+ {'X-Auth-Token': token, 'X-Account-Meta-Test': value})
return check_response(conn)
+
def head(url, token, parsed, conn):
conn.request('HEAD', parsed.path, '', {'X-Auth-Token': token})
return check_response(conn)
+
def get(url, token, parsed, conn):
conn.request('GET', parsed.path, '', {'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(post, '')
resp.read()
self.assertEquals(resp.status, 204)
@@ -121,13 +109,16 @@ class TestAccount(unittest.TestCase):
def test_multi_metadata(self):
if skip:
raise SkipTest
+
def post(url, token, parsed, conn, name, value):
conn.request('POST', parsed.path, '',
{'X-Auth-Token': token, name: value})
return check_response(conn)
+
def head(url, token, parsed, conn):
conn.request('HEAD', parsed.path, '', {'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(post, 'X-Account-Meta-One', '1')
resp.read()
self.assertEquals(resp.status, 204)
@@ -147,26 +138,30 @@ class TestAccount(unittest.TestCase):
def test_bad_metadata(self):
if skip:
raise SkipTest
+
def post(url, token, parsed, conn, extra_headers):
headers = {'X-Auth-Token': token}
headers.update(extra_headers)
conn.request('POST', parsed.path, '', headers)
return check_response(conn)
+
resp = retry(post,
- {'X-Account-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'})
+ {'X-Account-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'})
resp.read()
self.assertEquals(resp.status, 204)
- resp = retry(post,
- {'X-Account-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'})
+ resp = retry(
+ post,
+ {'X-Account-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'})
resp.read()
self.assertEquals(resp.status, 400)
resp = retry(post,
- {'X-Account-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH})
+ {'X-Account-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH})
resp.read()
self.assertEquals(resp.status, 204)
- resp = retry(post,
- {'X-Account-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)})
+ resp = retry(
+ post,
+ {'X-Account-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)})
resp.read()
self.assertEquals(resp.status, 400)
diff --git a/test/functionalnosetests/test_container.py b/test/functionalnosetests/test_container.py
index af78a7a..15f7fc1 100755
--- a/test/functionalnosetests/test_container.py
+++ b/test/functionalnosetests/test_container.py
@@ -1,21 +1,6 @@
#!/usr/bin/python
-# Copyright (c) 2010-2013 OpenStack, LLC.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Copyright (c) 2013 Red Hat, Inc.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,7 +24,7 @@ from swift.common.constraints import MAX_META_COUNT, MAX_META_NAME_LENGTH, \
MAX_META_OVERALL_SIZE, MAX_META_VALUE_LENGTH
from swift_testing import check_response, retry, skip, skip2, skip3, \
- swift_test_perm, web_front_end
+ swift_test_perm, web_front_end
class TestContainer(unittest.TestCase):
@@ -48,10 +33,12 @@ class TestContainer(unittest.TestCase):
if skip:
raise SkipTest
self.name = uuid4().hex
+
def put(url, token, parsed, conn):
conn.request('PUT', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(put)
resp.read()
self.assertEquals(resp.status, 201)
@@ -59,15 +46,18 @@ class TestContainer(unittest.TestCase):
def tearDown(self):
if skip:
raise SkipTest
+
def get(url, token, parsed, conn):
conn.request('GET', parsed.path + '/' + self.name + '?format=json',
'', {'X-Auth-Token': token})
return check_response(conn)
+
def delete(url, token, parsed, conn, obj):
conn.request('DELETE',
'/'.join([parsed.path, self.name, obj['name']]), '',
{'X-Auth-Token': token})
return check_response(conn)
+
while True:
resp = retry(get)
body = resp.read()
@@ -79,10 +69,12 @@ class TestContainer(unittest.TestCase):
resp = retry(delete, obj)
resp.read()
self.assertEquals(resp.status, 204)
+
def delete(url, token, parsed, conn):
conn.request('DELETE', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(delete)
resp.read()
self.assertEquals(resp.status, 204)
@@ -90,14 +82,17 @@ class TestContainer(unittest.TestCase):
def test_multi_metadata(self):
if skip:
raise SkipTest
+
def post(url, token, parsed, conn, name, value):
conn.request('POST', parsed.path + '/' + self.name, '',
- {'X-Auth-Token': token, name: value})
+ {'X-Auth-Token': token, name: value})
return check_response(conn)
+
def head(url, token, parsed, conn):
conn.request('HEAD', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(post, 'X-Container-Meta-One', '1')
resp.read()
self.assertEquals(resp.status, 204)
@@ -154,27 +149,33 @@ class TestContainer(unittest.TestCase):
resp.read()
self.assert_(resp.status in (200, 204), resp.status)
self.assertEquals(resp.getheader(uni_key.encode('utf-8')),
- uni_value.encode('utf-8'))
+ uni_value.encode('utf-8'))
def test_PUT_metadata(self):
if skip:
raise SkipTest
+
def put(url, token, parsed, conn, name, value):
conn.request('PUT', parsed.path + '/' + name, '',
- {'X-Auth-Token': token, 'X-Container-Meta-Test': value})
+ {'X-Auth-Token': token,
+ 'X-Container-Meta-Test': value})
return check_response(conn)
+
def head(url, token, parsed, conn, name):
conn.request('HEAD', parsed.path + '/' + name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
def get(url, token, parsed, conn, name):
conn.request('GET', parsed.path + '/' + name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
def delete(url, token, parsed, conn, name):
conn.request('DELETE', parsed.path + '/' + name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
name = uuid4().hex
resp = retry(put, name, 'Value')
resp.read()
@@ -210,18 +211,23 @@ class TestContainer(unittest.TestCase):
def test_POST_metadata(self):
if skip:
raise SkipTest
+
def post(url, token, parsed, conn, value):
conn.request('POST', parsed.path + '/' + self.name, '',
- {'X-Auth-Token': token, 'X-Container-Meta-Test': value})
+ {'X-Auth-Token': token,
+ 'X-Container-Meta-Test': value})
return check_response(conn)
+
def head(url, token, parsed, conn):
conn.request('HEAD', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
def get(url, token, parsed, conn):
conn.request('GET', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(head)
resp.read()
self.assert_(resp.status in (200, 204), resp.status)
@@ -245,26 +251,31 @@ class TestContainer(unittest.TestCase):
def test_PUT_bad_metadata(self):
if skip:
raise SkipTest
+
def put(url, token, parsed, conn, name, extra_headers):
headers = {'X-Auth-Token': token}
headers.update(extra_headers)
conn.request('PUT', parsed.path + '/' + name, '', headers)
return check_response(conn)
+
def delete(url, token, parsed, conn, name):
conn.request('DELETE', parsed.path + '/' + name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
name = uuid4().hex
- resp = retry(put, name,
- {'X-Container-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'})
+ resp = retry(
+ put, name,
+ {'X-Container-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'})
resp.read()
self.assertEquals(resp.status, 201)
resp = retry(delete, name)
resp.read()
self.assertEquals(resp.status, 204)
name = uuid4().hex
- resp = retry(put, name,
- {'X-Container-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'})
+ resp = retry(
+ put, name,
+ {'X-Container-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'})
resp.read()
self.assertEquals(resp.status, 400)
resp = retry(delete, name)
@@ -272,16 +283,18 @@ class TestContainer(unittest.TestCase):
self.assertEquals(resp.status, 404)
name = uuid4().hex
- resp = retry(put, name,
- {'X-Container-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH})
+ resp = retry(
+ put, name,
+ {'X-Container-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH})
resp.read()
self.assertEquals(resp.status, 201)
resp = retry(delete, name)
resp.read()
self.assertEquals(resp.status, 204)
name = uuid4().hex
- resp = retry(put, name,
- {'X-Container-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)})
+ resp = retry(
+ put, name,
+ {'X-Container-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)})
resp.read()
self.assertEquals(resp.status, 400)
resp = retry(delete, name)
@@ -340,26 +353,32 @@ class TestContainer(unittest.TestCase):
def test_POST_bad_metadata(self):
if skip:
raise SkipTest
+
def post(url, token, parsed, conn, extra_headers):
headers = {'X-Auth-Token': token}
headers.update(extra_headers)
conn.request('POST', parsed.path + '/' + self.name, '', headers)
return check_response(conn)
- resp = retry(post,
- {'X-Container-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'})
+
+ resp = retry(
+ post,
+ {'X-Container-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'})
resp.read()
self.assertEquals(resp.status, 204)
- resp = retry(post,
- {'X-Container-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'})
+ resp = retry(
+ post,
+ {'X-Container-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'})
resp.read()
self.assertEquals(resp.status, 400)
- resp = retry(post,
- {'X-Container-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH})
+ resp = retry(
+ post,
+ {'X-Container-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH})
resp.read()
self.assertEquals(resp.status, 204)
- resp = retry(post,
- {'X-Container-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)})
+ resp = retry(
+ post,
+ {'X-Container-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)})
resp.read()
self.assertEquals(resp.status, 400)
@@ -399,36 +418,42 @@ class TestContainer(unittest.TestCase):
def test_public_container(self):
if skip:
raise SkipTest
+
def get(url, token, parsed, conn):
conn.request('GET', parsed.path + '/' + self.name)
return check_response(conn)
+
try:
resp = retry(get)
raise Exception('Should not have been able to GET')
- except Exception, err:
+ except Exception as err:
self.assert_(str(err).startswith('No result after '), err)
+
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token,
'X-Container-Read': '.r:*,.rlistings'})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
resp = retry(get)
resp.read()
self.assertEquals(resp.status, 204)
+
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token, 'X-Container-Read': ''})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
try:
resp = retry(get)
raise Exception('Should not have been able to GET')
- except Exception, err:
+ except Exception as err:
self.assert_(str(err).startswith('No result after '), err)
def test_cross_account_container(self):
@@ -436,27 +461,34 @@ class TestContainer(unittest.TestCase):
raise SkipTest
# Obtain the first account's string
first_account = ['unknown']
+
def get1(url, token, parsed, conn):
first_account[0] = parsed.path
conn.request('HEAD', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(get1)
resp.read()
+
# Ensure we can't access the container with the second account
def get2(url, token, parsed, conn):
conn.request('GET', first_account[0] + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(get2, use_account=2)
resp.read()
self.assertEquals(resp.status, 403)
+
# Make the container accessible by the second account
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
- {'X-Auth-Token': token, 'X-Container-Read': swift_test_perm[1],
- 'X-Container-Write': swift_test_perm[1]})
+ {'X-Auth-Token': token,
+ 'X-Container-Read': swift_test_perm[1],
+ 'X-Container-Write': swift_test_perm[1]})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
@@ -464,12 +496,14 @@ class TestContainer(unittest.TestCase):
resp = retry(get2, use_account=2)
resp.read()
self.assertEquals(resp.status, 204)
+
# Make the container private again
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token, 'X-Container-Read': '',
'X-Container-Write': ''})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
@@ -483,27 +517,33 @@ class TestContainer(unittest.TestCase):
raise SkipTest
# Obtain the first account's string
first_account = ['unknown']
+
def get1(url, token, parsed, conn):
first_account[0] = parsed.path
conn.request('HEAD', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(get1)
resp.read()
+
# Ensure we can't access the container with the second account
def get2(url, token, parsed, conn):
conn.request('GET', first_account[0] + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(get2, use_account=2)
resp.read()
self.assertEquals(resp.status, 403)
+
# Make the container completely public
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token,
'X-Container-Read': '.r:*,.rlistings'})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
@@ -511,20 +551,24 @@ class TestContainer(unittest.TestCase):
resp = retry(get2, use_account=2)
resp.read()
self.assertEquals(resp.status, 204)
+
# But we shouldn't be able to write with the second account
def put2(url, token, parsed, conn):
conn.request('PUT', first_account[0] + '/' + self.name + '/object',
'test object', {'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(put2, use_account=2)
resp.read()
self.assertEquals(resp.status, 403)
+
# Now make the container also writeable by the second account
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
- {'X-Auth-Token': token,
- 'X-Container-Write': swift_test_perm[1]})
+ {'X-Auth-Token': token,
+ 'X-Container-Write': swift_test_perm[1]})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
@@ -542,26 +586,33 @@ class TestContainer(unittest.TestCase):
raise SkipTest
# Obtain the first account's string
first_account = ['unknown']
+
def get1(url, token, parsed, conn):
first_account[0] = parsed.path
conn.request('HEAD', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(get1)
resp.read()
+
# Ensure we can't access the container with the third account
def get3(url, token, parsed, conn):
conn.request('GET', first_account[0] + '/' + self.name, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(get3, use_account=3)
resp.read()
self.assertEquals(resp.status, 403)
+
# Make the container accessible by the third account
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
- {'X-Auth-Token': token, 'X-Container-Read': swift_test_perm[2]})
+ {'X-Auth-Token': token,
+ 'X-Container-Read': swift_test_perm[2]})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
@@ -569,20 +620,24 @@ class TestContainer(unittest.TestCase):
resp = retry(get3, use_account=3)
resp.read()
self.assertEquals(resp.status, 204)
+
# But we shouldn't be able to write with the third account
def put3(url, token, parsed, conn):
conn.request('PUT', first_account[0] + '/' + self.name + '/object',
'test object', {'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(put3, use_account=3)
resp.read()
self.assertEquals(resp.status, 403)
+
# Now make the container also writeable by the third account
def post(url, token, parsed, conn):
conn.request('POST', parsed.path + '/' + self.name, '',
{'X-Auth-Token': token,
'X-Container-Write': swift_test_perm[2]})
return check_response(conn)
+
resp = retry(post)
resp.read()
self.assertEquals(resp.status, 204)
@@ -601,9 +656,10 @@ class TestContainer(unittest.TestCase):
def put(url, token, parsed, conn):
container_name = 'X' * 2048
- conn.request('PUT', '%s/%s' % (parsed.path,
- container_name), 'there', {'X-Auth-Token': token})
+ conn.request('PUT', '%s/%s' % (parsed.path, container_name),
+ 'there', {'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(put)
resp.read()
self.assertEquals(resp.status, 400)
@@ -618,6 +674,7 @@ class TestContainer(unittest.TestCase):
conn.request('PUT', '%s/abc%%00def' % parsed.path, '',
{'X-Auth-Token': token})
return check_response(conn)
+
resp = retry(put)
if (web_front_end == 'apache2'):
self.assertEquals(resp.status, 404)
diff --git a/test/functionalnosetests/test_object.py b/test/functionalnosetests/test_object.py
index 3972aaf..97cd8d0 100755
--- a/test/functionalnosetests/test_object.py
+++ b/test/functionalnosetests/test_object.py
@@ -1,21 +1,6 @@
#!/usr/bin/python
-# Copyright (c) 2010-2013 OpenStack, LLC.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Copyright (c) 2013 Red Hat, Inc.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -55,8 +40,9 @@ class TestObject(unittest.TestCase):
self.obj = uuid4().hex
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/%s' % (parsed.path, self.container,
- self.obj), 'test', {'X-Auth-Token': token})
+ conn.request('PUT', '%s/%s/%s' % (
+ parsed.path, self.container, self.obj), 'test',
+ {'X-Auth-Token': token})
return check_response(conn)
resp = retry(put)
resp.read()
@@ -182,7 +168,7 @@ class TestObject(unittest.TestCase):
try:
resp = retry(get)
raise Exception('Should not have been able to GET')
- except Exception, err:
+ except Exception as err:
self.assert_(str(err).startswith('No result after '))
def post(url, token, parsed, conn):
@@ -207,7 +193,7 @@ class TestObject(unittest.TestCase):
try:
resp = retry(get)
raise Exception('Should not have been able to GET')
- except Exception, err:
+ except Exception as err:
self.assert_(str(err).startswith('No result after '))
def test_private_object(self):
@@ -216,9 +202,9 @@ class TestObject(unittest.TestCase):
# Ensure we can't access the object with the third account
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/%s' % (parsed.path, self.container,
- self.obj), '',
- {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/%s' % (
+ parsed.path, self.container, self.obj), '',
+ {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get, use_account=3)
resp.read()
@@ -228,11 +214,11 @@ class TestObject(unittest.TestCase):
shared_container = uuid4().hex
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s' % (parsed.path,
- shared_container), '',
- {'X-Auth-Token': token,
- 'X-Container-Read': swift_test_perm[2],
- 'X-Container-Write': swift_test_perm[2]})
+ conn.request('PUT', '%s/%s' % (
+ parsed.path, shared_container), '',
+ {'X-Auth-Token': token,
+ 'X-Container-Read': swift_test_perm[2],
+ 'X-Container-Write': swift_test_perm[2]})
return check_response(conn)
resp = retry(put)
resp.read()
@@ -240,13 +226,11 @@ class TestObject(unittest.TestCase):
# verify third account can not copy from private container
def copy(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/%s' % (parsed.path,
- shared_container,
- 'private_object'),
- '', {'X-Auth-Token': token,
- 'Content-Length': '0',
- 'X-Copy-From': '%s/%s' % (self.container,
- self.obj)})
+ conn.request('PUT', '%s/%s/%s' % (
+ parsed.path, shared_container, 'private_object'), '',
+ {'X-Auth-Token': token,
+ 'Content-Length': '0',
+ 'X-Copy-From': '%s/%s' % (self.container, self.obj)})
return check_response(conn)
resp = retry(copy, use_account=3)
resp.read()
@@ -254,8 +238,9 @@ class TestObject(unittest.TestCase):
# verify third account can write "obj1" to shared container
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/%s' % (parsed.path, shared_container,
- 'obj1'), 'test', {'X-Auth-Token': token})
+ conn.request('PUT', '%s/%s/%s' % (
+ parsed.path, shared_container, 'obj1'), 'test',
+ {'X-Auth-Token': token})
return check_response(conn)
resp = retry(put, use_account=3)
resp.read()
@@ -263,12 +248,10 @@ class TestObject(unittest.TestCase):
# verify third account can copy "obj1" to shared container
def copy2(url, token, parsed, conn):
- conn.request('COPY', '%s/%s/%s' % (parsed.path,
- shared_container,
- 'obj1'),
- '', {'X-Auth-Token': token,
- 'Destination': '%s/%s' % (shared_container,
- 'obj1')})
+ conn.request('COPY', '%s/%s/%s' % (
+ parsed.path, shared_container, 'obj1'), '',
+ {'X-Auth-Token': token,
+ 'Destination': '%s/%s' % (shared_container, 'obj1')})
return check_response(conn)
resp = retry(copy2, use_account=3)
resp.read()
@@ -276,12 +259,11 @@ class TestObject(unittest.TestCase):
# verify third account STILL can not copy from private container
def copy3(url, token, parsed, conn):
- conn.request('COPY', '%s/%s/%s' % (parsed.path,
- self.container,
- self.obj),
- '', {'X-Auth-Token': token,
- 'Destination': '%s/%s' % (shared_container,
- 'private_object')})
+ conn.request('COPY', '%s/%s/%s' % (
+ parsed.path, self.container, self.obj), '',
+ {'X-Auth-Token': token,
+ 'Destination': '%s/%s' % (shared_container,
+ 'private_object')})
return check_response(conn)
resp = retry(copy3, use_account=3)
resp.read()
@@ -289,8 +271,9 @@ class TestObject(unittest.TestCase):
# clean up "obj1"
def delete(url, token, parsed, conn):
- conn.request('DELETE', '%s/%s/%s' % (parsed.path, shared_container,
- 'obj1'), '', {'X-Auth-Token': token})
+ conn.request('DELETE', '%s/%s/%s' % (
+ parsed.path, shared_container, 'obj1'), '',
+ {'X-Auth-Token': token})
return check_response(conn)
resp = retry(delete)
resp.read()
@@ -316,8 +299,8 @@ class TestObject(unittest.TestCase):
# Upload the first set of segments
def put(url, token, parsed, conn, objnum):
- conn.request('PUT', '%s/%s/segments1/%s' % (parsed.path,
- self.container, str(objnum)), segments1[objnum],
+ conn.request('PUT', '%s/%s/segments1/%s' % (
+ parsed.path, self.container, str(objnum)), segments1[objnum],
{'X-Auth-Token': token})
return check_response(conn)
for objnum in xrange(len(segments1)):
@@ -327,10 +310,11 @@ class TestObject(unittest.TestCase):
# Upload the manifest
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token,
- 'X-Object-Manifest': '%s/segments1/' % self.container,
- 'Content-Type': 'text/jibberish', 'Content-Length': '0'})
+ conn.request('PUT', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {
+ 'X-Auth-Token': token,
+ 'X-Object-Manifest': '%s/segments1/' % self.container,
+ 'Content-Type': 'text/jibberish', 'Content-Length': '0'})
return check_response(conn)
resp = retry(put)
resp.read()
@@ -338,8 +322,8 @@ class TestObject(unittest.TestCase):
# Get the manifest (should get all the segments as the body)
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get)
self.assertEquals(resp.read(), ''.join(segments1))
@@ -348,9 +332,9 @@ class TestObject(unittest.TestCase):
# Get with a range at the start of the second segment
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token, 'Range':
- 'bytes=3-'})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {
+ 'X-Auth-Token': token, 'Range': 'bytes=3-'})
return check_response(conn)
resp = retry(get)
self.assertEquals(resp.read(), ''.join(segments1[1:]))
@@ -358,9 +342,9 @@ class TestObject(unittest.TestCase):
# Get with a range in the middle of the second segment
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token, 'Range':
- 'bytes=5-'})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {
+ 'X-Auth-Token': token, 'Range': 'bytes=5-'})
return check_response(conn)
resp = retry(get)
self.assertEquals(resp.read(), ''.join(segments1)[5:])
@@ -368,9 +352,9 @@ class TestObject(unittest.TestCase):
# Get with a full start and stop range
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token, 'Range':
- 'bytes=5-10'})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {
+ 'X-Auth-Token': token, 'Range': 'bytes=5-10'})
return check_response(conn)
resp = retry(get)
self.assertEquals(resp.read(), ''.join(segments1)[5:11])
@@ -378,8 +362,8 @@ class TestObject(unittest.TestCase):
# Upload the second set of segments
def put(url, token, parsed, conn, objnum):
- conn.request('PUT', '%s/%s/segments2/%s' % (parsed.path,
- self.container, str(objnum)), segments2[objnum],
+ conn.request('PUT', '%s/%s/segments2/%s' % (
+ parsed.path, self.container, str(objnum)), segments2[objnum],
{'X-Auth-Token': token})
return check_response(conn)
for objnum in xrange(len(segments2)):
@@ -389,8 +373,8 @@ class TestObject(unittest.TestCase):
# Get the manifest (should still be the first segments of course)
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get)
self.assertEquals(resp.read(), ''.join(segments1))
@@ -398,10 +382,11 @@ class TestObject(unittest.TestCase):
# Update the manifest
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token,
- 'X-Object-Manifest': '%s/segments2/' % self.container,
- 'Content-Length': '0'})
+ conn.request('PUT', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {
+ 'X-Auth-Token': token,
+ 'X-Object-Manifest': '%s/segments2/' % self.container,
+ 'Content-Length': '0'})
return check_response(conn)
resp = retry(put)
resp.read()
@@ -409,8 +394,8 @@ class TestObject(unittest.TestCase):
# Get the manifest (should be the second set of segments now)
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get)
self.assertEquals(resp.read(), ''.join(segments2))
@@ -420,8 +405,8 @@ class TestObject(unittest.TestCase):
# Ensure we can't access the manifest with the third account
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get, use_account=3)
resp.read()
@@ -430,8 +415,8 @@ class TestObject(unittest.TestCase):
# Grant access to the third account
def post(url, token, parsed, conn):
conn.request('POST', '%s/%s' % (parsed.path, self.container),
- '', {'X-Auth-Token': token,
- 'X-Container-Read': swift_test_perm[2]})
+ '', {'X-Auth-Token': token,
+ 'X-Container-Read': swift_test_perm[2]})
return check_response(conn)
resp = retry(post)
resp.read()
@@ -439,8 +424,8 @@ class TestObject(unittest.TestCase):
# The third account should be able to get the manifest now
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get, use_account=3)
self.assertEquals(resp.read(), ''.join(segments2))
@@ -459,8 +444,8 @@ class TestObject(unittest.TestCase):
# Upload the third set of segments in the other container
def put(url, token, parsed, conn, objnum):
- conn.request('PUT', '%s/%s/segments3/%s' % (parsed.path,
- acontainer, str(objnum)), segments3[objnum],
+ conn.request('PUT', '%s/%s/segments3/%s' % (
+ parsed.path, acontainer, str(objnum)), segments3[objnum],
{'X-Auth-Token': token})
return check_response(conn)
for objnum in xrange(len(segments3)):
@@ -470,10 +455,11 @@ class TestObject(unittest.TestCase):
# Update the manifest
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token,
- 'X-Object-Manifest': '%s/segments3/' % acontainer,
- 'Content-Length': '0'})
+ conn.request('PUT', '%s/%s/manifest' % (
+ parsed.path, self.container), '',
+ {'X-Auth-Token': token,
+ 'X-Object-Manifest': '%s/segments3/' % acontainer,
+ 'Content-Length': '0'})
return check_response(conn)
resp = retry(put)
resp.read()
@@ -481,8 +467,8 @@ class TestObject(unittest.TestCase):
# Get the manifest to ensure it's the third set of segments
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get)
self.assertEquals(resp.read(), ''.join(segments3))
@@ -495,8 +481,8 @@ class TestObject(unittest.TestCase):
# manifest itself is not).
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get, use_account=3)
resp.read()
@@ -505,8 +491,8 @@ class TestObject(unittest.TestCase):
# Grant access to the third account
def post(url, token, parsed, conn):
conn.request('POST', '%s/%s' % (parsed.path, acontainer),
- '', {'X-Auth-Token': token,
- 'X-Container-Read': swift_test_perm[2]})
+ '', {'X-Auth-Token': token,
+ 'X-Container-Read': swift_test_perm[2]})
return check_response(conn)
resp = retry(post)
resp.read()
@@ -514,8 +500,8 @@ class TestObject(unittest.TestCase):
# The third account should be able to get the manifest now
def get(url, token, parsed, conn):
- conn.request('GET', '%s/%s/manifest' % (parsed.path,
- self.container), '', {'X-Auth-Token': token})
+ conn.request('GET', '%s/%s/manifest' % (
+ parsed.path, self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(get, use_account=3)
self.assertEquals(resp.read(), ''.join(segments3))
@@ -523,7 +509,8 @@ class TestObject(unittest.TestCase):
# Delete the manifest
def delete(url, token, parsed, conn, objnum):
- conn.request('DELETE', '%s/%s/manifest' % (parsed.path,
+ conn.request('DELETE', '%s/%s/manifest' % (
+ parsed.path,
self.container), '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(delete, objnum)
@@ -532,8 +519,9 @@ class TestObject(unittest.TestCase):
# Delete the third set of segments
def delete(url, token, parsed, conn, objnum):
- conn.request('DELETE', '%s/%s/segments3/%s' % (parsed.path,
- acontainer, str(objnum)), '', {'X-Auth-Token': token})
+ conn.request('DELETE', '%s/%s/segments3/%s' % (
+ parsed.path, acontainer, str(objnum)), '',
+ {'X-Auth-Token': token})
return check_response(conn)
for objnum in xrange(len(segments3)):
resp = retry(delete, objnum)
@@ -542,8 +530,9 @@ class TestObject(unittest.TestCase):
# Delete the second set of segments
def delete(url, token, parsed, conn, objnum):
- conn.request('DELETE', '%s/%s/segments2/%s' % (parsed.path,
- self.container, str(objnum)), '', {'X-Auth-Token': token})
+ conn.request('DELETE', '%s/%s/segments2/%s' % (
+ parsed.path, self.container, str(objnum)), '',
+ {'X-Auth-Token': token})
return check_response(conn)
for objnum in xrange(len(segments2)):
resp = retry(delete, objnum)
@@ -552,8 +541,9 @@ class TestObject(unittest.TestCase):
# Delete the first set of segments
def delete(url, token, parsed, conn, objnum):
- conn.request('DELETE', '%s/%s/segments1/%s' % (parsed.path,
- self.container, str(objnum)), '', {'X-Auth-Token': token})
+ conn.request('DELETE', '%s/%s/segments1/%s' % (
+ parsed.path, self.container, str(objnum)), '',
+ {'X-Auth-Token': token})
return check_response(conn)
for objnum in xrange(len(segments1)):
resp = retry(delete, objnum)
@@ -563,7 +553,7 @@ class TestObject(unittest.TestCase):
# Delete the extra container
def delete(url, token, parsed, conn):
conn.request('DELETE', '%s/%s' % (parsed.path, acontainer), '',
- {'X-Auth-Token': token})
+ {'X-Auth-Token': token})
return check_response(conn)
resp = retry(delete)
resp.read()
@@ -574,8 +564,8 @@ class TestObject(unittest.TestCase):
raise SkipTest
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/hi' % (parsed.path,
- self.container), 'there', {'X-Auth-Token': token})
+ conn.request('PUT', '%s/%s/hi' % (parsed.path, self.container),
+ 'there', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(put)
resp.read()
@@ -583,7 +573,7 @@ class TestObject(unittest.TestCase):
def delete(url, token, parsed, conn):
conn.request('DELETE', '%s/%s/hi' % (parsed.path, self.container),
- '', {'X-Auth-Token': token})
+ '', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(delete)
resp.read()
@@ -596,7 +586,8 @@ class TestObject(unittest.TestCase):
raise SkipTest
def put(url, token, parsed, conn):
- conn.request('PUT', '%s/%s/abc%%00def' % (parsed.path,
+ conn.request('PUT', '%s/%s/abc%%00def' % (
+ parsed.path,
self.container), 'test', {'X-Auth-Token': token})
return check_response(conn)
resp = retry(put)
diff --git a/test/unit/__init__.py b/test/unit/__init__.py
index 04895b4..76e09c1 100644
--- a/test/unit/__init__.py
+++ b/test/unit/__init__.py
@@ -1,3 +1,18 @@
+# Copyright (c) 2010-2012 OpenStack Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
""" Swift tests """
import os
@@ -8,6 +23,7 @@ from sys import exc_info
from contextlib import contextmanager
from collections import defaultdict
from tempfile import NamedTemporaryFile
+import time
from eventlet.green import socket
from tempfile import mkdtemp
from shutil import rmtree
@@ -142,13 +158,24 @@ def tmpfile(content):
xattr_data = {}
-def _get_inode(fd):
- if not isinstance(fd, int):
- try:
- fd = fd.fileno()
- except AttributeError:
- return os.stat(fd).st_ino
- return os.fstat(fd).st_ino
+def _get_inode(fd_or_name):
+ try:
+ if isinstance(fd_or_name, int):
+ fd = fd_or_name
+ else:
+ try:
+ fd = fd_or_name.fileno()
+ except AttributeError:
+ fd = None
+ if fd is None:
+ ino = os.stat(fd_or_name).st_ino
+ else:
+ ino = os.fstat(fd).st_ino
+ except OSError as err:
+ ioerr = IOError()
+ ioerr.errno = err.errno
+ raise ioerr
+ return ino
def _setxattr(fd, k, v):
@@ -199,27 +226,57 @@ class NullLoggingHandler(logging.Handler):
pass
-class FakeLogger(object):
+class UnmockTimeModule(object):
+ """
+ Even if a test mocks time.time - you can restore unmolested behavior in a
+ another module who imports time directly by monkey patching it's imported
+ reference to the module with an instance of this class
+ """
+
+ _orig_time = time.time
+
+ def __getattribute__(self, name):
+ if name == 'time':
+ return UnmockTimeModule._orig_time
+ return getattr(time, name)
+
+
+# logging.LogRecord.__init__ calls time.time
+logging.time = UnmockTimeModule()
+
+
+class FakeLogger(logging.Logger):
# a thread safe logger
def __init__(self, *args, **kwargs):
self._clear()
+ self.name = 'swift.unit.fake_logger'
self.level = logging.NOTSET
if 'facility' in kwargs:
self.facility = kwargs['facility']
def _clear(self):
self.log_dict = defaultdict(list)
+ self.lines_dict = defaultdict(list)
def _store_in(store_name):
def stub_fn(self, *args, **kwargs):
self.log_dict[store_name].append((args, kwargs))
return stub_fn
- error = _store_in('error')
- info = _store_in('info')
- warning = _store_in('warning')
- debug = _store_in('debug')
+ def _store_and_log_in(store_name):
+ def stub_fn(self, *args, **kwargs):
+ self.log_dict[store_name].append((args, kwargs))
+ self._log(store_name, args[0], args[1:], **kwargs)
+ return stub_fn
+
+ def get_lines_for_level(self, level):
+ return self.lines_dict[level]
+
+ error = _store_and_log_in('error')
+ info = _store_and_log_in('info')
+ warning = _store_and_log_in('warning')
+ debug = _store_and_log_in('debug')
def exception(self, *args, **kwargs):
self.log_dict['exception'].append((args, kwargs, str(exc_info()[1])))
@@ -267,7 +324,13 @@ class FakeLogger(object):
pass
def handle(self, record):
- pass
+ try:
+ line = record.getMessage()
+ except TypeError:
+ print 'WARNING: unable to format log message %r %% %r' % (
+ record.msg, record.args)
+ raise
+ self.lines_dict[record.levelno].append(line)
def flush(self):
pass
@@ -354,11 +417,13 @@ def mock(update):
else:
deletes.append((module, attr))
setattr(module, attr, value)
- yield True
- for module, attr, value in returns:
- setattr(module, attr, value)
- for module, attr in deletes:
- delattr(module, attr)
+ try:
+ yield True
+ finally:
+ for module, attr, value in returns:
+ setattr(module, attr, value)
+ for module, attr in deletes:
+ delattr(module, attr)
def fake_http_connect(*code_iter, **kwargs):
@@ -466,6 +531,8 @@ def fake_http_connect(*code_iter, **kwargs):
body_iter = iter(body_iter)
def connect(*args, **ckwargs):
+ if kwargs.get('slow_connect', False):
+ sleep(0.1)
if 'give_content_type' in kwargs:
if len(args) >= 7 and 'Content-Type' in args[6]:
kwargs['give_content_type'](args[6]['Content-Type'])
diff --git a/test/unit/common/test_fs_utils.py b/test/unit/common/test_fs_utils.py
index 02c6ecb..19fc2df 100644
--- a/test/unit/common/test_fs_utils.py
+++ b/test/unit/common/test_fs_utils.py
@@ -30,8 +30,22 @@ from gluster.swift.common.exceptions import NotDirectoryError, \
def mock_os_fsync(fd):
return True
-def mock_tpool_execute(func, *args, **kwargs):
- func(*args, **kwargs)
+def mock_os_fdatasync(fd):
+ return True
+
+
+class TestFakefile(unittest.TestCase):
+ """ Tests for common.fs_utils.Fake_file """
+
+ def test_Fake_file(self):
+ path = "/tmp/bar"
+ ff = fs.Fake_file(path)
+ self.assertEqual(path, ff.path)
+ self.assertEqual(0, ff.tell())
+ self.assertEqual(None, ff.read(50))
+ self.assertEqual(-1, ff.fileno())
+ self.assertEqual(None, ff.close())
+
class TestFsUtils(unittest.TestCase):
""" Tests for common.fs_utils """
@@ -688,9 +702,8 @@ class TestFsUtils(unittest.TestCase):
fd, tmpfile = mkstemp(dir=tmpdir)
try:
os.write(fd, 'test')
- with patch('eventlet.tpool.execute', mock_tpool_execute):
- with patch('os.fsync', mock_os_fsync):
- assert fs.do_fsync(fd) is None
+ with patch('os.fsync', mock_os_fsync):
+ assert fs.do_fsync(fd) is None
except GlusterFileSystemOSError as ose:
self.fail('Opening a temporary file failed with %s' %ose.strerror)
else:
@@ -704,15 +717,47 @@ class TestFsUtils(unittest.TestCase):
try:
fd, tmpfile = mkstemp(dir=tmpdir)
os.write(fd, 'test')
- with patch('eventlet.tpool.execute', mock_tpool_execute):
- with patch('os.fsync', mock_os_fsync):
- assert fs.do_fsync(fd) is None
+ with patch('os.fsync', mock_os_fsync):
+ assert fs.do_fsync(fd) is None
+ os.close(fd)
+ try:
+ fs.do_fsync(fd)
+ except GlusterFileSystemOSError:
+ pass
+ else:
+ self.fail("Expected GlusterFileSystemOSError")
+ finally:
+ shutil.rmtree(tmpdir)
+
+ def test_do_fdatasync(self):
+ tmpdir = mkdtemp()
+ try:
+ fd, tmpfile = mkstemp(dir=tmpdir)
+ try:
+ os.write(fd, 'test')
+ with patch('os.fdatasync', mock_os_fdatasync):
+ assert fs.do_fdatasync(fd) is None
+ except GlusterFileSystemOSError as ose:
+ self.fail('Opening a temporary file failed with %s' %ose.strerror)
+ else:
os.close(fd)
- try:
- fs.do_fsync(fd)
- except GlusterFileSystemOSError:
- pass
- else:
- self.fail("Expected GlusterFileSystemOSError")
+ finally:
+ shutil.rmtree(tmpdir)
+
+
+ def test_do_fdatasync_err(self):
+ tmpdir = mkdtemp()
+ try:
+ fd, tmpfile = mkstemp(dir=tmpdir)
+ os.write(fd, 'test')
+ with patch('os.fdatasync', mock_os_fdatasync):
+ assert fs.do_fdatasync(fd) is None
+ os.close(fd)
+ try:
+ fs.do_fdatasync(fd)
+ except GlusterFileSystemOSError:
+ pass
+ else:
+ self.fail("Expected GlusterFileSystemOSError")
finally:
shutil.rmtree(tmpdir)
diff --git a/test/unit/obj/test_diskfile.py b/test/unit/obj/test_diskfile.py
index 7475105..27ff51e 100644
--- a/test/unit/obj/test_diskfile.py
+++ b/test/unit/obj/test_diskfile.py
@@ -43,18 +43,35 @@ from test.unit import FakeLogger
_metadata = {}
-def _mock_read_metadata(filename):
+def _mapit(filename_or_fd):
+ if isinstance(filename_or_fd, int):
+ statmeth = os.fstat
+ else:
+ statmeth = os.lstat
+ try:
+ stats = statmeth(filename_or_fd)
+ except OSError as err:
+ if err.errno == errno.ENOENT:
+ raise GlusterFileSystemOSError(
+ err.errno, '%s, os.fstat(%s)' % (err.strerror, filename_or_fd))
+ raise
+ return stats.st_ino
+
+
+def _mock_read_metadata(filename_or_fd):
global _metadata
- if filename in _metadata:
- md = _metadata[filename]
+ ino = _mapit(filename_or_fd)
+ if ino in _metadata:
+ md = _metadata[ino].copy()
else:
md = {}
return md
-def _mock_write_metadata(filename, metadata):
+def _mock_write_metadata(filename_or_fd, metadata):
global _metadata
- _metadata[filename] = metadata
+ ino = _mapit(filename_or_fd)
+ _metadata[ino] = metadata.copy()
def _mock_clear_metadata():
@@ -127,8 +144,7 @@ class TestDiskFile(unittest.TestCase):
assert gdf.logger == self.lg
assert gdf.uid == DEFAULT_UID
assert gdf.gid == DEFAULT_GID
- assert gdf.metadata == {}
- assert gdf.meta_file is None
+ assert gdf._metadata == None
assert gdf.data_file is None
assert gdf.fp is None
assert gdf.iter_etag is None
@@ -146,7 +162,7 @@ class TestDiskFile(unittest.TestCase):
assert gdf.datadir == os.path.join(self.td, "vol0", "bar", "b", "a")
assert gdf.device_path == os.path.join(self.td, "vol0")
- def test_constructor_no_metadata(self):
+ def test_open_no_metadata(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_file = os.path.join(the_path, "z")
os.makedirs(the_path)
@@ -164,12 +180,13 @@ class TestDiskFile(unittest.TestCase):
'Content-Type': 'application/octet-stream'}
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- assert gdf.fp is None
- assert gdf.metadata == exp_md
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ assert gdf.fp is not None
+ assert gdf._metadata == exp_md
- def test_constructor_existing_metadata(self):
+ def test_open_existing_metadata(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_file = os.path.join(the_path, "z")
os.makedirs(the_path)
@@ -182,37 +199,39 @@ class TestDiskFile(unittest.TestCase):
'ETag': 'etag',
'X-Timestamp': 'ts',
'Content-Type': 'application/loctet-stream'}
- _metadata[the_file] = ini_md
+ _metadata[_mapit(the_file)] = ini_md
exp_md = ini_md.copy()
del exp_md['X-Type']
del exp_md['X-Object-Type']
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- assert gdf.fp is None
- assert gdf.metadata == exp_md
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ assert gdf.fp is not None
+ assert gdf._metadata == exp_md
- def test_constructor_invalid_existing_metadata(self):
+ def test_open_invalid_existing_metadata(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_file = os.path.join(the_path, "z")
+ os.makedirs(the_path)
+ with open(the_file, "wb") as fd:
+ fd.write("1234")
inv_md = {
'Content-Length': 5,
'ETag': 'etag',
'X-Timestamp': 'ts',
'Content-Type': 'application/loctet-stream'}
- _metadata[the_file] = inv_md
- os.makedirs(the_path)
- with open(the_file, "wb") as fd:
- fd.write("1234")
+ _metadata[_mapit(the_file)] = inv_md
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- assert gdf.fp is None
- assert gdf.metadata != inv_md
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ assert gdf.fp is not None
+ assert gdf._metadata != inv_md
- def test_constructor_isdir(self):
+ def test_open_isdir(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_dir = os.path.join(the_path, "d")
os.makedirs(the_dir)
@@ -223,29 +242,16 @@ class TestDiskFile(unittest.TestCase):
'ETag': 'etag',
'X-Timestamp': 'ts',
'Content-Type': 'application/loctet-stream'}
- _metadata[the_dir] = ini_md
+ _metadata[_mapit(the_dir)] = ini_md
exp_md = ini_md.copy()
del exp_md['X-Type']
del exp_md['X-Object-Type']
- gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d",
- keep_data_fp=True)
+ gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d")
assert gdf._obj == "d"
- assert gdf.data_file == the_dir
- assert gdf._is_dir
- assert gdf.metadata == exp_md
-
- def test_constructor_keep_data_fp(self):
- the_path = os.path.join(self.td, "vol0", "bar")
- the_file = os.path.join(the_path, "z")
- os.makedirs(the_path)
- with open(the_file, "wb") as fd:
- fd.write("1234")
- gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z",
- keep_data_fp=True)
- assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- assert gdf.fp is not None
+ with gdf.open():
+ assert gdf.data_file == the_dir
+ assert gdf._is_dir
+ assert gdf._metadata == exp_md
def test_constructor_chunk_size(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z",
@@ -258,8 +264,7 @@ class TestDiskFile(unittest.TestCase):
assert gdf.iter_hook == 'hook'
def test_close_no_open_fp(self):
- gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z",
- keep_data_fp=True)
+ gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
gdf._is_dir = False
self.called = False
@@ -276,28 +281,32 @@ class TestDiskFile(unittest.TestCase):
the_dir = "dir"
self.called = False
os.makedirs(os.path.join(the_cont, the_dir))
- gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir",
- keep_data_fp=True)
-
- ret = isinstance(gdf.fp, Fake_file)
- self.assertTrue(ret)
+ gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
+ with gdf.open():
+ ret = isinstance(gdf.fp, Fake_file)
+ self.assertTrue(ret)
- # Get a File descriptor
- fd = gdf.fp
+ # Get a "Fake_file" pointer
+ ffp = gdf.fp
- # This expected to call Fake_file interfaces
- ret = fd.tell()
- self.assertEqual(ret , 0)
+ # This expected to call Fake_file interfaces
+ ret = ffp.tell()
+ self.assertEqual(ret, 0)
- ret = fd.read(1)
- self.assertEqual(ret , 0)
+ ret = ffp.read(1)
+ self.assertEqual(ret, None)
- ret = fd.fileno()
- self.assertEqual(ret, -1)
+ ret = ffp.fileno()
+ self.assertEqual(ret, -1)
- ret = fd.close()
- self.assertFalse(self.called)
+ def our_do_close(ffp):
+ self.called = True
+ with mock.patch("gluster.swift.obj.diskfile.do_close",
+ our_do_close):
+ ret = ffp.close()
+ self.assertEqual(ret, None)
+ self.assertFalse(self.called)
def test_close_file_object(self):
the_cont = os.path.join(self.td, "vol0", "bar")
@@ -306,22 +315,23 @@ class TestDiskFile(unittest.TestCase):
os.makedirs(the_cont)
with open(the_file, "wb") as fd:
fd.write("1234")
- gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z",
- keep_data_fp=True)
+ gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
def our_do_close(fp):
self.called = True
with mock.patch("gluster.swift.obj.diskfile.do_close",
our_do_close):
- gdf.close()
+ with gdf.open():
+ assert not self.called
assert self.called
def test_is_deleted(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
- assert gdf.is_deleted()
- gdf.data_file = os.path.join(self.td, "bar")
- assert not gdf.is_deleted()
+ with gdf.open():
+ assert gdf.is_deleted()
+ gdf.data_file = os.path.join(self.td, "bar")
+ assert not gdf.is_deleted()
def test_create_dir_object_no_md(self):
the_cont = os.path.join(self.td, "vol0", "bar")
@@ -334,7 +344,7 @@ class TestDiskFile(unittest.TestCase):
gdf._create_dir_object(the_dir)
full_dir_path = os.path.join(the_cont, the_dir)
assert os.path.isdir(full_dir_path)
- assert full_dir_path not in _metadata
+ assert _mapit(full_dir_path) not in _metadata
def test_create_dir_object_with_md(self):
the_cont = os.path.join(self.td, "vol0", "bar")
@@ -349,7 +359,7 @@ class TestDiskFile(unittest.TestCase):
gdf._create_dir_object(the_dir, dir_md)
full_dir_path = os.path.join(the_cont, the_dir)
assert os.path.isdir(full_dir_path)
- assert full_dir_path in _metadata
+ assert _mapit(full_dir_path) in _metadata
def test_create_dir_object_exists(self):
the_path = os.path.join(self.td, "vol0", "bar")
@@ -371,7 +381,7 @@ class TestDiskFile(unittest.TestCase):
DiskFileError, gdf._create_dir_object, the_dir)
gluster.swift.obj.diskfile.do_chown = dc
self.assertFalse(os.path.isdir(the_dir))
- self.assertFalse(the_dir in _metadata)
+ self.assertFalse(_mapit(the_dir) in _metadata)
def test_create_dir_object_do_stat_failure(self):
the_path = os.path.join(self.td, "vol0", "bar")
@@ -393,25 +403,26 @@ class TestDiskFile(unittest.TestCase):
DiskFileError, gdf._create_dir_object, the_dir)
gluster.swift.obj.diskfile.do_chown = dc
self.assertFalse(os.path.isdir(the_dir))
- self.assertFalse(the_dir in _metadata)
+ self.assertFalse(_mapit(the_dir) in _metadata)
def test_put_metadata(self):
- the_path = os.path.join(self.td, "vol0", "bar")
- the_dir = os.path.join(the_path, "z")
+ the_dir = os.path.join(self.td, "vol0", "bar", "z")
os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
md = {'Content-Type': 'application/octet-stream', 'a': 'b'}
gdf.put_metadata(md.copy())
- assert gdf.metadata == md, "gdf.metadata = %r, md = %r" % (
- gdf.metadata, md)
- assert _metadata[the_dir] == md
+ assert gdf._metadata is None
+ fmd = _metadata[_mapit(the_dir)]
+ md.update({'X-Object-Type': 'file', 'X-Type': 'Object'})
+ assert fmd == md, "on-disk md = %r, md = %r" % (fmd, md)
def test_put_w_tombstone(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
- assert gdf.metadata == {}
+ assert gdf._metadata == None
gdf.put_metadata({'x': '1'}, tombstone=True)
- assert gdf.metadata == {}
+ assert gdf._metadata is None
+ assert _metadata == {}
def test_put_w_meta_file(self):
the_path = os.path.join(self.td, "vol0", "bar")
@@ -420,11 +431,13 @@ class TestDiskFile(unittest.TestCase):
with open(the_file, "wb") as fd:
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
- newmd = gdf.metadata.copy()
- newmd['X-Object-Meta-test'] = '1234'
+ with gdf.open():
+ newmd = gdf.get_metadata().copy()
+ newmd['X-Object-Meta-test'] = '1234'
gdf.put_metadata(newmd)
- assert gdf.metadata == newmd
- assert _metadata[the_file] == newmd
+ assert gdf._metadata is None
+ fmd = _metadata[_mapit(the_file)]
+ assert fmd == newmd, "on-disk md = %r, newmd = %r" % (fmd, newmd)
def test_put_w_meta_file_no_content_type(self):
the_path = os.path.join(self.td, "vol0", "bar")
@@ -433,67 +446,72 @@ class TestDiskFile(unittest.TestCase):
with open(the_file, "wb") as fd:
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
- newmd = gdf.metadata.copy()
- newmd['Content-Type'] = ''
- newmd['X-Object-Meta-test'] = '1234'
+ with gdf.open():
+ newmd = gdf.get_metadata().copy()
+ newmd['Content-Type'] = ''
+ newmd['X-Object-Meta-test'] = '1234'
gdf.put_metadata(newmd)
- assert gdf.metadata == newmd
- assert _metadata[the_file] == newmd
+ assert gdf._metadata is None
+ fmd = _metadata[_mapit(the_file)]
+ assert fmd == newmd, "on-disk md = %r, newmd = %r" % (fmd, newmd)
def test_put_w_meta_dir(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_dir = os.path.join(the_path, "dir")
os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
- newmd = gdf.metadata.copy()
- newmd['X-Object-Meta-test'] = '1234'
+ with gdf.open():
+ newmd = gdf.get_metadata().copy()
+ newmd['X-Object-Meta-test'] = '1234'
gdf.put_metadata(newmd)
- assert gdf.metadata == newmd
- assert _metadata[the_dir] == newmd
+ assert gdf._metadata is None
+ fmd = _metadata[_mapit(the_dir)]
+ assert fmd == newmd, "on-disk md = %r, newmd = %r" % (fmd, newmd)
def test_put_w_marker_dir(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_dir = os.path.join(the_path, "dir")
os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
- newmd = gdf.metadata.copy()
- newmd['X-Object-Meta-test'] = '1234'
+ with gdf.open():
+ newmd = gdf.get_metadata().copy()
+ newmd['X-Object-Meta-test'] = '1234'
gdf.put_metadata(newmd)
- assert gdf.metadata == newmd
- assert _metadata[the_dir] == newmd
+ assert gdf._metadata is None
+ fmd = _metadata[_mapit(the_dir)]
+ assert fmd == newmd, "on-disk md = %r, newmd = %r" % (fmd, newmd)
def test_put_w_marker_dir_create(self):
the_cont = os.path.join(self.td, "vol0", "bar")
the_dir = os.path.join(the_cont, "dir")
os.makedirs(the_cont)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
- assert gdf.metadata == {}
+ assert gdf._metadata == None
newmd = {
'ETag': 'etag',
'X-Timestamp': 'ts',
'Content-Type': 'application/directory'}
- with gdf.writer() as dw:
- dw.put(newmd, extension='.dir')
- assert gdf.data_file == the_dir
- for key, val in newmd.items():
- assert gdf.metadata[key] == val
- assert _metadata[the_dir][key] == val
- assert gdf.metadata[X_OBJECT_TYPE] == DIR_OBJECT
- assert _metadata[the_dir][X_OBJECT_TYPE] == DIR_OBJECT
+ with gdf.create() as dw:
+ dw.put(newmd.copy(), extension='.dir')
+ with gdf.open():
+ assert gdf.data_file == the_dir
+ for key, val in newmd.items():
+ assert gdf._metadata[key] == val
+ assert _metadata[_mapit(the_dir)][key] == val
+ assert X_OBJECT_TYPE not in gdf._metadata, "md = %r" % gdf._metadata
+ assert _metadata[_mapit(the_dir)][X_OBJECT_TYPE] == DIR_OBJECT
def test_put_is_dir(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_dir = os.path.join(the_path, "dir")
os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
- origmd = gdf.metadata.copy()
- origfmd = _metadata[the_dir]
- newmd = gdf.metadata.copy()
# FIXME: This is a hack to get to the code-path; it is not clear
# how this can happen normally.
- newmd['Content-Type'] = ''
- newmd['X-Object-Meta-test'] = '1234'
- with gdf.writer() as dw:
+ newmd = {
+ 'Content-Type': '',
+ 'X-Object-Meta-test': '1234'}
+ with gdf.create() as dw:
try:
dw.put(newmd, extension='.data')
except DiskFileError:
@@ -501,8 +519,6 @@ class TestDiskFile(unittest.TestCase):
else:
self.fail("Expected to encounter"
" 'already-exists-as-dir' exception")
- assert gdf.metadata == origmd
- assert _metadata[the_dir] == origfmd
def test_put(self):
the_cont = os.path.join(self.td, "vol0", "bar")
@@ -525,7 +541,7 @@ class TestDiskFile(unittest.TestCase):
'Content-Length': '5',
}
- with gdf.writer() as dw:
+ with gdf.create() as dw:
assert dw.tmppath is not None
tmppath = dw.tmppath
dw.write(body)
@@ -561,7 +577,7 @@ class TestDiskFile(unittest.TestCase):
with mock.patch("os.open", mock_open):
try:
- with gdf.writer() as dw:
+ with gdf.create() as dw:
assert dw.tmppath is not None
dw.write(body)
dw.put(metadata)
@@ -601,7 +617,7 @@ class TestDiskFile(unittest.TestCase):
with mock.patch("gluster.swift.obj.diskfile.sleep", mock_sleep):
with mock.patch("os.rename", mock_rename):
try:
- with gdf.writer() as dw:
+ with gdf.create() as dw:
assert dw.tmppath is not None
dw.write(body)
dw.put(metadata)
@@ -631,7 +647,7 @@ class TestDiskFile(unittest.TestCase):
'Content-Length': '5',
}
- with gdf.writer() as dw:
+ with gdf.create() as dw:
assert dw.tmppath is not None
tmppath = dw.tmppath
dw.write(body)
@@ -642,32 +658,32 @@ class TestDiskFile(unittest.TestCase):
assert os.path.exists(gdf.data_file)
assert not os.path.exists(tmppath)
- def test_unlinkold_no_metadata(self):
+ def test_delete_no_metadata(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
- assert gdf.metadata == {}
+ assert gdf._metadata == None
_saved_rmobjdir = gluster.swift.obj.diskfile.rmobjdir
gluster.swift.obj.diskfile.rmobjdir = _mock_rmobjdir
try:
- gdf.unlinkold(None)
+ gdf.delete(1.0)
except MockException as exp:
self.fail(str(exp))
finally:
gluster.swift.obj.diskfile.rmobjdir = _saved_rmobjdir
- def test_unlinkold_same_timestamp(self):
+ def test_delete_same_timestamp(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
- assert gdf.metadata == {}
- gdf.metadata['X-Timestamp'] = 1
+ assert gdf._metadata == None
+ gdf._metadata = {'X-Timestamp': 1}
_saved_rmobjdir = gluster.swift.obj.diskfile.rmobjdir
gluster.swift.obj.diskfile.rmobjdir = _mock_rmobjdir
try:
- gdf.unlinkold(1)
+ gdf.delete(1)
except MockException as exp:
self.fail(str(exp))
finally:
gluster.swift.obj.diskfile.rmobjdir = _saved_rmobjdir
- def test_unlinkold_file(self):
+ def test_delete_file(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_file = os.path.join(the_path, "z")
os.makedirs(the_path)
@@ -675,15 +691,14 @@ class TestDiskFile(unittest.TestCase):
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
-
- later = float(gdf.metadata['X-Timestamp']) + 1
- gdf.unlinkold(normalize_timestamp(later))
+ with gdf.open():
+ later = float(gdf.get_metadata()['X-Timestamp']) + 1
+ assert gdf.data_file == the_file
+ gdf.delete(normalize_timestamp(later))
assert os.path.isdir(gdf.datadir)
assert not os.path.exists(os.path.join(gdf.datadir, gdf._obj))
- def test_unlinkold_file_not_found(self):
+ def test_delete_file_not_found(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_file = os.path.join(the_path, "z")
os.makedirs(the_path)
@@ -691,18 +706,19 @@ class TestDiskFile(unittest.TestCase):
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
+ with gdf.open():
+ later = float(gdf._metadata['X-Timestamp']) + 1
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
# Handle the case the file is not in the directory listing.
os.unlink(the_file)
- later = float(gdf.metadata['X-Timestamp']) + 1
- gdf.unlinkold(normalize_timestamp(later))
+ gdf.delete(normalize_timestamp(later))
assert os.path.isdir(gdf.datadir)
assert not os.path.exists(os.path.join(gdf.datadir, gdf._obj))
- def test_unlinkold_file_unlink_error(self):
+ def test_delete_file_unlink_error(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_file = os.path.join(the_path, "z")
os.makedirs(the_path)
@@ -710,10 +726,10 @@ class TestDiskFile(unittest.TestCase):
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
-
- later = float(gdf.metadata['X-Timestamp']) + 1
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ later = float(gdf._metadata['X-Timestamp']) + 1
def _mock_os_unlink_eacces_err(f):
raise OSError(errno.EACCES, os.strerror(errno.EACCES))
@@ -725,7 +741,7 @@ class TestDiskFile(unittest.TestCase):
# Handle the case os_unlink() raises an OSError
with patch("os.unlink", _mock_os_unlink_eacces_err):
try:
- gdf.unlinkold(normalize_timestamp(later))
+ gdf.delete(normalize_timestamp(later))
except OSError as e:
assert e.errno == errno.EACCES
else:
@@ -736,17 +752,17 @@ class TestDiskFile(unittest.TestCase):
assert os.path.isdir(gdf.datadir)
assert os.path.exists(os.path.join(gdf.datadir, gdf._obj))
- def test_unlinkold_is_dir(self):
+ def test_delete_is_dir(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_dir = os.path.join(the_path, "d")
os.makedirs(the_dir)
- gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d",
- keep_data_fp=True)
- assert gdf.data_file == the_dir
- assert gdf._is_dir
-
- later = float(gdf.metadata['X-Timestamp']) + 1
- gdf.unlinkold(normalize_timestamp(later))
+ gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d")
+ assert gdf._obj == "d"
+ with gdf.open():
+ assert gdf.data_file == the_dir
+ assert gdf._is_dir
+ later = float(gdf._metadata['X-Timestamp']) + 1
+ gdf.delete(normalize_timestamp(later))
assert os.path.isdir(gdf.datadir)
assert not os.path.exists(os.path.join(gdf.datadir, gdf._obj))
@@ -758,9 +774,10 @@ class TestDiskFile(unittest.TestCase):
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- assert 4 == gdf.get_data_file_size()
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ assert 4 == gdf.get_data_file_size()
def test_get_data_file_size_md_restored(self):
the_path = os.path.join(self.td, "vol0", "bar")
@@ -770,12 +787,13 @@ class TestDiskFile(unittest.TestCase):
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- assert 4 == gdf.metadata['Content-Length']
- gdf.metadata['Content-Length'] = 3
- assert 4 == gdf.get_data_file_size()
- assert 4 == gdf.metadata['Content-Length']
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ assert 4 == gdf._metadata['Content-Length']
+ gdf._metadata['Content-Length'] = 3
+ assert 4 == gdf.get_data_file_size()
+ assert 4 == gdf._metadata['Content-Length']
def test_get_data_file_size_dne(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar",
@@ -795,15 +813,16 @@ class TestDiskFile(unittest.TestCase):
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- gdf.data_file = gdf.data_file + ".dne"
- try:
- gdf.get_data_file_size()
- except DiskFileNotExist:
- pass
- else:
- self.fail("Expected DiskFileNotExist exception")
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ gdf.data_file = gdf.data_file + ".dne"
+ try:
+ gdf.get_data_file_size()
+ except DiskFileNotExist:
+ pass
+ else:
+ self.fail("Expected DiskFileNotExist exception")
def test_get_data_file_size_os_err(self):
the_path = os.path.join(self.td, "vol0", "bar")
@@ -813,55 +832,57 @@ class TestDiskFile(unittest.TestCase):
fd.write("1234")
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z"
- assert gdf.data_file == the_file
- assert not gdf._is_dir
- stats = os.stat(the_path)
- try:
- os.chmod(the_path, 0)
+ with gdf.open():
+ assert gdf.data_file == the_file
+ assert not gdf._is_dir
+ stats = os.stat(the_path)
+ try:
+ os.chmod(the_path, 0)
- def _mock_getsize_eaccess_err(f):
- raise OSError(errno.EACCES, os.strerror(errno.EACCES))
+ def _mock_getsize_eaccess_err(f):
+ raise OSError(errno.EACCES, os.strerror(errno.EACCES))
- with patch("os.path.getsize", _mock_getsize_eaccess_err):
- try:
- gdf.get_data_file_size()
- except OSError as err:
- assert err.errno == errno.EACCES
- else:
- self.fail("Expected OSError exception")
- finally:
- os.chmod(the_path, stats.st_mode)
+ with patch("os.path.getsize", _mock_getsize_eaccess_err):
+ try:
+ gdf.get_data_file_size()
+ except OSError as err:
+ assert err.errno == errno.EACCES
+ else:
+ self.fail("Expected OSError exception")
+ finally:
+ os.chmod(the_path, stats.st_mode)
def test_get_data_file_size_dir(self):
the_path = os.path.join(self.td, "vol0", "bar")
the_dir = os.path.join(the_path, "d")
os.makedirs(the_dir)
- gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d",
- keep_data_fp=True)
+ gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d")
assert gdf._obj == "d"
- assert gdf.data_file == the_dir
- assert gdf._is_dir
- assert 0 == gdf.get_data_file_size()
+ with gdf.open():
+ assert gdf.data_file == the_dir
+ assert gdf._is_dir
+ assert 0 == gdf.get_data_file_size()
def test_filter_metadata(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
- assert gdf.metadata == {}
+ assert gdf._metadata == None
gdf._filter_metadata()
- assert gdf.metadata == {}
+ assert gdf._metadata == None
- gdf.metadata[X_TYPE] = 'a'
- gdf.metadata[X_OBJECT_TYPE] = 'b'
- gdf.metadata['foobar'] = 'c'
+ gdf._metadata = {}
+ gdf._metadata[X_TYPE] = 'a'
+ gdf._metadata[X_OBJECT_TYPE] = 'b'
+ gdf._metadata['foobar'] = 'c'
gdf._filter_metadata()
- assert X_TYPE not in gdf.metadata
- assert X_OBJECT_TYPE not in gdf.metadata
- assert 'foobar' in gdf.metadata
+ assert X_TYPE not in gdf._metadata
+ assert X_OBJECT_TYPE not in gdf._metadata
+ assert 'foobar' in gdf._metadata
- def test_writer(self):
+ def test_create(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir/z")
saved_tmppath = ''
saved_fd = None
- with gdf.writer() as dw:
+ with gdf.create() as dw:
assert gdf.datadir == os.path.join(self.td, "vol0", "bar", "dir")
assert os.path.isdir(gdf.datadir)
saved_tmppath = dw.tmppath
@@ -881,10 +902,10 @@ class TestDiskFile(unittest.TestCase):
self.fail("Exception expected")
assert not os.path.exists(saved_tmppath)
- def test_writer_err_on_close(self):
+ def test_create_err_on_close(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir/z")
saved_tmppath = ''
- with gdf.writer() as dw:
+ with gdf.create() as dw:
assert gdf.datadir == os.path.join(self.td, "vol0", "bar", "dir")
assert os.path.isdir(gdf.datadir)
saved_tmppath = dw.tmppath
@@ -896,10 +917,10 @@ class TestDiskFile(unittest.TestCase):
os.close(dw.fd)
assert not os.path.exists(saved_tmppath)
- def test_writer_err_on_unlink(self):
+ def test_create_err_on_unlink(self):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir/z")
saved_tmppath = ''
- with gdf.writer() as dw:
+ with gdf.create() as dw:
assert gdf.datadir == os.path.join(self.td, "vol0", "bar", "dir")
assert os.path.isdir(gdf.datadir)
saved_tmppath = dw.tmppath
diff --git a/test/unit/proxy/controllers/test_account.py b/test/unit/proxy/controllers/test_account.py
index 4d67d65..394ada7 100644
--- a/test/unit/proxy/controllers/test_account.py
+++ b/test/unit/proxy/controllers/test_account.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2012 OpenStack, LLC.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,6 +40,28 @@ class TestAccountController(unittest.TestCase):
self.assertEqual(headers_to_account_info(resp.headers),
resp.environ['swift.account/AUTH_bob'])
+ def test_swift_owner(self):
+ owner_headers = {
+ 'x-account-meta-temp-url-key': 'value',
+ 'x-account-meta-temp-url-key-2': 'value'}
+ controller = proxy_server.AccountController(self.app, 'a')
+
+ req = Request.blank('/a')
+ with mock.patch('swift.proxy.controllers.base.http_connect',
+ fake_http_connect(200, 200, headers=owner_headers)):
+ resp = controller.HEAD(req)
+ self.assertEquals(2, resp.status_int // 100)
+ for key in owner_headers:
+ self.assertTrue(key not in resp.headers)
+
+ req = Request.blank('/a', environ={'swift_owner': True})
+ with mock.patch('swift.proxy.controllers.base.http_connect',
+ fake_http_connect(200, 200, headers=owner_headers)):
+ resp = controller.HEAD(req)
+ self.assertEquals(2, resp.status_int // 100)
+ for key in owner_headers:
+ self.assertTrue(key in resp.headers)
+
if __name__ == '__main__':
unittest.main()
diff --git a/test/unit/proxy/controllers/test_base.py b/test/unit/proxy/controllers/test_base.py
index 02692eb..8214b98 100644
--- a/test/unit/proxy/controllers/test_base.py
+++ b/test/unit/proxy/controllers/test_base.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2012 OpenStack, LLC.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,9 +16,9 @@
import unittest
from mock import patch
from swift.proxy.controllers.base import headers_to_container_info, \
- headers_to_account_info, get_container_info, get_container_memcache_key, \
- get_account_info, get_account_memcache_key, _get_cache_key, get_info, \
- Controller
+ headers_to_account_info, headers_to_object_info, get_container_info, \
+ get_container_memcache_key, get_account_info, get_account_memcache_key, \
+ get_object_env_key, _get_cache_key, get_info, get_object_info, Controller
from swift.common.swob import Request
from swift.common.utils import split_path
from test.unit import fake_http_connect, FakeRing, FakeMemcache
@@ -29,12 +29,18 @@ FakeResponse_status_int = 201
class FakeResponse(object):
- def __init__(self, headers, env, account, container):
+ def __init__(self, headers, env, account, container, obj):
self.headers = headers
self.status_int = FakeResponse_status_int
self.environ = env
- cache_key, env_key = _get_cache_key(account, container)
- if container:
+ if obj:
+ env_key = get_object_env_key(account, container, obj)
+ else:
+ cache_key, env_key = _get_cache_key(account, container)
+
+ if account and container and obj:
+ info = headers_to_object_info(headers, FakeResponse_status_int)
+ elif account and container:
info = headers_to_container_info(headers, FakeResponse_status_int)
else:
info = headers_to_account_info(headers, FakeResponse_status_int)
@@ -42,18 +48,27 @@ class FakeResponse(object):
class FakeRequest(object):
- def __init__(self, env, path):
+ def __init__(self, env, path, swift_source=None):
self.environ = env
(version, account, container, obj) = split_path(path, 2, 4, True)
self.account = account
self.container = container
- stype = container and 'container' or 'account'
- self.headers = {'x-%s-object-count' % (stype): 1000,
- 'x-%s-bytes-used' % (stype): 6666}
+ self.obj = obj
+ if obj:
+ stype = 'object'
+ self.headers = {'content-length': 5555,
+ 'content-type': 'text/plain'}
+ else:
+ stype = container and 'container' or 'account'
+ self.headers = {'x-%s-object-count' % (stype): 1000,
+ 'x-%s-bytes-used' % (stype): 6666}
+ if swift_source:
+ meta = 'x-%s-meta-fakerequest-swift-source' % stype
+ self.headers[meta] = swift_source
def get_response(self, app):
return FakeResponse(self.headers, self.environ, self.account,
- self.container)
+ self.container, self.obj)
class FakeCache(object):
@@ -73,6 +88,21 @@ class TestFuncs(unittest.TestCase):
def test_GETorHEAD_base(self):
base = Controller(self.app)
+ req = Request.blank('/a/c/o/with/slashes')
+ with patch('swift.proxy.controllers.base.'
+ 'http_connect', fake_http_connect(200)):
+ resp = base.GETorHEAD_base(req, 'object', FakeRing(), 'part',
+ '/a/c/o/with/slashes')
+ self.assertTrue('swift.object/a/c/o/with/slashes' in resp.environ)
+ self.assertEqual(
+ resp.environ['swift.object/a/c/o/with/slashes']['status'], 200)
+ req = Request.blank('/a/c/o')
+ with patch('swift.proxy.controllers.base.'
+ 'http_connect', fake_http_connect(200)):
+ resp = base.GETorHEAD_base(req, 'object', FakeRing(), 'part',
+ '/a/c/o')
+ self.assertTrue('swift.object/a/c/o' in resp.environ)
+ self.assertEqual(resp.environ['swift.object/a/c/o']['status'], 200)
req = Request.blank('/a/c')
with patch('swift.proxy.controllers.base.'
'http_connect', fake_http_connect(200)):
@@ -101,7 +131,7 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_a['bytes'], 6666)
self.assertEquals(info_a['total_object_count'], 1000)
# Make sure the env cache is set
- self.assertEquals(env, {'swift.account/a': info_a})
+ self.assertEquals(env.get('swift.account/a'), info_a)
# Do an env cached call to account
info_a = get_info(None, env, 'a')
@@ -110,7 +140,7 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_a['bytes'], 6666)
self.assertEquals(info_a['total_object_count'], 1000)
# Make sure the env cache is set
- self.assertEquals(env, {'swift.account/a': info_a})
+ self.assertEquals(env.get('swift.account/a'), info_a)
# This time do env cached call to account and non cached to container
with patch('swift.proxy.controllers.base.'
@@ -121,11 +151,12 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_c['bytes'], 6666)
self.assertEquals(info_c['object_count'], 1000)
# Make sure the env cache is set
- self.assertEquals(env['swift.account/a'], info_a)
- self.assertEquals(env['swift.container/a/c'], info_c)
+ self.assertEquals(env.get('swift.account/a'), info_a)
+ self.assertEquals(env.get('swift.container/a/c'), info_c)
- # This time do a non cached call to account than non cached to container
- env = {} # abandon previous call to env
+ # This time do a non cached call to account than non cached to
+ # container
+ env = {} # abandon previous call to env
with patch('swift.proxy.controllers.base.'
'_prepare_pre_auth_info_request', FakeRequest):
info_c = get_info(None, env, 'a', 'c')
@@ -134,10 +165,11 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_c['bytes'], 6666)
self.assertEquals(info_c['object_count'], 1000)
# Make sure the env cache is set
- self.assertEquals(env['swift.account/a'], info_a)
- self.assertEquals(env['swift.container/a/c'], info_c)
+ self.assertEquals(env.get('swift.account/a'), info_a)
+ self.assertEquals(env.get('swift.container/a/c'), info_c)
- # This time do an env cached call to container while account is not cached
+ # This time do an env cached call to container while account is not
+ # cached
del(env['swift.account/a'])
info_c = get_info(None, env, 'a', 'c')
# Check that you got proper info
@@ -145,7 +177,7 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_c['bytes'], 6666)
self.assertEquals(info_c['object_count'], 1000)
# Make sure the env cache is set and account still not cached
- self.assertEquals(env, {'swift.container/a/c': info_c})
+ self.assertEquals(env.get('swift.container/a/c'), info_c)
# Do a non cached call to account not found with ret_not_found
env = {}
@@ -161,7 +193,7 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_a['bytes'], 6666)
self.assertEquals(info_a['total_object_count'], 1000)
# Make sure the env cache is set
- self.assertEquals(env, {'swift.account/a': info_a})
+ self.assertEquals(env.get('swift.account/a'), info_a)
# Do a cached call to account not found with ret_not_found
info_a = get_info(None, env, 'a', ret_not_found=True)
@@ -170,7 +202,7 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_a['bytes'], 6666)
self.assertEquals(info_a['total_object_count'], 1000)
# Make sure the env cache is set
- self.assertEquals(env, {'swift.account/a': info_a})
+ self.assertEquals(env.get('swift.account/a'), info_a)
# Do a non cached call to account not found without ret_not_found
env = {}
@@ -191,6 +223,21 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(info_a, None)
self.assertEquals(env['swift.account/a']['status'], 404)
+ def test_get_container_info_swift_source(self):
+ req = Request.blank("/v1/a/c", environ={'swift.cache': FakeCache({})})
+ with patch('swift.proxy.controllers.base.'
+ '_prepare_pre_auth_info_request', FakeRequest):
+ resp = get_container_info(req.environ, 'app', swift_source='MC')
+ self.assertEquals(resp['meta']['fakerequest-swift-source'], 'MC')
+
+ def test_get_object_info_swift_source(self):
+ req = Request.blank("/v1/a/c/o",
+ environ={'swift.cache': FakeCache({})})
+ with patch('swift.proxy.controllers.base.'
+ '_prepare_pre_auth_info_request', FakeRequest):
+ resp = get_object_info(req.environ, 'app', swift_source='LU')
+ self.assertEquals(resp['meta']['fakerequest-swift-source'], 'LU')
+
def test_get_container_info_no_cache(self):
req = Request.blank("/v1/AUTH_account/cont",
environ={'swift.cache': FakeCache({})})
@@ -217,11 +264,18 @@ class TestFuncs(unittest.TestCase):
cache_key = get_container_memcache_key("account", "cont")
env_key = 'swift.%s' % cache_key
req = Request.blank("/v1/account/cont",
- environ={ env_key: {'bytes': 3867},
- 'swift.cache': FakeCache({})})
+ environ={env_key: {'bytes': 3867},
+ 'swift.cache': FakeCache({})})
resp = get_container_info(req.environ, 'xxx')
self.assertEquals(resp['bytes'], 3867)
+ def test_get_account_info_swift_source(self):
+ req = Request.blank("/v1/a", environ={'swift.cache': FakeCache({})})
+ with patch('swift.proxy.controllers.base.'
+ '_prepare_pre_auth_info_request', FakeRequest):
+ resp = get_account_info(req.environ, 'a', swift_source='MC')
+ self.assertEquals(resp['meta']['fakerequest-swift-source'], 'MC')
+
def test_get_account_info_no_cache(self):
req = Request.blank("/v1/AUTH_account",
environ={'swift.cache': FakeCache({})})
@@ -266,11 +320,33 @@ class TestFuncs(unittest.TestCase):
cache_key = get_account_memcache_key("account")
env_key = 'swift.%s' % cache_key
req = Request.blank("/v1/account",
- environ={ env_key: {'bytes': 3867},
- 'swift.cache': FakeCache({})})
+ environ={env_key: {'bytes': 3867},
+ 'swift.cache': FakeCache({})})
resp = get_account_info(req.environ, 'xxx')
self.assertEquals(resp['bytes'], 3867)
+ def test_get_object_info_env(self):
+ cached = {'status': 200,
+ 'length': 3333,
+ 'type': 'application/json',
+ 'meta': {}}
+ env_key = get_object_env_key("account", "cont", "obj")
+ req = Request.blank("/v1/account/cont/obj",
+ environ={env_key: cached,
+ 'swift.cache': FakeCache({})})
+ resp = get_object_info(req.environ, 'xxx')
+ self.assertEquals(resp['length'], 3333)
+ self.assertEquals(resp['type'], 'application/json')
+
+ def test_get_object_info_no_env(self):
+ req = Request.blank("/v1/account/cont/obj",
+ environ={'swift.cache': FakeCache({})})
+ with patch('swift.proxy.controllers.base.'
+ '_prepare_pre_auth_info_request', FakeRequest):
+ resp = get_object_info(req.environ, 'xxx')
+ self.assertEquals(resp['length'], 5555)
+ self.assertEquals(resp['type'], 'text/plain')
+
def test_headers_to_container_info_missing(self):
resp = headers_to_container_info({}, 404)
self.assertEquals(resp['status'], 404)
@@ -329,3 +405,31 @@ class TestFuncs(unittest.TestCase):
self.assertEquals(
resp,
headers_to_account_info(headers.items(), 200))
+
+ def test_headers_to_object_info_missing(self):
+ resp = headers_to_object_info({}, 404)
+ self.assertEquals(resp['status'], 404)
+ self.assertEquals(resp['length'], None)
+ self.assertEquals(resp['etag'], None)
+
+ def test_headers_to_object_info_meta(self):
+ headers = {'X-Object-Meta-Whatevs': 14,
+ 'x-object-meta-somethingelse': 0}
+ resp = headers_to_object_info(headers.items(), 200)
+ self.assertEquals(len(resp['meta']), 2)
+ self.assertEquals(resp['meta']['whatevs'], 14)
+ self.assertEquals(resp['meta']['somethingelse'], 0)
+
+ def test_headers_to_object_info_values(self):
+ headers = {
+ 'content-length': '1024',
+ 'content-type': 'application/json',
+ }
+ resp = headers_to_object_info(headers.items(), 200)
+ self.assertEquals(resp['length'], '1024')
+ self.assertEquals(resp['type'], 'application/json')
+
+ headers['x-unused-header'] = 'blahblahblah'
+ self.assertEquals(
+ resp,
+ headers_to_object_info(headers.items(), 200))
diff --git a/test/unit/proxy/controllers/test_container.py b/test/unit/proxy/controllers/test_container.py
index c2e9483..63e6b0e 100644
--- a/test/unit/proxy/controllers/test_container.py
+++ b/test/unit/proxy/controllers/test_container.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2010-2012 OpenStack, LLC.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,6 +40,28 @@ class TestContainerController(unittest.TestCase):
self.assertEqual(headers_to_container_info(resp.headers),
resp.environ['swift.container/a/c'])
+ def test_swift_owner(self):
+ owner_headers = {
+ 'x-container-read': 'value', 'x-container-write': 'value',
+ 'x-container-sync-key': 'value', 'x-container-sync-to': 'value'}
+ controller = proxy_server.ContainerController(self.app, 'a', 'c')
+
+ req = Request.blank('/a/c')
+ with mock.patch('swift.proxy.controllers.base.http_connect',
+ fake_http_connect(200, 200, headers=owner_headers)):
+ resp = controller.HEAD(req)
+ self.assertEquals(2, resp.status_int // 100)
+ for key in owner_headers:
+ self.assertTrue(key not in resp.headers)
+
+ req = Request.blank('/a/c', environ={'swift_owner': True})
+ with mock.patch('swift.proxy.controllers.base.http_connect',
+ fake_http_connect(200, 200, headers=owner_headers)):
+ resp = controller.HEAD(req)
+ self.assertEquals(2, resp.status_int // 100)
+ for key in owner_headers:
+ self.assertTrue(key in resp.headers)
+
if __name__ == '__main__':
unittest.main()
diff --git a/test/unit/proxy/controllers/test_obj.py b/test/unit/proxy/controllers/test_obj.py
index e4af789..cae62b0 100755
--- a/test/unit/proxy/controllers/test_obj.py
+++ b/test/unit/proxy/controllers/test_obj.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2010-2012 OpenStack, LLC.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,9 +15,28 @@
# limitations under the License.
import unittest
+from contextlib import contextmanager
+import mock
+
+import swift
from swift.proxy import server as proxy_server
-from test.unit import FakeRing, FakeMemcache
+from test.unit import FakeRing, FakeMemcache, fake_http_connect
+
+
+@contextmanager
+def set_http_connect(*args, **kwargs):
+ old_connect = swift.proxy.controllers.base.http_connect
+ new_connect = fake_http_connect(*args, **kwargs)
+ swift.proxy.controllers.base.http_connect = new_connect
+ swift.proxy.controllers.obj.http_connect = new_connect
+ swift.proxy.controllers.account.http_connect = new_connect
+ swift.proxy.controllers.container.http_connect = new_connect
+ yield new_connect
+ swift.proxy.controllers.base.http_connect = old_connect
+ swift.proxy.controllers.obj.http_connect = old_connect
+ swift.proxy.controllers.account.http_connect = old_connect
+ swift.proxy.controllers.container.http_connect = old_connect
class TestObjControllerWriteAffinity(unittest.TestCase):
@@ -44,7 +63,8 @@ class TestObjControllerWriteAffinity(unittest.TestCase):
def test_iter_nodes_local_first_moves_locals_first(self):
controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o')
- self.app.write_affinity_is_local_fn = (lambda node: node['region'] == 1)
+ self.app.write_affinity_is_local_fn = (
+ lambda node: node['region'] == 1)
self.app.write_affinity_node_count = lambda ring: 4
all_nodes = self.app.object_ring.get_part_nodes(1)
@@ -59,6 +79,44 @@ class TestObjControllerWriteAffinity(unittest.TestCase):
# we don't skip any nodes
self.assertEqual(sorted(all_nodes), sorted(local_first_nodes))
+ def test_connect_put_node_timeout(self):
+ controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o')
+ self.app.conn_timeout = 0.1
+ with set_http_connect(200, slow_connect=True):
+ nodes = [dict(ip='', port='', device='')]
+ res = controller._connect_put_node(nodes, '', '', {}, ('', ''))
+ self.assertTrue(res is None)
+
+
+class TestObjController(unittest.TestCase):
+
+ def test_PUT_log_info(self):
+ # mock out enough to get to the area of the code we want to test
+ with mock.patch('swift.proxy.controllers.obj.check_object_creation',
+ mock.MagicMock(return_value=None)):
+ app = mock.MagicMock()
+ app.container_ring.get_nodes.return_value = (1, [2])
+ app.object_ring.get_nodes.return_value = (1, [2])
+ controller = proxy_server.ObjectController(app, 'a', 'c', 'o')
+ controller.container_info = mock.MagicMock(return_value={
+ 'partition': 1,
+ 'nodes': [{}],
+ 'write_acl': None,
+ 'sync_key': None,
+ 'versions': None})
+ # and now test that we add the header to log_info
+ req = swift.common.swob.Request.blank('/v1/a/c/o')
+ req.headers['x-copy-from'] = 'somewhere'
+ controller.PUT(req)
+ self.assertEquals(
+ req.environ.get('swift.log_info'), ['x-copy-from:somewhere'])
+ # and then check that we don't do that for originating POSTs
+ req = swift.common.swob.Request.blank('/v1/a/c/o')
+ req.method = 'POST'
+ req.headers['x-copy-from'] = 'elsewhere'
+ controller.PUT(req)
+ self.assertEquals(req.environ.get('swift.log_info'), None)
+
if __name__ == '__main__':
unittest.main()
diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py
index 488f253..490e8fc 100644
--- a/test/unit/proxy/test_server.py
+++ b/test/unit/proxy/test_server.py
@@ -1,19 +1,4 @@
-# Copyright (c) 2010-2013 OpenStack, LLC.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Copyright (c) 2013 Red Hat, Inc.
+# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -34,16 +19,17 @@ import logging
import os
import sys
import unittest
-from nose import SkipTest
import urlparse
-import signal
+from nose import SkipTest
from contextlib import contextmanager, nested, closing
from gzip import GzipFile
from shutil import rmtree
+import gc
import time
from urllib import quote
from hashlib import md5
from tempfile import mkdtemp
+import weakref
import mock
from eventlet import sleep, spawn, wsgi, listen
@@ -53,18 +39,18 @@ import gluster.swift.common.Glusterfs as gfs
gfs.RUN_DIR = mkdtemp()
from test.unit import connect_tcp, readuntil2crlfs, FakeLogger, \
- fake_http_connect, FakeRing, FakeMemcache
-from gluster.swift.proxy.server import server as proxy_server
-from gluster.swift.obj import server as object_server
+ fake_http_connect, FakeRing, FakeMemcache, DebugLogger
+from gluster.swift.proxy import server as proxy_server
from gluster.swift.account import server as account_server
from gluster.swift.container import server as container_server
+from gluster.swift.obj import server as object_server
from swift.common import ring
from swift.common.exceptions import ChunkReadTimeout, SegmentError
from swift.common.constraints import MAX_META_NAME_LENGTH, \
MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, \
MAX_FILE_SIZE, MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH
from swift.common import utils
-from swift.common.utils import mkdirs, normalize_timestamp, NullLogger
+from swift.common.utils import mkdirs, normalize_timestamp
from swift.common.wsgi import monkey_patch_mimetools
from swift.proxy.controllers.obj import SegmentedIterable
from swift.proxy.controllers.base import get_container_memcache_key, \
@@ -78,22 +64,15 @@ logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
STATIC_TIME = time.time()
-_request_instances = 0
+_request_instances = weakref.WeakKeyDictionary()
_test_coros = _test_servers = _test_sockets = _orig_container_listing_limit = \
_testdir = None
def request_init(self, *args, **kwargs):
- global _request_instances
self._orig_init(*args, **kwargs)
- _request_instances += 1
-
-def request_del(self):
- global _request_instances
- if self._orig_del:
- self._orig_del()
- _request_instances -= 1
+ _request_instances[self] = None
def setup():
@@ -102,8 +81,6 @@ def setup():
_orig_container_listing_limit, _test_coros
Request._orig_init = Request.__init__
Request.__init__ = request_init
- Request._orig_del = getattr(Request, '__del__', None)
- Request.__del__ = request_del
monkey_patch_mimetools()
# Since we're starting up a lot here, we're going to test more than
# just chunked puts; we're also going to test parts of
@@ -132,8 +109,8 @@ def setup():
obj2lis = listen(('localhost', 0))
_test_sockets = \
(prolis, acc1lis, acc2lis, con1lis, con2lis, obj1lis, obj2lis)
- with closing(GzipFile(os.path.join(_testdir, 'account.ring.gz'), 'wb')) \
- as f:
+ account_ring_path = os.path.join(_testdir, 'account.ring.gz')
+ with closing(GzipFile(account_ring_path, 'wb')) as f:
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
'port': acc1lis.getsockname()[1]},
@@ -143,8 +120,8 @@ def setup():
{'id': 1, 'zone': 1, 'device': 'a', 'ip': '127.0.0.1',
'port': acc2lis.getsockname()[1]}], 30),
f)
- with closing(GzipFile(os.path.join(_testdir, 'container.ring.gz'), 'wb')) \
- as f:
+ container_ring_path = os.path.join(_testdir, 'container.ring.gz')
+ with closing(GzipFile(container_ring_path, 'wb')) as f:
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
'port': con1lis.getsockname()[1]},
@@ -154,8 +131,8 @@ def setup():
{'id': 1, 'zone': 1, 'device': 'a', 'ip': '127.0.0.1',
'port': con2lis.getsockname()[1]}], 30),
f)
- with closing(GzipFile(os.path.join(_testdir, 'object.ring.gz'), 'wb')) \
- as f:
+ object_ring_path = os.path.join(_testdir, 'object.ring.gz')
+ with closing(GzipFile(object_ring_path, 'wb')) as f:
pickle.dump(ring.RingData([[0, 1, 0, 1], [1, 0, 1, 0]],
[{'id': 0, 'zone': 0, 'device': 'sda1', 'ip': '127.0.0.1',
'port': obj1lis.getsockname()[1]},
@@ -174,9 +151,6 @@ def setup():
obj2srv = object_server.ObjectController(conf)
_test_servers = \
(prosrv, acc1srv, acc2srv, con1srv, con2srv, obj1srv, obj2srv)
- # Use DebugLogger() when trying to figure out what failed in the spawned
- # servers.
- from test.unit import DebugLogger
nl = DebugLogger()
prospa = spawn(wsgi.server, prolis, prosrv, nl)
acc1spa = spawn(wsgi.server, acc1lis, acc1srv, nl)
@@ -212,7 +186,8 @@ def setup():
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
- assert headers[:len(exp)] == exp, "Expected '%s', encountered '%s'" % (exp, headers[:len(exp)])
+ assert headers[:len(exp)] == exp, "Expected '%s', encountered '%s'" % (
+ exp, headers[:len(exp)])
def teardown():
@@ -222,8 +197,6 @@ def teardown():
_orig_container_listing_limit
rmtree(os.path.dirname(_testdir))
Request.__init__ = Request._orig_init
- if Request._orig_del:
- Request.__del__ = Request._orig_del
def sortHeaderNames(headerNames):
@@ -391,7 +364,7 @@ class TestController(unittest.TestCase):
# 'container_count' changed from 0 to None
cache_key = get_account_memcache_key(self.account)
account_info = {'status': 404,
- 'container_count': None, # internally keep None
+ 'container_count': None, # internally keep None
'total_object_count': None,
'bytes': None,
'meta': {}}
@@ -459,8 +432,8 @@ class TestController(unittest.TestCase):
with save_globals():
headers = {'x-container-read': self.read_acl,
'x-container-write': self.write_acl}
- set_http_connect(200, # account_info is found
- 200, headers=headers) # container_info is found
+ set_http_connect(200, # account_info is found
+ 200, headers=headers) # container_info is found
ret = self.controller.container_info(
self.account, self.container, self.request)
self.check_container_info_return(ret)
@@ -482,8 +455,8 @@ class TestController(unittest.TestCase):
return True, True, 0
with save_globals():
- set_http_connect(503, 204, # account_info found
- 504, 404, 404) # container_info 'NotFound'
+ set_http_connect(503, 204, # account_info found
+ 504, 404, 404) # container_info 'NotFound'
ret = self.controller.container_info(
self.account, self.container, self.request)
self.check_container_info_return(ret, True)
@@ -499,7 +472,7 @@ class TestController(unittest.TestCase):
self.account, self.container, self.request)
self.check_container_info_return(ret, True)
- set_http_connect(503, 404, 404)# account_info 'NotFound'
+ set_http_connect(503, 404, 404) # account_info 'NotFound'
ret = self.controller.container_info(
self.account, self.container, self.request)
self.check_container_info_return(ret, True)
@@ -720,41 +693,31 @@ class TestObjectController(unittest.TestCase):
self.assertEquals(res.status_int, expected)
def test_GET_newest_large_file(self):
- calls = [0]
-
- def handler(_junk1, _junk2):
- calls[0] += 1
-
- old_handler = signal.signal(signal.SIGPIPE, handler)
- try:
- prolis = _test_sockets[0]
- prosrv = _test_servers[0]
- sock = connect_tcp(('localhost', prolis.getsockname()[1]))
- fd = sock.makefile()
- obj = 'a' * (1024 * 1024)
- path = '/v1/a/c/o.large'
- fd.write('PUT %s HTTP/1.1\r\n'
- 'Host: localhost\r\n'
- 'Connection: close\r\n'
- 'X-Storage-Token: t\r\n'
- 'Content-Length: %s\r\n'
- 'Content-Type: application/octet-stream\r\n'
- '\r\n%s' % (path, str(len(obj)), obj))
- fd.flush()
- headers = readuntil2crlfs(fd)
- exp = 'HTTP/1.1 201'
- self.assertEqual(headers[:len(exp)], exp)
- req = Request.blank(path,
- environ={'REQUEST_METHOD': 'GET'},
- headers={'Content-Type':
- 'application/octet-stream',
- 'X-Newest': 'true'})
- res = req.get_response(prosrv)
- self.assertEqual(res.status_int, 200)
- self.assertEqual(res.body, obj)
- self.assertEqual(calls[0], 0)
- finally:
- signal.signal(signal.SIGPIPE, old_handler)
+ prolis = _test_sockets[0]
+ prosrv = _test_servers[0]
+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
+ fd = sock.makefile()
+ obj = 'a' * (1024 * 1024)
+ path = '/v1/a/c/o.large'
+ fd.write('PUT %s HTTP/1.1\r\n'
+ 'Host: localhost\r\n'
+ 'Connection: close\r\n'
+ 'X-Storage-Token: t\r\n'
+ 'Content-Length: %s\r\n'
+ 'Content-Type: application/octet-stream\r\n'
+ '\r\n%s' % (path, str(len(obj)), obj))
+ fd.flush()
+ headers = readuntil2crlfs(fd)
+ exp = 'HTTP/1.1 201'
+ self.assertEqual(headers[:len(exp)], exp)
+ req = Request.blank(path,
+ environ={'REQUEST_METHOD': 'GET'},
+ headers={'Content-Type':
+ 'application/octet-stream',
+ 'X-Newest': 'true'})
+ res = req.get_response(prosrv)
+ self.assertEqual(res.status_int, 200)
+ self.assertEqual(res.body, obj)
def test_PUT_expect_header_zero_content_length(self):
test_errors = []
@@ -860,8 +823,8 @@ class TestObjectController(unittest.TestCase):
proxy_server.ObjectController(self.app, 'a', 'c', 'o.jpg')
controller.error_limit(
self.app.object_ring.get_part_nodes(1)[0], 'test')
- set_http_connect(200, 200, # account, container
- 201, 201, 201, # 3 working backends
+ set_http_connect(200, 200, # account, container
+ 201, 201, 201, # 3 working backends
give_connect=test_connect)
req = Request.blank('/a/c/o.jpg', {})
req.content_length = 1
@@ -874,7 +837,7 @@ class TestObjectController(unittest.TestCase):
# this is kind of a hokey test, but in FakeRing, the port is even when
# the region is 0, and odd when the region is 1, so this test asserts
# that we wrote to 2 nodes in region 0, then went to 1 non-r0 node.
- self.assertEqual(0, written_to[0][1] % 2) # it's (ip, port, device)
+ self.assertEqual(0, written_to[0][1] % 2) # it's (ip, port, device)
self.assertEqual(0, written_to[1][1] % 2)
self.assertNotEqual(0, written_to[2][1] % 2)
@@ -1085,7 +1048,7 @@ class TestObjectController(unittest.TestCase):
response_bodies = (
'', # HEAD /a
'', # HEAD /a/c
- '', # GET manifest
+ simplejson.dumps([]), # GET manifest
simplejson.dumps([])) # GET empty listing
with save_globals():
@@ -1279,8 +1242,8 @@ class TestObjectController(unittest.TestCase):
"content_type": "application/octet-stream"}]
json_listing = simplejson.dumps(listing)
response_bodies = (
- '', # HEAD /a
- '', # HEAD /a/c
+ '', # HEAD /a
+ '', # HEAD /a/c
json_listing) # GET manifest
with save_globals():
controller = proxy_server.ObjectController(
@@ -1432,7 +1395,7 @@ class TestObjectController(unittest.TestCase):
{"hash": "8681fb3ada2715c8754706ee5f23d4f8",
"last_modified": "2012-11-08T04:05:37.846710",
"bytes": 4,
- "name": "/d2/sub_manifest",
+ "name": u"/d2/sub_manifest \u2661", "sub_slo": True,
"content_type": "application/octet-stream"},
{"hash": "419af6d362a14b7a789ba1c7e772bbae",
"last_modified": "2012-11-08T04:05:37.866820",
@@ -1455,8 +1418,8 @@ class TestObjectController(unittest.TestCase):
'', # HEAD /a
'', # HEAD /a/c
simplejson.dumps(listing), # GET manifest
- 'Aa', # GET seg01
simplejson.dumps(sub_listing), # GET sub_manifest
+ 'Aa', # GET seg01
'Bb', # GET seg02
'Cc', # GET seg03
'Dd') # GET seg04
@@ -1478,12 +1441,12 @@ class TestObjectController(unittest.TestCase):
200, # HEAD /a
200, # HEAD /a/c
200, # GET listing1
- 200, # GET seg01
200, # GET sub listing1
+ 200, # GET seg01
200, # GET seg02
200, # GET seg03
200, # GET seg04
- headers=[{}, {}, slob_headers, {}, slob_headers, {}, {}, {}],
+ headers=[{}, {}, slob_headers, slob_headers, {}, {}, {}, {}],
body_iter=response_bodies,
give_connect=capture_requested_paths)
req = Request.blank('/a/c/manifest')
@@ -1496,7 +1459,8 @@ class TestObjectController(unittest.TestCase):
requested,
[['HEAD', '/a', {}],
['HEAD', '/a/c', {}],
- ['GET', '/a/c/manifest', {}]])
+ ['GET', '/a/c/manifest', {}],
+ ['GET', '/a/d2/sub_manifest \xe2\x99\xa1', {}]])
# iterating over body will retrieve manifest and sub manifest's
# objects
self.assertEqual(resp.body, 'AaBbCcDd')
@@ -1505,12 +1469,116 @@ class TestObjectController(unittest.TestCase):
[['HEAD', '/a', {}],
['HEAD', '/a/c', {}],
['GET', '/a/c/manifest', {}],
+ ['GET', '/a/d2/sub_manifest \xe2\x99\xa1', {}],
['GET', '/a/d1/seg01', {}],
- ['GET', '/a/d2/sub_manifest', {}],
['GET', '/a/d1/seg02', {}],
['GET', '/a/d2/seg03', {}],
['GET', '/a/d1/seg04', {}]])
+ def test_GET_nested_manifest_slo_with_range(self):
+ """
+ Original whole slo is Aa1234Bb where 1234 is a sub-manifests. I'm
+ pulling out 34Bb
+ """
+ listing = [{"hash": "98568d540134639be4655198a36614a4", # Aa
+ "last_modified": "2012-11-08T04:05:37.866820",
+ "bytes": 2,
+ "name": "/d1/seg01",
+ "content_type": "application/octet-stream"},
+ {"hash": "7b4b0ffa275d404bdc2fc6384916714f", # SubManifest1
+ "last_modified": "2012-11-08T04:05:37.866820",
+ "bytes": 4, "sub_slo": True,
+ "name": "/d2/subManifest01",
+ "content_type": "application/octet-stream"},
+ {"hash": "d526f1c8ef6c1e4e980e2b8471352d23", # Bb
+ "last_modified": "2012-11-08T04:05:37.866820",
+ "bytes": 2,
+ "name": "/d1/seg02",
+ "content_type": "application/octet-stream"}]
+
+ sublisting = [{"hash": "c20ad4d76fe97759aa27a0c99bff6710", # 12
+ "last_modified": "2012-11-08T04:05:37.866820",
+ "bytes": 2,
+ "name": "/d2/subSeg01",
+ "content_type": "application/octet-stream"},
+ {"hash": "e369853df766fa44e1ed0ff613f563bd", # 34
+ "last_modified": "2012-11-08T04:05:37.866820",
+ "bytes": 2,
+ "name": "/d2/subSeg02",
+ "content_type": "application/octet-stream"}]
+
+ response_bodies = (
+ '', # HEAD /a
+ '', # HEAD /a/c
+ simplejson.dumps(listing)[1:1], # GET incomplete manifest
+ simplejson.dumps(listing), # GET complete manifest
+ simplejson.dumps(sublisting), # GET complete submanifest
+ '34', # GET subseg02
+ 'Bb') # GET seg02
+ etag_iter = ['', '', '', '', '',
+ 'e369853df766fa44e1ed0ff613f563bd', # subSeg02
+ 'd526f1c8ef6c1e4e980e2b8471352d23'] # seg02
+ headers = [{}, {},
+ {'X-Static-Large-Object': 'True',
+ 'content-type': 'text/html; swift_bytes=4'},
+ {'X-Static-Large-Object': 'True',
+ 'content-type': 'text/html; swift_bytes=4'},
+ {'X-Static-Large-Object': 'True',
+ 'content-type': 'text/html; swift_bytes=4'},
+ {}, {}]
+ self.assertTrue(len(response_bodies) == len(etag_iter) == len(headers))
+ with save_globals():
+ controller = proxy_server.ObjectController(
+ self.app, 'a', 'c', 'manifest')
+
+ requested = []
+
+ def capture_requested_paths(ipaddr, port, device, partition,
+ method, path, headers=None,
+ query_string=None):
+ qs_dict = dict(urlparse.parse_qsl(query_string or ''))
+ requested.append([method, path, qs_dict])
+
+ set_http_connect(
+ 200, # HEAD /a
+ 200, # HEAD /a/c
+ 206, # GET incomplete listing
+ 200, # GET complete listing
+ 200, # GET complete sublisting
+ 200, # GET subSeg02
+ 200, # GET seg02
+ headers=headers,
+ etags=etag_iter,
+ body_iter=response_bodies,
+ give_connect=capture_requested_paths)
+
+ req = Request.blank('/a/c/manifest')
+ req.range = 'bytes=4-7'
+ resp = controller.GET(req)
+ got_called = [False, ]
+
+ def fake_start_response(*args, **kwargs):
+ got_called[0] = True
+ self.assertTrue(args[0].startswith('206'))
+
+ app_iter = resp(req.environ, fake_start_response)
+ resp_body = ''.join(app_iter) # read in entire resp
+ self.assertEqual(resp.status_int, 206)
+ self.assertEqual(resp_body, '34Bb')
+ self.assertTrue(got_called[0])
+ self.assertEqual(resp.content_length, 4)
+ self.assertEqual(resp.content_type, 'text/html')
+
+ self.assertEqual(
+ requested,
+ [['HEAD', '/a', {}],
+ ['HEAD', '/a/c', {}],
+ ['GET', '/a/c/manifest', {}], # for incomplete manifest
+ ['GET', '/a/c/manifest', {}],
+ ['GET', '/a/d2/subManifest01', {}],
+ ['GET', '/a/d2/subSeg02', {}],
+ ['GET', '/a/d1/seg02', {}]])
+
def test_GET_bad_404_manifest_slo(self):
listing = [{"hash": "98568d540134639be4655198a36614a4",
"last_modified": "2012-11-08T04:05:37.866820",
@@ -1777,16 +1845,14 @@ class TestObjectController(unittest.TestCase):
def test_POST(self):
with save_globals():
self.app.object_post_as_copy = False
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
def test_status_map(statuses, expected):
set_http_connect(*statuses)
self.app.memcache.store = {}
- req = Request.blank('/a/c/o', {},
+ req = Request.blank('/v1/a/c/o', {}, method='POST',
headers={'Content-Type': 'foo/bar'})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
expected = str(expected)
self.assertEquals(res.status[:len(expected)], expected)
test_status_map((200, 200, 202, 202, 202), 202)
@@ -1799,16 +1865,13 @@ class TestObjectController(unittest.TestCase):
def test_POST_as_copy(self):
with save_globals():
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
-
def test_status_map(statuses, expected):
set_http_connect(*statuses)
self.app.memcache.store = {}
- req = Request.blank('/a/c/o', {},
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
headers={'Content-Type': 'foo/bar'})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
expected = str(expected)
self.assertEquals(res.status[:len(expected)], expected)
test_status_map((200, 200, 200, 200, 200, 202, 202, 202), 202)
@@ -1821,15 +1884,12 @@ class TestObjectController(unittest.TestCase):
def test_DELETE(self):
with save_globals():
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
-
def test_status_map(statuses, expected):
set_http_connect(*statuses)
self.app.memcache.store = {}
- req = Request.blank('/a/c/o', {})
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'DELETE'})
self.app.update_request(req)
- res = controller.DELETE(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status[:len(str(expected))],
str(expected))
test_status_map((200, 200, 204, 204, 204), 204)
@@ -1841,15 +1901,12 @@ class TestObjectController(unittest.TestCase):
def test_HEAD(self):
with save_globals():
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
-
def test_status_map(statuses, expected):
set_http_connect(*statuses)
self.app.memcache.store = {}
- req = Request.blank('/a/c/o', {})
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'HEAD'})
self.app.update_request(req)
- res = controller.HEAD(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status[:len(str(expected))],
str(expected))
if expected < 400:
@@ -1867,16 +1924,14 @@ class TestObjectController(unittest.TestCase):
def test_HEAD_newest(self):
with save_globals():
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
-
def test_status_map(statuses, expected, timestamps,
expected_timestamp):
set_http_connect(*statuses, timestamps=timestamps)
self.app.memcache.store = {}
- req = Request.blank('/a/c/o', {}, headers={'x-newest': 'true'})
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'HEAD'},
+ headers={'x-newest': 'true'})
self.app.update_request(req)
- res = controller.HEAD(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status[:len(str(expected))],
str(expected))
self.assertEquals(res.headers.get('last-modified'),
@@ -1898,16 +1953,14 @@ class TestObjectController(unittest.TestCase):
def test_GET_newest(self):
with save_globals():
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
-
def test_status_map(statuses, expected, timestamps,
expected_timestamp):
set_http_connect(*statuses, timestamps=timestamps)
self.app.memcache.store = {}
- req = Request.blank('/a/c/o', {}, headers={'x-newest': 'true'})
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'GET'},
+ headers={'x-newest': 'true'})
self.app.update_request(req)
- res = controller.GET(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status[:len(str(expected))],
str(expected))
self.assertEquals(res.headers.get('last-modified'),
@@ -1927,16 +1980,13 @@ class TestObjectController(unittest.TestCase):
None, '1'), '1')
with save_globals():
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
-
def test_status_map(statuses, expected, timestamps,
expected_timestamp):
set_http_connect(*statuses, timestamps=timestamps)
self.app.memcache.store = {}
- req = Request.blank('/a/c/o', {})
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'HEAD'})
self.app.update_request(req)
- res = controller.HEAD(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status[:len(str(expected))],
str(expected))
self.assertEquals(res.headers.get('last-modified'),
@@ -1957,123 +2007,118 @@ class TestObjectController(unittest.TestCase):
with save_globals():
limit = MAX_META_VALUE_LENGTH
self.app.object_post_as_copy = False
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
+ proxy_server.ObjectController(self.app, 'account',
+ 'container', 'object')
set_http_connect(200, 200, 202, 202, 202)
# acct cont obj obj obj
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- 'X-Object-Meta-Foo': 'x' * limit})
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ 'X-Object-Meta-Foo': 'x' * limit})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 202)
set_http_connect(202, 202, 202)
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- 'X-Object-Meta-Foo': 'x' * (limit + 1)})
+ req = Request.blank(
+ '/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ 'X-Object-Meta-Foo': 'x' * (limit + 1)})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 400)
def test_POST_as_copy_meta_val_len(self):
with save_globals():
limit = MAX_META_VALUE_LENGTH
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 200, 200, 200, 202, 202, 202)
# acct cont objc objc objc obj obj obj
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- 'X-Object-Meta-Foo': 'x' * limit})
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ 'X-Object-Meta-Foo': 'x' * limit})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 202)
set_http_connect(202, 202, 202)
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- 'X-Object-Meta-Foo': 'x' * (limit + 1)})
+ req = Request.blank(
+ '/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ 'X-Object-Meta-Foo': 'x' * (limit + 1)})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 400)
def test_POST_meta_key_len(self):
with save_globals():
limit = MAX_META_NAME_LENGTH
self.app.object_post_as_copy = False
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 202, 202, 202)
# acct cont obj obj obj
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- ('X-Object-Meta-' + 'x' * limit): 'x'})
+ req = Request.blank(
+ '/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ ('X-Object-Meta-' + 'x' * limit): 'x'})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 202)
set_http_connect(202, 202, 202)
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- ('X-Object-Meta-' + 'x' * (limit + 1)): 'x'})
+ req = Request.blank(
+ '/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ ('X-Object-Meta-' + 'x' * (limit + 1)): 'x'})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 400)
def test_POST_as_copy_meta_key_len(self):
with save_globals():
limit = MAX_META_NAME_LENGTH
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 200, 200, 200, 202, 202, 202)
# acct cont objc objc objc obj obj obj
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- ('X-Object-Meta-' + 'x' * limit): 'x'})
+ req = Request.blank(
+ '/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ ('X-Object-Meta-' + 'x' * limit): 'x'})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 202)
set_http_connect(202, 202, 202)
- req = Request.blank('/a/c/o', {}, headers={
- 'Content-Type': 'foo/bar',
- ('X-Object-Meta-' + 'x' * (limit + 1)): 'x'})
+ req = Request.blank(
+ '/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers={'Content-Type': 'foo/bar',
+ ('X-Object-Meta-' + 'x' * (limit + 1)): 'x'})
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 400)
def test_POST_meta_count(self):
with save_globals():
limit = MAX_META_COUNT
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
headers = dict(
(('X-Object-Meta-' + str(i), 'a') for i in xrange(limit + 1)))
headers.update({'Content-Type': 'foo/bar'})
set_http_connect(202, 202, 202)
- req = Request.blank('/a/c/o', {}, headers=headers)
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers=headers)
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 400)
def test_POST_meta_size(self):
with save_globals():
limit = MAX_META_OVERALL_SIZE
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
count = limit / 256 # enough to cause the limit to be reached
headers = dict(
(('X-Object-Meta-' + str(i), 'a' * 256)
for i in xrange(count + 1)))
headers.update({'Content-Type': 'foo/bar'})
set_http_connect(202, 202, 202)
- req = Request.blank('/a/c/o', {}, headers=headers)
+ req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'POST'},
+ headers=headers)
self.app.update_request(req)
- res = controller.POST(req)
+ res = req.get_response(self.app)
self.assertEquals(res.status_int, 400)
def test_PUT_not_autodetect_content_type(self):
with save_globals():
- controller = proxy_server.ObjectController(
- self.app, 'a', 'c', 'o.html')
-
headers = {'Content-Type': 'something/right', 'Content-Length': 0}
it_worked = []
@@ -2086,17 +2131,15 @@ class TestObjectController(unittest.TestCase):
set_http_connect(204, 204, 201, 201, 201,
give_connect=verify_content_type)
- req = Request.blank('/a/c/o.html', {}, headers=headers)
+ req = Request.blank('/v1/a/c/o.html', {'REQUEST_METHOD': 'PUT'},
+ headers=headers)
self.app.update_request(req)
- res = controller.PUT(req)
+ req.get_response(self.app)
self.assertNotEquals(it_worked, [])
self.assertTrue(all(it_worked))
def test_PUT_autodetect_content_type(self):
with save_globals():
- controller = proxy_server.ObjectController(
- self.app, 'a', 'c', 'o.html')
-
headers = {'Content-Type': 'something/wrong', 'Content-Length': 0,
'X-Detect-Content-Type': 'True'}
it_worked = []
@@ -2110,9 +2153,10 @@ class TestObjectController(unittest.TestCase):
set_http_connect(204, 204, 201, 201, 201,
give_connect=verify_content_type)
- req = Request.blank('/a/c/o.html', {}, headers=headers)
+ req = Request.blank('/v1/a/c/o.html', {'REQUEST_METHOD': 'PUT'},
+ headers=headers)
self.app.update_request(req)
- res = controller.PUT(req)
+ req.get_response(self.app)
self.assertNotEquals(it_worked, [])
self.assertTrue(all(it_worked))
@@ -2143,20 +2187,18 @@ class TestObjectController(unittest.TestCase):
return ' '
return ''
- req = Request.blank('/a/c/o',
+ req = Request.blank('/v1/a/c/o',
environ={'REQUEST_METHOD': 'PUT',
'wsgi.input': SlowBody()},
headers={'Content-Length': '4',
'Content-Type': 'text/plain'})
self.app.update_request(req)
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 201, 201, 201)
# acct cont obj obj obj
- resp = controller.PUT(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 201)
self.app.client_timeout = 0.1
- req = Request.blank('/a/c/o',
+ req = Request.blank('/v1/a/c/o',
environ={'REQUEST_METHOD': 'PUT',
'wsgi.input': SlowBody()},
headers={'Content-Length': '4',
@@ -2164,7 +2206,7 @@ class TestObjectController(unittest.TestCase):
self.app.update_request(req)
set_http_connect(201, 201, 201)
# obj obj obj
- resp = controller.PUT(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 408)
def test_client_disconnect(self):
@@ -2190,17 +2232,15 @@ class TestObjectController(unittest.TestCase):
def read(self, size=-1):
raise Exception('Disconnected')
- req = Request.blank('/a/c/o',
+ req = Request.blank('/v1/a/c/o',
environ={'REQUEST_METHOD': 'PUT',
'wsgi.input': SlowBody()},
headers={'Content-Length': '4',
'Content-Type': 'text/plain'})
self.app.update_request(req)
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 201, 201, 201)
# acct cont obj obj obj
- resp = controller.PUT(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 499)
def test_node_read_timeout(self):
@@ -2217,13 +2257,11 @@ class TestObjectController(unittest.TestCase):
for dev in self.app.object_ring.devs.values():
dev['ip'] = '127.0.0.1'
dev['port'] = 1
- req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'GET'})
+ req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'})
self.app.update_request(req)
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 200, slow=True)
req.sent_size = 0
- resp = controller.GET(req)
+ resp = req.get_response(self.app)
got_exc = False
try:
resp.body
@@ -2232,7 +2270,7 @@ class TestObjectController(unittest.TestCase):
self.assert_(not got_exc)
self.app.node_timeout = 0.1
set_http_connect(200, 200, 200, slow=True)
- resp = controller.GET(req)
+ resp = req.get_response(self.app)
got_exc = False
try:
resp.body
@@ -2254,26 +2292,24 @@ class TestObjectController(unittest.TestCase):
for dev in self.app.object_ring.devs.values():
dev['ip'] = '127.0.0.1'
dev['port'] = 1
- req = Request.blank('/a/c/o',
+ req = Request.blank('/v1/a/c/o',
environ={'REQUEST_METHOD': 'PUT'},
headers={'Content-Length': '4',
'Content-Type': 'text/plain'},
body=' ')
self.app.update_request(req)
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 201, 201, 201, slow=True)
- resp = controller.PUT(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 201)
self.app.node_timeout = 0.1
set_http_connect(201, 201, 201, slow=True)
- req = Request.blank('/a/c/o',
+ req = Request.blank('/v1/a/c/o',
environ={'REQUEST_METHOD': 'PUT'},
headers={'Content-Length': '4',
'Content-Type': 'text/plain'},
body=' ')
self.app.update_request(req)
- resp = controller.PUT(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 503)
def test_iter_nodes(self):
@@ -2422,20 +2458,18 @@ class TestObjectController(unittest.TestCase):
def test_proxy_passes_content_type(self):
with save_globals():
- req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'GET'})
+ req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'})
self.app.update_request(req)
- controller = proxy_server.ObjectController(self.app, 'account',
- 'container', 'object')
set_http_connect(200, 200, 200)
- resp = controller.GET(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 200)
self.assertEquals(resp.content_type, 'x-application/test')
set_http_connect(200, 200, 200)
- resp = controller.GET(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 200)
self.assertEquals(resp.content_length, 0)
set_http_connect(200, 200, 200, slow=True)
- resp = controller.GET(req)
+ resp = req.get_response(self.app)
self.assertEquals(resp.status_int, 200)
self.assertEquals(resp.content_length, 4)
@@ -2865,7 +2899,7 @@ class TestObjectController(unittest.TestCase):
copy_from_obj_body = LargeResponseBody()
set_http_connect(200, 200, 200, 200, 200, 201, 201, 201,
- body=copy_from_obj_body)
+ body=copy_from_obj_body)
self.app.memcache.store = {}
resp = controller.PUT(req)
self.assertEquals(resp.status_int, 413)
@@ -2995,7 +3029,7 @@ class TestObjectController(unittest.TestCase):
copy_from_obj_body = LargeResponseBody()
set_http_connect(200, 200, 200, 200, 200, 201, 201, 201,
- body=copy_from_obj_body)
+ body=copy_from_obj_body)
self.app.memcache.store = {}
resp = controller.COPY(req)
self.assertEquals(resp.status_int, 413)
@@ -3347,16 +3381,24 @@ class TestObjectController(unittest.TestCase):
body = fd.read()
self.assertEquals(body, 'oh hai123456789abcdef')
- def test_version_manifest(self):
+ def test_version_manifest(self, oc='versions', vc='vers', o='name'):
versions_to_create = 3
# Create a container for our versioned object testing
(prolis, acc1lis, acc2lis, con1lis, con2lis, obj1lis,
obj2lis) = _test_sockets
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/versions HTTP/1.1\r\nHost: localhost\r\n'
+ pre = quote('%03x' % len(o))
+ osub = '%s.sub' % o
+ presub = quote('%03x' % len(osub))
+ osub = quote(osub)
+ presub = quote(presub)
+ oc = quote(oc)
+ vc = quote(vc)
+ fd.write('PUT /v1/a/%s HTTP/1.1\r\nHost: localhost\r\n'
'Connection: close\r\nX-Storage-Token: t\r\n'
- 'Content-Length: 0\r\nX-Versions-Location: vers\r\n\r\n')
+ 'Content-Length: 0\r\nX-Versions-Location: %s\r\n\r\n'
+ % (oc, vc))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
@@ -3364,19 +3406,19 @@ class TestObjectController(unittest.TestCase):
# check that the header was set
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/versions HTTP/1.1\r\nHost: localhost\r\n'
- 'Connection: close\r\nX-Storage-Token: t\r\n\r\n\r\n')
+ fd.write('GET /v1/a/%s HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nX-Storage-Token: t\r\n\r\n\r\n' % oc)
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response
self.assertEquals(headers[:len(exp)], exp)
- self.assert_('X-Versions-Location: vers' in headers)
+ self.assert_('X-Versions-Location: %s' % vc in headers)
# make the container for the object versions
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/vers HTTP/1.1\r\nHost: localhost\r\n'
+ fd.write('PUT /v1/a/%s HTTP/1.1\r\nHost: localhost\r\n'
'Connection: close\r\nX-Storage-Token: t\r\n'
- 'Content-Length: 0\r\n\r\n')
+ 'Content-Length: 0\r\n\r\n' % vc)
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
@@ -3384,10 +3426,10 @@ class TestObjectController(unittest.TestCase):
# Create the versioned file
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/versions/name HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
't\r\nContent-Length: 5\r\nContent-Type: text/jibberish0\r\n'
- 'X-Object-Meta-Foo: barbaz\r\n\r\n00000\r\n')
+ 'X-Object-Meta-Foo: barbaz\r\n\r\n00000\r\n' % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
@@ -3397,10 +3439,10 @@ class TestObjectController(unittest.TestCase):
sleep(.01) # guarantee that the timestamp changes
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/versions/name HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
't\r\nContent-Length: 5\r\nContent-Type: text/jibberish%s'
- '\r\n\r\n%05d\r\n' % (segment, segment))
+ '\r\n\r\n%05d\r\n' % (oc, o, segment, segment))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
@@ -3408,9 +3450,9 @@ class TestObjectController(unittest.TestCase):
# Ensure retrieving the manifest file gets the latest version
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/versions/name HTTP/1.1\r\nHost: '
+ fd.write('GET /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n'
- '\r\n')
+ '\r\n' % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 200'
@@ -3422,8 +3464,9 @@ class TestObjectController(unittest.TestCase):
# Ensure we have the right number of versions saved
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/vers?prefix=004name/ HTTP/1.1\r\nHost: '
- 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s?prefix=%s%s/ HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % (vc, pre, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 200'
@@ -3434,18 +3477,19 @@ class TestObjectController(unittest.TestCase):
# copy a version and make sure the version info is stripped
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('COPY /v1/a/versions/name HTTP/1.1\r\nHost: '
+ fd.write('COPY /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Auth-Token: '
- 't\r\nDestination: versions/copied_name\r\n'
- 'Content-Length: 0\r\n\r\n')
+ 't\r\nDestination: %s/copied_name\r\n'
+ 'Content-Length: 0\r\n\r\n' % (oc, o, oc))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response to the COPY
self.assertEquals(headers[:len(exp)], exp)
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/versions/copied_name HTTP/1.1\r\nHost: '
- 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s/copied_name HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % oc)
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 200'
@@ -3455,18 +3499,19 @@ class TestObjectController(unittest.TestCase):
# post and make sure it's updated
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('POST /v1/a/versions/name HTTP/1.1\r\nHost: '
+ fd.write('POST /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Auth-Token: '
't\r\nContent-Type: foo/bar\r\nContent-Length: 0\r\n'
- 'X-Object-Meta-Bar: foo\r\n\r\n')
+ 'X-Object-Meta-Bar: foo\r\n\r\n' % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response to the POST
self.assertEquals(headers[:len(exp)], exp)
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/versions/name HTTP/1.1\r\nHost: '
- 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s/%s HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 200'
@@ -3479,8 +3524,9 @@ class TestObjectController(unittest.TestCase):
for segment in xrange(versions_to_create - 1, 0, -1):
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('DELETE /v1/a/versions/name HTTP/1.1\r\nHost: localhost\r'
- '\nConnection: close\r\nX-Storage-Token: t\r\n\r\n')
+ fd.write('DELETE /v1/a/%s/%s HTTP/1.1\r\nHost: localhost\r'
+ '\nConnection: close\r\nX-Storage-Token: t\r\n\r\n'
+ % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response
@@ -3488,8 +3534,9 @@ class TestObjectController(unittest.TestCase):
# Ensure retrieving the manifest file gets the latest version
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/versions/name HTTP/1.1\r\nHost: localhost\r\n'
- 'Connection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s/%s HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 200'
@@ -3501,9 +3548,9 @@ class TestObjectController(unittest.TestCase):
# Ensure we have the right number of versions saved
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/vers?prefix=004name/ HTTP/1.1\r\nHost: '
+ fd.write('GET /v1/a/%s?prefix=%s%s/ HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r'
- '\n')
+ '\n' % (vc, pre, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response
@@ -3515,8 +3562,9 @@ class TestObjectController(unittest.TestCase):
# Ensure we have no saved versions
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/vers?prefix=004name/ HTTP/1.1\r\nHost: '
- 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s?prefix=%s%s/ HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % (vc, pre, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 204 No Content'
@@ -3524,8 +3572,8 @@ class TestObjectController(unittest.TestCase):
# delete the last verision
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('DELETE /v1/a/versions/name HTTP/1.1\r\nHost: localhost\r\n'
- 'Connection: close\r\nX-Storage-Token: t\r\n\r\n')
+ fd.write('DELETE /v1/a/%s/%s HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nX-Storage-Token: t\r\n\r\n' % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response
@@ -3533,8 +3581,9 @@ class TestObjectController(unittest.TestCase):
# Ensure it's all gone
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/versions/name HTTP/1.1\r\nHost: '
- 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s/%s HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 404'
@@ -3543,10 +3592,11 @@ class TestObjectController(unittest.TestCase):
# make sure manifest files don't get versioned
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/versions/name HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
't\r\nContent-Length: 0\r\nContent-Type: text/jibberish0\r\n'
- 'Foo: barbaz\r\nX-Object-Manifest: vers/foo_\r\n\r\n')
+ 'Foo: barbaz\r\nX-Object-Manifest: %s/foo_\r\n\r\n'
+ % (oc, vc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
@@ -3554,55 +3604,68 @@ class TestObjectController(unittest.TestCase):
# Ensure we have no saved versions
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/vers?prefix=004name/ HTTP/1.1\r\nHost: '
- 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s?prefix=%s%s/ HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % (vc, pre, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 204 No Content'
self.assertEquals(headers[:len(exp)], exp)
- # DELETE v1/a/c/dir shouldn't delete v1/a/c/dir/sub versions
+ # DELETE v1/a/c/obj shouldn't delete v1/a/c/obj/sub versions
+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
+ fd = sock.makefile()
+ fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Storage-Token: '
+ 't\r\nContent-Length: 5\r\nContent-Type: text/jibberish0\r\n'
+ 'Foo: barbaz\r\n\r\n00000\r\n' % (oc, o))
+ fd.flush()
+ headers = readuntil2crlfs(fd)
+ exp = 'HTTP/1.1 201'
+ self.assertEquals(headers[:len(exp)], exp)
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/versions/dir HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
- 't\r\nContent-Length: 0\r\nContent-Type: application/directory\r\n\r\n')
+ 't\r\nContent-Length: 5\r\nContent-Type: text/jibberish0\r\n'
+ 'Foo: barbaz\r\n\r\n00001\r\n' % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
self.assertEquals(headers[:len(exp)], exp)
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/versions/dir/sub HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
't\r\nContent-Length: 4\r\nContent-Type: text/jibberish0\r\n'
- 'Foo: barbaz\r\n\r\nsub1\r\n')
+ 'Foo: barbaz\r\n\r\nsub1\r\n' % (oc, osub))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
self.assertEquals(headers[:len(exp)], exp)
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/versions/dir/sub HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
't\r\nContent-Length: 4\r\nContent-Type: text/jibberish0\r\n'
- 'Foo: barbaz\r\n\r\nsub2\r\n')
+ 'Foo: barbaz\r\n\r\nsub2\r\n' % (oc, osub))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
self.assertEquals(headers[:len(exp)], exp)
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('DELETE /v1/a/versions/dir HTTP/1.1\r\nHost: localhost\r\n'
- 'Connection: close\r\nX-Storage-Token: t\r\n\r\n')
+ fd.write('DELETE /v1/a/%s/%s HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nX-Storage-Token: t\r\n\r\n' % (oc, o))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response
self.assertEquals(headers[:len(exp)], exp)
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('GET /v1/a/vers?prefix=007dir/sub/ HTTP/1.1\r\nHost: '
- 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n')
+ fd.write('GET /v1/a/%s?prefix=%s%s/ HTTP/1.1\r\nHost: '
+ 'localhost\r\nConnection: close\r\nX-Auth-Token: t\r\n\r\n'
+ % (vc, presub, osub))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx series response
@@ -3614,9 +3677,9 @@ class TestObjectController(unittest.TestCase):
# Check for when the versions target container doesn't exist
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/whoops HTTP/1.1\r\nHost: localhost\r\n'
+ fd.write('PUT /v1/a/%swhoops HTTP/1.1\r\nHost: localhost\r\n'
'Connection: close\r\nX-Storage-Token: t\r\n'
- 'Content-Length: 0\r\nX-Versions-Location: none\r\n\r\n')
+ 'Content-Length: 0\r\nX-Versions-Location: none\r\n\r\n' % oc)
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
@@ -3624,9 +3687,9 @@ class TestObjectController(unittest.TestCase):
# Create the versioned file
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/whoops/foo HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%swhoops/foo HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
- 't\r\nContent-Length: 5\r\n\r\n00000\r\n')
+ 't\r\nContent-Length: 5\r\n\r\n00000\r\n' % oc)
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
@@ -3634,9 +3697,9 @@ class TestObjectController(unittest.TestCase):
# Create another version
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('PUT /v1/a/whoops/foo HTTP/1.1\r\nHost: '
+ fd.write('PUT /v1/a/%swhoops/foo HTTP/1.1\r\nHost: '
'localhost\r\nConnection: close\r\nX-Storage-Token: '
- 't\r\nContent-Length: 5\r\n\r\n00001\r\n')
+ 't\r\nContent-Length: 5\r\n\r\n00001\r\n' % oc)
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 412'
@@ -3644,13 +3707,102 @@ class TestObjectController(unittest.TestCase):
# Delete the object
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
- fd.write('DELETE /v1/a/whoops/foo HTTP/1.1\r\nHost: localhost\r\n'
- 'Connection: close\r\nX-Storage-Token: t\r\n\r\n')
+ fd.write('DELETE /v1/a/%swhoops/foo HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nX-Storage-Token: t\r\n\r\n' % oc)
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 2' # 2xx response
self.assertEquals(headers[:len(exp)], exp)
+ def test_version_manifest_utf8(self):
+ oc = '0_oc_non_ascii\xc2\xa3'
+ vc = '0_vc_non_ascii\xc2\xa3'
+ o = '0_o_non_ascii\xc2\xa3'
+ self.test_version_manifest(oc, vc, o)
+
+ def test_version_manifest_utf8_container(self):
+ oc = '1_oc_non_ascii\xc2\xa3'
+ vc = '1_vc_ascii'
+ o = '1_o_ascii'
+ self.test_version_manifest(oc, vc, o)
+
+ def test_version_manifest_utf8_version_container(self):
+ oc = '2_oc_ascii'
+ vc = '2_vc_non_ascii\xc2\xa3'
+ o = '2_o_ascii'
+ self.test_version_manifest(oc, vc, o)
+
+ def test_version_manifest_utf8_containers(self):
+ oc = '3_oc_non_ascii\xc2\xa3'
+ vc = '3_vc_non_ascii\xc2\xa3'
+ o = '3_o_ascii'
+ self.test_version_manifest(oc, vc, o)
+
+ def test_version_manifest_utf8_object(self):
+ oc = '4_oc_ascii'
+ vc = '4_vc_ascii'
+ o = '4_o_non_ascii\xc2\xa3'
+ self.test_version_manifest(oc, vc, o)
+
+ def test_version_manifest_utf8_version_container_utf_object(self):
+ oc = '5_oc_ascii'
+ vc = '5_vc_non_ascii\xc2\xa3'
+ o = '5_o_non_ascii\xc2\xa3'
+ self.test_version_manifest(oc, vc, o)
+
+ def test_version_manifest_utf8_container_utf_object(self):
+ oc = '6_oc_non_ascii\xc2\xa3'
+ vc = '6_vc_ascii'
+ o = '6_o_non_ascii\xc2\xa3'
+ self.test_version_manifest(oc, vc, o)
+
+ def test_conditional_range_get(self):
+ (prolis, acc1lis, acc2lis, con1lis, con2lis, obj1lis, obj2lis) = \
+ _test_sockets
+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
+
+ # make a container
+ fd = sock.makefile()
+ fd.write('PUT /v1/a/con HTTP/1.1\r\nHost: localhost\r\n'
+ 'Connection: close\r\nX-Storage-Token: t\r\n'
+ 'Content-Length: 0\r\n\r\n')
+ fd.flush()
+ exp = 'HTTP/1.1 201'
+ headers = readuntil2crlfs(fd)
+ self.assertEquals(headers[:len(exp)], exp)
+
+ # put an object in it
+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
+ fd = sock.makefile()
+ fd.write('PUT /v1/a/con/o HTTP/1.1\r\n'
+ 'Host: localhost\r\n'
+ 'Connection: close\r\n'
+ 'X-Storage-Token: t\r\n'
+ 'Content-Length: 10\r\n'
+ 'Content-Type: text/plain\r\n'
+ '\r\n'
+ 'abcdefghij\r\n')
+ fd.flush()
+ exp = 'HTTP/1.1 201'
+ headers = readuntil2crlfs(fd)
+ self.assertEquals(headers[:len(exp)], exp)
+
+ # request with both If-None-Match and Range
+ etag = md5("abcdefghij").hexdigest()
+ sock = connect_tcp(('localhost', prolis.getsockname()[1]))
+ fd = sock.makefile()
+ fd.write('GET /v1/a/con/o HTTP/1.1\r\n' +
+ 'Host: localhost\r\n' +
+ 'Connection: close\r\n' +
+ 'X-Storage-Token: t\r\n' +
+ 'If-None-Match: "' + etag + '"\r\n' +
+ 'Range: bytes=3-8\r\n' +
+ '\r\n')
+ fd.flush()
+ exp = 'HTTP/1.1 304'
+ headers = readuntil2crlfs(fd)
+ self.assertEquals(headers[:len(exp)], exp)
+
def test_chunked_put_lobjects_with_nonzero_size_manifest_file(self):
raise SkipTest("Not until we support pure object requests")
# Create a container for our segmented/manifest object testing
@@ -4408,7 +4560,6 @@ class TestObjectController(unittest.TestCase):
self.assertTrue('X-Delete-At in past' in resp.body)
def test_leak_1(self):
- global _request_instances
prolis = _test_sockets[0]
prosrv = _test_servers[0]
obj_len = prosrv.client_chunk_size * 2
@@ -4426,8 +4577,11 @@ class TestObjectController(unittest.TestCase):
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
self.assertEqual(headers[:len(exp)], exp)
- # Remember Request instance count
- before_request_instances = _request_instances
+ # Remember Request instance count, make sure the GC is run for pythons
+ # without reference counting.
+ for i in xrange(4):
+ gc.collect()
+ before_request_instances = len(_request_instances)
# GET test file, but disconnect early
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()
@@ -4443,7 +4597,10 @@ class TestObjectController(unittest.TestCase):
fd.read(1)
fd.close()
sock.close()
- self.assertEquals(before_request_instances, _request_instances)
+ # Make sure the GC is run again for pythons without reference counting
+ for i in xrange(4):
+ gc.collect()
+ self.assertEquals(before_request_instances, len(_request_instances))
def test_OPTIONS(self):
with save_globals():
@@ -4630,7 +4787,8 @@ class TestObjectController(unittest.TestCase):
seen_headers = self._gather_x_container_headers(
controller.PUT, req,
200, 200, 201, 201, 201) # HEAD HEAD PUT PUT PUT
- self.assertEqual(seen_headers, [
+ self.assertEqual(
+ seen_headers, [
{'X-Container-Host': '10.0.0.0:1000',
'X-Container-Partition': '1',
'X-Container-Device': 'sda'},
@@ -4651,7 +4809,8 @@ class TestObjectController(unittest.TestCase):
controller.PUT, req,
200, 200, 201, 201, 201) # HEAD HEAD PUT PUT PUT
- self.assertEqual(seen_headers, [
+ self.assertEqual(
+ seen_headers, [
{'X-Container-Host': '10.0.0.0:1000',
'X-Container-Partition': '1',
'X-Container-Device': 'sda'},
@@ -4672,7 +4831,8 @@ class TestObjectController(unittest.TestCase):
controller.PUT, req,
200, 200, 201, 201, 201) # HEAD HEAD PUT PUT PUT
- self.assertEqual(seen_headers, [
+ self.assertEqual(
+ seen_headers, [
{'X-Container-Host': '10.0.0.0:1000,10.0.0.3:1003',
'X-Container-Partition': '1',
'X-Container-Device': 'sda,sdd'},
@@ -4694,7 +4854,8 @@ class TestObjectController(unittest.TestCase):
controller.POST, req,
200, 200, 200, 200, 200) # HEAD HEAD POST POST POST
- self.assertEqual(seen_headers, [
+ self.assertEqual(
+ seen_headers, [
{'X-Container-Host': '10.0.0.0:1000,10.0.0.3:1003',
'X-Container-Partition': '1',
'X-Container-Device': 'sda,sdd'},
@@ -4859,8 +5020,9 @@ class TestContainerController(unittest.TestCase):
self.assertEquals(res.headers['x-works'], 'yes')
if c_expected:
self.assertTrue('swift.container/a/c' in res.environ)
- self.assertEquals(res.environ['swift.container/a/c']['status'],
- c_expected)
+ self.assertEquals(
+ res.environ['swift.container/a/c']['status'],
+ c_expected)
else:
self.assertTrue('swift.container/a/c' not in res.environ)
if a_expected:
@@ -4882,8 +5044,9 @@ class TestContainerController(unittest.TestCase):
self.assertEquals(res.headers['x-works'], 'yes')
if c_expected:
self.assertTrue('swift.container/a/c' in res.environ)
- self.assertEquals(res.environ['swift.container/a/c']['status'],
- c_expected)
+ self.assertEquals(
+ res.environ['swift.container/a/c']['status'],
+ c_expected)
else:
self.assertTrue('swift.container/a/c' not in res.environ)
if a_expected:
@@ -4909,7 +5072,8 @@ class TestContainerController(unittest.TestCase):
# In all the following tests cache 404 for account
# return 404 (as account is not found) and dont cache container
test_status_map((404, 404, 404), 404, None, 404)
- self.app.account_autocreate = True # This should make no difference
+ # This should make no difference
+ self.app.account_autocreate = True
test_status_map((404, 404, 404), 404, None, 404)
def test_PUT(self):
@@ -4934,41 +5098,41 @@ class TestContainerController(unittest.TestCase):
self.assertFalse(self.app.account_autocreate)
test_status_map((404, 404, 404), 404, missing_container=True)
self.app.account_autocreate = True
- #fail to retrieve account info
+ # fail to retrieve account info
test_status_map(
- (503, 503, 503), # account_info fails on 503
- 404, missing_container=True)
+ (503, 503, 503), # account_info fails on 503
+ 404, missing_container=True)
# account fail after creation
test_status_map(
- (404, 404, 404, # account_info fails on 404
- 201, 201, 201, # PUT account
- 404, 404, 404), # account_info fail
- 404, missing_container=True)
+ (404, 404, 404, # account_info fails on 404
+ 201, 201, 201, # PUT account
+ 404, 404, 404), # account_info fail
+ 404, missing_container=True)
test_status_map(
- (503, 503, 404, # account_info fails on 404
- 503, 503, 503, # PUT account
- 503, 503, 404), # account_info fail
- 404, missing_container=True)
- #put fails
+ (503, 503, 404, # account_info fails on 404
+ 503, 503, 503, # PUT account
+ 503, 503, 404), # account_info fail
+ 404, missing_container=True)
+ # put fails
test_status_map(
- (404, 404, 404, # account_info fails on 404
- 201, 201, 201, # PUT account
- 200, # account_info success
- 503, 503, 201), # put container fail
- 503, missing_container=True)
+ (404, 404, 404, # account_info fails on 404
+ 201, 201, 201, # PUT account
+ 200, # account_info success
+ 503, 503, 201), # put container fail
+ 503, missing_container=True)
# all goes according to plan
test_status_map(
- (404, 404, 404, # account_info fails on 404
- 201, 201, 201, # PUT account
- 200, # account_info success
- 201, 201, 201), # put container success
- 201, missing_container=True)
+ (404, 404, 404, # account_info fails on 404
+ 201, 201, 201, # PUT account
+ 200, # account_info success
+ 201, 201, 201), # put container success
+ 201, missing_container=True)
test_status_map(
- (503, 404, 404, # account_info fails on 404
- 503, 201, 201, # PUT account
- 503, 200, # account_info success
- 503, 201, 201), # put container success
- 201, missing_container=True)
+ (503, 404, 404, # account_info fails on 404
+ 503, 201, 201, # PUT account
+ 503, 200, # account_info success
+ 503, 201, 201), # put container success
+ 201, missing_container=True)
def test_POST(self):
with save_globals():
@@ -5382,7 +5546,8 @@ class TestContainerController(unittest.TestCase):
req = Request.blank('/a/c')
self.app.update_request(req)
res = controller.GET(req)
- self.assertEquals(res.environ['swift.container/a/c']['status'], 204)
+ self.assertEquals(
+ res.environ['swift.container/a/c']['status'], 204)
self.assertEquals(res.content_length, 0)
self.assertTrue('transfer-encoding' not in res.headers)
@@ -5586,7 +5751,7 @@ class TestContainerController(unittest.TestCase):
self.assertEquals(expected_exposed, exposed)
def _gather_x_account_headers(self, controller_call, req, *connect_args,
- **kwargs):
+ **kwargs):
seen_headers = []
to_capture = ('X-Account-Partition', 'X-Account-Host',
'X-Account-Device')
@@ -5736,9 +5901,10 @@ class TestAccountController(unittest.TestCase):
# Access-Control-Request-Method headers)
self.app.allow_account_management = False
controller = proxy_server.AccountController(self.app, 'account')
- req = Request.blank('/account', {'REQUEST_METHOD': 'OPTIONS'},
+ req = Request.blank(
+ '/account', {'REQUEST_METHOD': 'OPTIONS'},
headers={'Origin': 'http://foo.com',
- 'Access-Control-Request-Method': 'GET'})
+ 'Access-Control-Request-Method': 'GET'})
req.content_length = 0
resp = controller.OPTIONS(req)
self.assertEquals(200, resp.status_int)
@@ -5753,7 +5919,6 @@ class TestAccountController(unittest.TestCase):
req.content_length = 0
resp = controller.OPTIONS(req)
self.assertEquals(200, resp.status_int)
- print resp.headers['Allow']
for verb in 'OPTIONS GET POST PUT DELETE HEAD'.split():
self.assertTrue(
verb in resp.headers['Allow'])
@@ -5847,16 +6012,19 @@ class TestAccountController(unittest.TestCase):
# first test with autocreate being False
self.assertFalse(self.app.account_autocreate)
self.assert_status_map(controller.POST,
- (404, 404, 404), 404)
+ (404, 404, 404), 404)
# next turn it on and test account being created than updated
controller.app.account_autocreate = True
- self.assert_status_map(controller.POST,
+ self.assert_status_map(
+ controller.POST,
(404, 404, 404, 202, 202, 202, 201, 201, 201), 201)
# account_info PUT account POST account
- self.assert_status_map(controller.POST,
- (404, 404, 503, 201, 201, 503, 204, 204, 504), 204)
+ self.assert_status_map(
+ controller.POST,
+ (404, 404, 503, 201, 201, 503, 204, 204, 504), 204)
# what if create fails
- self.assert_status_map(controller.POST,
+ self.assert_status_map(
+ controller.POST,
(404, 404, 404, 403, 403, 403, 400, 400, 400), 400)
def test_connection_refused(self):
@@ -6121,20 +6289,21 @@ class TestAccountControllerFakeGetResponse(unittest.TestCase):
have to match the responses for empty accounts that really exist.
"""
def setUp(self):
- self.app = proxy_server.Application(None, FakeMemcache(),
+ conf = {'account_autocreate': 'yes'}
+ self.app = proxy_server.Application(conf, FakeMemcache(),
account_ring=FakeRing(),
container_ring=FakeRing(),
object_ring=FakeRing)
self.app.memcache = FakeMemcacheReturnsNone()
- self.controller = proxy_server.AccountController(self.app, 'acc')
- self.controller.app.account_autocreate = True
def test_GET_autocreate_accept_json(self):
with save_globals():
- set_http_connect(404) # however many backends we ask, they all 404
- req = Request.blank('/a', headers={'Accept': 'application/json'})
-
- resp = self.controller.GET(req)
+ set_http_connect(*([404] * 100)) # nonexistent: all backends 404
+ req = Request.blank(
+ '/v1/a', headers={'Accept': 'application/json'},
+ environ={'REQUEST_METHOD': 'GET',
+ 'PATH_INFO': '/v1/a'})
+ resp = req.get_response(self.app)
self.assertEqual(200, resp.status_int)
self.assertEqual('application/json; charset=utf-8',
resp.headers['Content-Type'])
@@ -6142,10 +6311,12 @@ class TestAccountControllerFakeGetResponse(unittest.TestCase):
def test_GET_autocreate_format_json(self):
with save_globals():
- set_http_connect(404) # however many backends we ask, they all 404
- req = Request.blank('/a?format=json')
-
- resp = self.controller.GET(req)
+ set_http_connect(*([404] * 100)) # nonexistent: all backends 404
+ req = Request.blank('/v1/a?format=json',
+ environ={'REQUEST_METHOD': 'GET',
+ 'PATH_INFO': '/v1/a',
+ 'QUERY_STRING': 'format=json'})
+ resp = req.get_response(self.app)
self.assertEqual(200, resp.status_int)
self.assertEqual('application/json; charset=utf-8',
resp.headers['Content-Type'])
@@ -6153,30 +6324,54 @@ class TestAccountControllerFakeGetResponse(unittest.TestCase):
def test_GET_autocreate_accept_xml(self):
with save_globals():
- set_http_connect(404) # however many backends we ask, they all 404
- req = Request.blank('/a', headers={"Accept": "text/xml"})
+ set_http_connect(*([404] * 100)) # nonexistent: all backends 404
+ req = Request.blank('/v1/a', headers={"Accept": "text/xml"},
+ environ={'REQUEST_METHOD': 'GET',
+ 'PATH_INFO': '/v1/a'})
- resp = self.controller.GET(req)
+ resp = req.get_response(self.app)
self.assertEqual(200, resp.status_int)
+
self.assertEqual('text/xml; charset=utf-8',
resp.headers['Content-Type'])
empty_xml_listing = ('<?xml version="1.0" encoding="UTF-8"?>\n'
- '<account name="acc">\n</account>')
+ '<account name="a">\n</account>')
self.assertEqual(empty_xml_listing, resp.body)
def test_GET_autocreate_format_xml(self):
with save_globals():
- set_http_connect(404) # however many backends we ask, they all 404
- req = Request.blank('/a?format=xml')
-
- resp = self.controller.GET(req)
+ set_http_connect(*([404] * 100)) # nonexistent: all backends 404
+ req = Request.blank('/v1/a?format=xml',
+ environ={'REQUEST_METHOD': 'GET',
+ 'PATH_INFO': '/v1/a',
+ 'QUERY_STRING': 'format=xml'})
+ resp = req.get_response(self.app)
self.assertEqual(200, resp.status_int)
self.assertEqual('application/xml; charset=utf-8',
resp.headers['Content-Type'])
empty_xml_listing = ('<?xml version="1.0" encoding="UTF-8"?>\n'
- '<account name="acc">\n</account>')
+ '<account name="a">\n</account>')
self.assertEqual(empty_xml_listing, resp.body)
+ def test_GET_autocreate_accept_unknown(self):
+ with save_globals():
+ set_http_connect(*([404] * 100)) # nonexistent: all backends 404
+ req = Request.blank('/v1/a', headers={"Accept": "mystery/meat"},
+ environ={'REQUEST_METHOD': 'GET',
+ 'PATH_INFO': '/v1/a'})
+ resp = req.get_response(self.app)
+ self.assertEqual(406, resp.status_int)
+
+ def test_GET_autocreate_format_invalid_utf8(self):
+ with save_globals():
+ set_http_connect(*([404] * 100)) # nonexistent: all backends 404
+ req = Request.blank('/v1/a?format=\xff\xfe',
+ environ={'REQUEST_METHOD': 'GET',
+ 'PATH_INFO': '/v1/a',
+ 'QUERY_STRING': 'format=\xff\xfe'})
+ resp = req.get_response(self.app)
+ self.assertEqual(400, resp.status_int)
+
class FakeObjectController(object):
@@ -6350,7 +6545,8 @@ class TestSegmentedIterable(unittest.TestCase):
segit.ratelimit_index = 0
segit.listing.next()
segit._load_next_segment()
- self.assertEquals(self.controller.GETorHEAD_base_args[-1][4], '/a/lc/o2')
+ self.assertEquals(
+ self.controller.GETorHEAD_base_args[-1][4], '/a/lc/o2')
data = ''.join(segit.segment_iter)
self.assertEquals(data, '22')
@@ -6362,9 +6558,11 @@ class TestSegmentedIterable(unittest.TestCase):
segit.listing.next()
segit.seek = 1
segit._load_next_segment()
- self.assertEquals(self.controller.GETorHEAD_base_args[-1][4], '/a/lc/o2')
- self.assertEquals(str(self.controller.GETorHEAD_base_args[-1][0].range),
- 'bytes=1-')
+ self.assertEquals(
+ self.controller.GETorHEAD_base_args[-1][4], '/a/lc/o2')
+ self.assertEquals(
+ str(self.controller.GETorHEAD_base_args[-1][0].range),
+ 'bytes=1-')
data = ''.join(segit.segment_iter)
self.assertEquals(data, '2')