summaryrefslogtreecommitdiffstats
path: root/test/unit/proxy/test_server.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit/proxy/test_server.py')
-rw-r--r--test/unit/proxy/test_server.py904
1 files changed, 551 insertions, 353 deletions
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')