Reorganize SLO unit tests
This brings some sanity to the SLO test app (the thing the middleware wraps in the unit tests) as well as splits things into multiple test classes. This is part of the effort to move all SLO functionality to middleware, but it's a separate commit to prove that these test changes don't harm anything when running against the old code. Change-Id: I52a16f15a80dfaf9b3c595b0e634d52f418caf6c
This commit is contained in:
parent
2e1fc7446f
commit
9151bcc92c
@ -14,155 +14,15 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from copy import deepcopy
|
||||||
from mock import patch
|
from mock import patch
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
from swift.common import swob
|
||||||
from swift.common.middleware import slo
|
from swift.common.middleware import slo
|
||||||
from swift.common.utils import json
|
from swift.common.utils import json, split_path
|
||||||
from swift.common.swob import Request, Response, HTTPException
|
from swift.common.swob import Request, HTTPException
|
||||||
|
|
||||||
|
|
||||||
class FakeApp(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.calls = 0
|
|
||||||
self.req_method_paths = []
|
|
||||||
|
|
||||||
def __call__(self, env, start_response):
|
|
||||||
self.calls += 1
|
|
||||||
if env['PATH_INFO'] == '/':
|
|
||||||
return Response(status=200, body='passed')(env, start_response)
|
|
||||||
if env['PATH_INFO'].startswith('/test_good/'):
|
|
||||||
j, v, a, cont, obj = env['PATH_INFO'].split('/')
|
|
||||||
if obj == 'a_2':
|
|
||||||
return Response(status=400)(env, start_response)
|
|
||||||
cont_len = 100
|
|
||||||
if obj == 'small_object':
|
|
||||||
cont_len = 10
|
|
||||||
headers = {'etag': 'etagoftheobjectsegment',
|
|
||||||
'Content-Length': cont_len}
|
|
||||||
if obj == 'slob':
|
|
||||||
headers['X-Static-Large-Object'] = 'true'
|
|
||||||
return Response(status=200, headers=headers)(env, start_response)
|
|
||||||
if env['PATH_INFO'].startswith('/test_good_check/'):
|
|
||||||
j, v, a, cont, obj = env['PATH_INFO'].split('/')
|
|
||||||
etag, size = obj.split('_')
|
|
||||||
last_mod = 'Fri, 01 Feb 2012 20:38:36 GMT'
|
|
||||||
if obj == 'a_1':
|
|
||||||
last_mod = ''
|
|
||||||
return Response(
|
|
||||||
status=200,
|
|
||||||
headers={'etag': etag, 'Last-Modified': last_mod,
|
|
||||||
'Content-Length': size})(env, start_response)
|
|
||||||
if env['PATH_INFO'].startswith('/test_get/'):
|
|
||||||
good_data = json.dumps(
|
|
||||||
[{'name': '/c/a_1', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/d/b_2', 'hash': 'b', 'bytes': '2'}])
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True',
|
|
||||||
'Content-Type': 'html;swift_bytes=55'},
|
|
||||||
body=good_data)(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_get_broke_json/'):
|
|
||||||
good_data = json.dumps(
|
|
||||||
[{'name': '/c/a_1', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/d/b_2', 'hash': 'b', 'bytes': '2'}])
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=good_data[:-5])(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_get_bad_json/'):
|
|
||||||
bad_data = json.dumps(
|
|
||||||
[{'name': '/c/a_1', 'something': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/d/b_2', 'bytes': '2'}])
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=bad_data)(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_get_not_slo/'):
|
|
||||||
return Response(status=200, body='lalala')(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_delete_404/'):
|
|
||||||
good_data = json.dumps(
|
|
||||||
[{'name': '/c/a_1', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/d/b_2', 'hash': 'b', 'bytes': '2'}])
|
|
||||||
self.req_method_paths.append((env['REQUEST_METHOD'],
|
|
||||||
env['PATH_INFO']))
|
|
||||||
if env['PATH_INFO'].endswith('/c/man_404'):
|
|
||||||
return Response(status=404)(env, start_response)
|
|
||||||
if env['PATH_INFO'].endswith('/c/a_1'):
|
|
||||||
return Response(status=404)(env, start_response)
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=good_data)(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_delete/'):
|
|
||||||
good_data = json.dumps(
|
|
||||||
[{'name': '/c/a_1', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/d/b_2', 'hash': 'b', 'bytes': '2'}])
|
|
||||||
self.req_method_paths.append((env['REQUEST_METHOD'],
|
|
||||||
env['PATH_INFO']))
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=good_data)(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_delete_nested/'):
|
|
||||||
nested_data = json.dumps(
|
|
||||||
[{'name': '/b/b_2', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/c/c_3', 'hash': 'b', 'bytes': '2'}])
|
|
||||||
good_data = json.dumps(
|
|
||||||
[{'name': '/a/a_1', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/a/sub_nest', 'hash': 'a', 'sub_slo': True,
|
|
||||||
'bytes': len(nested_data)},
|
|
||||||
{'name': '/d/d_3', 'hash': 'b', 'bytes': '2'}])
|
|
||||||
self.req_method_paths.append((env['REQUEST_METHOD'],
|
|
||||||
env['PATH_INFO']))
|
|
||||||
if 'sub_nest' in env['PATH_INFO']:
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=nested_data)(env, start_response)
|
|
||||||
else:
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=good_data)(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_delete_nested_404/'):
|
|
||||||
good_data = json.dumps(
|
|
||||||
[{'name': '/a/a_1', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/a/sub_nest', 'hash': 'a', 'bytes': '2',
|
|
||||||
'sub_slo': True},
|
|
||||||
{'name': '/d/d_3', 'hash': 'b', 'bytes': '3'}])
|
|
||||||
self.req_method_paths.append((env['REQUEST_METHOD'],
|
|
||||||
env['PATH_INFO']))
|
|
||||||
if 'sub_nest' in env['PATH_INFO']:
|
|
||||||
return Response(status=404)(env, start_response)
|
|
||||||
else:
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=good_data)(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_delete_bad_json/'):
|
|
||||||
self.req_method_paths.append((env['REQUEST_METHOD'],
|
|
||||||
env['PATH_INFO']))
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body='bad json')(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_delete_bad_man/'):
|
|
||||||
self.req_method_paths.append((env['REQUEST_METHOD'],
|
|
||||||
env['PATH_INFO']))
|
|
||||||
return Response(status=200, body='')(env, start_response)
|
|
||||||
|
|
||||||
if env['PATH_INFO'].startswith('/test_delete_401/'):
|
|
||||||
good_data = json.dumps(
|
|
||||||
[{'name': '/c/a_1', 'hash': 'a', 'bytes': '1'},
|
|
||||||
{'name': '/d/b_2', 'hash': 'b', 'bytes': '2'}])
|
|
||||||
self.req_method_paths.append((env['REQUEST_METHOD'],
|
|
||||||
env['PATH_INFO']))
|
|
||||||
if env['PATH_INFO'].endswith('/d/b_2'):
|
|
||||||
return Response(status=401)(env, start_response)
|
|
||||||
return Response(status=200,
|
|
||||||
headers={'X-Static-Large-Object': 'True'},
|
|
||||||
body=good_data)(env, start_response)
|
|
||||||
|
|
||||||
test_xml_data = '''<?xml version="1.0" encoding="UTF-8"?>
|
test_xml_data = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<static_large_object>
|
<static_large_object>
|
||||||
<object_segment>
|
<object_segment>
|
||||||
@ -181,25 +41,97 @@ def fake_start_response(*args, **kwargs):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestStaticLargeObject(unittest.TestCase):
|
class FakeSwift(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.calls = []
|
||||||
|
self.req_method_paths = []
|
||||||
|
self.uploaded = {}
|
||||||
|
# mapping of (method, path) --> (response class, headers, body)
|
||||||
|
self._responses = {}
|
||||||
|
|
||||||
|
def __call__(self, env, start_response):
|
||||||
|
method = env['REQUEST_METHOD']
|
||||||
|
path = env['PATH_INFO']
|
||||||
|
_, acc, cont, obj = split_path(env['PATH_INFO'], 0, 4,
|
||||||
|
rest_with_last=True)
|
||||||
|
|
||||||
|
self.calls.append((method, path))
|
||||||
|
|
||||||
|
try:
|
||||||
|
resp_class, raw_headers, body = self._responses[(method, path)]
|
||||||
|
headers = swob.HeaderKeyDict(raw_headers)
|
||||||
|
except KeyError:
|
||||||
|
if method == 'GET' and obj and path in self.uploaded:
|
||||||
|
resp_class = swob.HTTPOk
|
||||||
|
headers, body = self.uploaded[path]
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
# simulate object PUT
|
||||||
|
if method == 'PUT' and obj:
|
||||||
|
input = env['wsgi.input'].read()
|
||||||
|
etag = md5(input).hexdigest()
|
||||||
|
headers.setdefault('Etag', etag)
|
||||||
|
headers.setdefault('Content-Length', len(input))
|
||||||
|
|
||||||
|
# keep it for subsequent GET requests later
|
||||||
|
self.uploaded[path] = (deepcopy(headers), input)
|
||||||
|
if "CONTENT_TYPE" in env:
|
||||||
|
self.uploaded[path][0]['Content-Type'] = env["CONTENT_TYPE"]
|
||||||
|
|
||||||
|
return resp_class(headers=headers, body=body)(env, start_response)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def call_count(self):
|
||||||
|
return len(self.calls)
|
||||||
|
|
||||||
|
def register(self, method, path, response_class, headers, body):
|
||||||
|
self._responses[(method, path)] = (response_class, headers, body)
|
||||||
|
|
||||||
|
|
||||||
|
class SloTestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.app = FakeApp()
|
self.app = FakeSwift()
|
||||||
self.slo = slo.filter_factory({})(self.app)
|
self.slo = slo.filter_factory({})(self.app)
|
||||||
self.slo.min_segment_size = 1
|
self.slo.min_segment_size = 1
|
||||||
|
|
||||||
def tearDown(self):
|
def call_app(self, req, app=None):
|
||||||
pass
|
if app is None:
|
||||||
|
app = self.app
|
||||||
|
|
||||||
|
status = [None]
|
||||||
|
headers = [None]
|
||||||
|
|
||||||
|
def start_response(s, h, ei=None):
|
||||||
|
status[0] = s
|
||||||
|
headers[0] = h
|
||||||
|
|
||||||
|
body = ''.join(app(req.environ, start_response))
|
||||||
|
return status[0], headers[0], body
|
||||||
|
|
||||||
|
def call_slo(self, req):
|
||||||
|
return self.call_app(req, app=self.slo)
|
||||||
|
|
||||||
|
|
||||||
|
class TestSloMiddleware(SloTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSloMiddleware, self).setUp()
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/', swob.HTTPOk, {}, 'passed')
|
||||||
|
self.app.register(
|
||||||
|
'PUT', '/', swob.HTTPOk, {}, 'passed')
|
||||||
|
|
||||||
def test_handle_multipart_no_obj(self):
|
def test_handle_multipart_no_obj(self):
|
||||||
req = Request.blank('/')
|
req = Request.blank('/')
|
||||||
resp_iter = self.slo(req.environ, fake_start_response)
|
resp_iter = self.slo(req.environ, fake_start_response)
|
||||||
self.assertEquals(self.app.calls, 1)
|
self.assertEquals(self.app.calls, [('GET', '/')])
|
||||||
self.assertEquals(''.join(resp_iter), 'passed')
|
self.assertEquals(''.join(resp_iter), 'passed')
|
||||||
|
|
||||||
def test_slo_header_assigned(self):
|
def test_slo_header_assigned(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/v/a/c/o', headers={'x-static-large-object': "true"})
|
'/v1/a/c/o', headers={'x-static-large-object': "true"})
|
||||||
resp = self.slo(req.environ, fake_start_response)
|
resp = self.slo(req.environ, fake_start_response)
|
||||||
self.assert_(
|
self.assert_(
|
||||||
resp[0].startswith('X-Static-Large-Object is a reserved header'))
|
resp[0].startswith('X-Static-Large-Object is a reserved header'))
|
||||||
@ -212,11 +144,62 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
self.assertEquals('/cont/object',
|
self.assertEquals('/cont/object',
|
||||||
slo.parse_input(data)[0]['path'])
|
slo.parse_input(data)[0]['path'])
|
||||||
|
|
||||||
bad_data = json.dumps([{'path': '/cont/object', 'size_bytes': 100}])
|
|
||||||
self.assertRaises(HTTPException, slo.parse_input, bad_data)
|
class TestSloPutManifest(SloTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSloPutManifest, self).setUp()
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/', swob.HTTPOk, {}, 'passed')
|
||||||
|
self.app.register(
|
||||||
|
'PUT', '/', swob.HTTPOk, {}, 'passed')
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'HEAD', '/v1/AUTH_test/cont/object',
|
||||||
|
swob.HTTPOk,
|
||||||
|
{'Content-Length': '100', 'Etag': 'etagoftheobjectsegment'},
|
||||||
|
None)
|
||||||
|
self.app.register(
|
||||||
|
'HEAD', '/v1/AUTH_test/cont/object\xe2\x99\xa1',
|
||||||
|
swob.HTTPOk,
|
||||||
|
{'Content-Length': '100', 'Etag': 'etagoftheobjectsegment'},
|
||||||
|
None)
|
||||||
|
self.app.register(
|
||||||
|
'HEAD', '/v1/AUTH_test/cont/small_object',
|
||||||
|
swob.HTTPOk,
|
||||||
|
{'Content-Length': '10', 'Etag': 'etagoftheobjectsegment'},
|
||||||
|
None)
|
||||||
|
self.app.register(
|
||||||
|
'PUT', '/v1/AUTH_test/c/man', swob.HTTPCreated, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/c/man', swob.HTTPNoContent, {}, None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'HEAD', '/v1/AUTH_test/checktest/a_1',
|
||||||
|
swob.HTTPOk,
|
||||||
|
{'Content-Length': '1', 'Etag': 'a'},
|
||||||
|
None)
|
||||||
|
self.app.register(
|
||||||
|
'HEAD', '/v1/AUTH_test/checktest/badreq',
|
||||||
|
swob.HTTPBadRequest, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'HEAD', '/v1/AUTH_test/checktest/b_2',
|
||||||
|
swob.HTTPOk,
|
||||||
|
{'Content-Length': '2', 'Etag': 'b',
|
||||||
|
'Last-Modified': 'Fri, 01 Feb 2012 20:38:36 GMT'},
|
||||||
|
None)
|
||||||
|
self.app.register(
|
||||||
|
'HEAD', '/v1/AUTH_test/checktest/slob',
|
||||||
|
swob.HTTPOk,
|
||||||
|
{'X-Static-Large-Object': 'true', 'Etag': 'slob-etag'},
|
||||||
|
None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'PUT', '/v1/AUTH_test/checktest/man_3', swob.HTTPCreated, {}, None)
|
||||||
|
|
||||||
def test_put_manifest_too_quick_fail(self):
|
def test_put_manifest_too_quick_fail(self):
|
||||||
req = Request.blank('/v/a/c/o')
|
req = Request.blank('/v1/a/c/o')
|
||||||
req.content_length = self.slo.max_manifest_size + 1
|
req.content_length = self.slo.max_manifest_size + 1
|
||||||
try:
|
try:
|
||||||
self.slo.handle_multipart_put(req, fake_start_response)
|
self.slo.handle_multipart_put(req, fake_start_response)
|
||||||
@ -225,7 +208,7 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
self.assertEquals(e.status_int, 413)
|
self.assertEquals(e.status_int, 413)
|
||||||
|
|
||||||
with patch.object(self.slo, 'max_manifest_segments', 0):
|
with patch.object(self.slo, 'max_manifest_segments', 0):
|
||||||
req = Request.blank('/v/a/c/o', body=test_json_data)
|
req = Request.blank('/v1/a/c/o', body=test_json_data)
|
||||||
e = None
|
e = None
|
||||||
try:
|
try:
|
||||||
self.slo.handle_multipart_put(req, fake_start_response)
|
self.slo.handle_multipart_put(req, fake_start_response)
|
||||||
@ -234,14 +217,14 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
self.assertEquals(e.status_int, 413)
|
self.assertEquals(e.status_int, 413)
|
||||||
|
|
||||||
with patch.object(self.slo, 'min_segment_size', 1000):
|
with patch.object(self.slo, 'min_segment_size', 1000):
|
||||||
req = Request.blank('/v/a/c/o', body=test_json_data)
|
req = Request.blank('/v1/a/c/o', body=test_json_data)
|
||||||
try:
|
try:
|
||||||
self.slo.handle_multipart_put(req, fake_start_response)
|
self.slo.handle_multipart_put(req, fake_start_response)
|
||||||
except HTTPException as e:
|
except HTTPException as e:
|
||||||
pass
|
pass
|
||||||
self.assertEquals(e.status_int, 400)
|
self.assertEquals(e.status_int, 400)
|
||||||
|
|
||||||
req = Request.blank('/v/a/c/o', headers={'X-Copy-From': 'lala'})
|
req = Request.blank('/v1/a/c/o', headers={'X-Copy-From': 'lala'})
|
||||||
try:
|
try:
|
||||||
self.slo.handle_multipart_put(req, fake_start_response)
|
self.slo.handle_multipart_put(req, fake_start_response)
|
||||||
except HTTPException as e:
|
except HTTPException as e:
|
||||||
@ -258,7 +241,7 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
|
|
||||||
def test_handle_multipart_put_success(self):
|
def test_handle_multipart_put_success(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_good/AUTH_test/c/man?multipart-manifest=put',
|
'/v1/AUTH_test/c/man?multipart-manifest=put',
|
||||||
environ={'REQUEST_METHOD': 'PUT'}, headers={'Accept': 'test'},
|
environ={'REQUEST_METHOD': 'PUT'}, headers={'Accept': 'test'},
|
||||||
body=test_json_data)
|
body=test_json_data)
|
||||||
self.assertTrue('X-Static-Large-Object' not in req.headers)
|
self.assertTrue('X-Static-Large-Object' not in req.headers)
|
||||||
@ -279,7 +262,7 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
'etag': 'etagoftheobjectsegment',
|
'etag': 'etagoftheobjectsegment',
|
||||||
'size_bytes': 10}])
|
'size_bytes': 10}])
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_good/AUTH_test/c/man?multipart-manifest=put',
|
'/v1/AUTH_test/c/man?multipart-manifest=put',
|
||||||
environ={'REQUEST_METHOD': 'PUT'}, headers={'Accept': 'test'},
|
environ={'REQUEST_METHOD': 'PUT'}, headers={'Accept': 'test'},
|
||||||
body=test_json_data)
|
body=test_json_data)
|
||||||
self.assertTrue('X-Static-Large-Object' not in req.headers)
|
self.assertTrue('X-Static-Large-Object' not in req.headers)
|
||||||
@ -291,13 +274,13 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
'etag': 'etagoftheobjectsegment',
|
'etag': 'etagoftheobjectsegment',
|
||||||
'size_bytes': 100}])
|
'size_bytes': 100}])
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_good/AUTH_test/c/man?multipart-manifest=put',
|
'/v1/AUTH_test/c/man?multipart-manifest=put',
|
||||||
environ={'REQUEST_METHOD': 'PUT'}, headers={'Accept': 'test'},
|
environ={'REQUEST_METHOD': 'PUT'}, headers={'Accept': 'test'},
|
||||||
body=test_json_data)
|
body=test_json_data)
|
||||||
self.assertTrue('X-Static-Large-Object' not in req.headers)
|
self.assertTrue('X-Static-Large-Object' not in req.headers)
|
||||||
self.slo(req.environ, fake_start_response)
|
self.slo(req.environ, fake_start_response)
|
||||||
self.assertTrue('X-Static-Large-Object' in req.headers)
|
self.assertTrue('X-Static-Large-Object' in req.headers)
|
||||||
self.assertTrue(req.environ['PATH_INFO'], '/cont/object\xe2\x99\xa4')
|
self.assertTrue(req.environ['PATH_INFO'], '/cont/object\xe2\x99\xa1')
|
||||||
|
|
||||||
def test_handle_multipart_put_no_xml(self):
|
def test_handle_multipart_put_no_xml(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
@ -322,9 +305,9 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
'size_bytes': 100}]),
|
'size_bytes': 100}]),
|
||||||
json.dumps('asdf'), json.dumps(None), json.dumps(5),
|
json.dumps('asdf'), json.dumps(None), json.dumps(5),
|
||||||
'not json', '1234', None, '', json.dumps({'path': None}),
|
'not json', '1234', None, '', json.dumps({'path': None}),
|
||||||
json.dumps([{'path': '/c/o', 'etag': None,
|
json.dumps([{'path': '/cont/object', 'etag': None,
|
||||||
'size_bytes': 12}]),
|
'size_bytes': 12}]),
|
||||||
json.dumps([{'path': '/c/o', 'etag': 'asdf',
|
json.dumps([{'path': '/cont/object', 'etag': 'asdf',
|
||||||
'size_bytes': 'sd'}]),
|
'size_bytes': 'sd'}]),
|
||||||
json.dumps([{'path': 12, 'etag': 'etagoftheobj',
|
json.dumps([{'path': 12, 'etag': 'etagoftheobj',
|
||||||
'size_bytes': 100}]),
|
'size_bytes': 100}]),
|
||||||
@ -335,22 +318,29 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
json.dumps([{'path': None, 'etag': 'etagoftheobj',
|
json.dumps([{'path': None, 'etag': 'etagoftheobj',
|
||||||
'size_bytes': 100}])]:
|
'size_bytes': 100}])]:
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_good/AUTH_test/c/man?multipart-manifest=put',
|
'/v1/AUTH_test/c/man?multipart-manifest=put',
|
||||||
environ={'REQUEST_METHOD': 'PUT'}, body=bad_data)
|
environ={'REQUEST_METHOD': 'PUT'}, body=bad_data)
|
||||||
self.assertRaises(HTTPException, self.slo.handle_multipart_put,
|
self.assertRaises(HTTPException, self.slo.handle_multipart_put,
|
||||||
req, fake_start_response)
|
req, fake_start_response)
|
||||||
|
|
||||||
def test_handle_multipart_put_check_data(self):
|
def test_handle_multipart_put_check_data(self):
|
||||||
good_data = json.dumps(
|
good_data = json.dumps(
|
||||||
[{'path': '/c/a_1', 'etag': 'a', 'size_bytes': '1'},
|
[{'path': '/checktest/a_1', 'etag': 'a', 'size_bytes': '1'},
|
||||||
{'path': '/d/b_2', 'etag': 'b', 'size_bytes': '2'}])
|
{'path': '/checktest/b_2', 'etag': 'b', 'size_bytes': '2'}])
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_good_check/A/c/man_3?multipart-manifest=put',
|
'/v1/AUTH_test/checktest/man_3?multipart-manifest=put',
|
||||||
environ={'REQUEST_METHOD': 'PUT'}, body=good_data)
|
environ={'REQUEST_METHOD': 'PUT'}, body=good_data)
|
||||||
self.slo.handle_multipart_put(req, fake_start_response)
|
status, headers, body = self.call_slo(req)
|
||||||
self.assertEquals(self.app.calls, 3)
|
self.assertEquals(self.app.call_count, 3)
|
||||||
self.assert_(req.environ['CONTENT_TYPE'].endswith(';swift_bytes=3'))
|
|
||||||
manifest_data = json.loads(req.environ['wsgi.input'].read())
|
# go behind SLO's back and see what actually got stored
|
||||||
|
req = Request.blank(
|
||||||
|
'/v1/AUTH_test/checktest/man_3?multipart-manifest=get',
|
||||||
|
environ={'REQUEST_METHOD': 'GET'})
|
||||||
|
status, headers, body = self.call_app(req)
|
||||||
|
headers = dict(headers)
|
||||||
|
manifest_data = json.loads(body)
|
||||||
|
self.assert_(headers['Content-Type'].endswith(';swift_bytes=3'))
|
||||||
self.assertEquals(len(manifest_data), 2)
|
self.assertEquals(len(manifest_data), 2)
|
||||||
self.assertEquals(manifest_data[0]['hash'], 'a')
|
self.assertEquals(manifest_data[0]['hash'], 'a')
|
||||||
self.assertEquals(manifest_data[0]['bytes'], 1)
|
self.assertEquals(manifest_data[0]['bytes'], 1)
|
||||||
@ -359,49 +349,156 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
|
|
||||||
def test_handle_multipart_put_check_data_bad(self):
|
def test_handle_multipart_put_check_data_bad(self):
|
||||||
bad_data = json.dumps(
|
bad_data = json.dumps(
|
||||||
[{'path': '/c/a_1', 'etag': 'a', 'size_bytes': '1'},
|
[{'path': '/checktest/a_1', 'etag': 'a', 'size_bytes': '2'},
|
||||||
{'path': '/c/a_2', 'etag': 'a', 'size_bytes': '1'},
|
{'path': '/checktest/badreq', 'etag': 'a', 'size_bytes': '1'},
|
||||||
{'path': '/d/b_2', 'etag': 'b', 'size_bytes': '2'},
|
{'path': '/checktest/b_2', 'etag': 'not-b', 'size_bytes': '2'},
|
||||||
{'path': '/d/slob', 'etag': 'a', 'size_bytes': '2'}])
|
{'path': '/checktest/slob', 'etag': 'not-slob',
|
||||||
|
'size_bytes': '2'}])
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_good/A/c/man?multipart-manifest=put',
|
'/v1/AUTH_test/checktest/man?multipart-manifest=put',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'Accept': 'application/json'},
|
headers={'Accept': 'application/json'},
|
||||||
body=bad_data)
|
body=bad_data)
|
||||||
try:
|
|
||||||
self.slo.handle_multipart_put(req, fake_start_response)
|
status, headers, body = self.call_slo(req)
|
||||||
except HTTPException as e:
|
self.assertEquals(self.app.call_count, 4)
|
||||||
self.assertEquals(self.app.calls, 4)
|
errors = json.loads(body)['Errors']
|
||||||
data = json.loads(e.body)
|
self.assertEquals(len(errors), 5)
|
||||||
errors = data['Errors']
|
self.assertEquals(errors[0][0], '/checktest/a_1')
|
||||||
self.assertEquals(errors[0][0], '/c/a_1')
|
self.assertEquals(errors[0][1], 'Size Mismatch')
|
||||||
self.assertEquals(errors[0][1], 'Size Mismatch')
|
self.assertEquals(errors[1][0], '/checktest/badreq')
|
||||||
self.assertEquals(errors[2][0], '/c/a_2')
|
self.assertEquals(errors[1][1], '400 Bad Request')
|
||||||
self.assertEquals(errors[2][1], '400 Bad Request')
|
self.assertEquals(errors[2][0], '/checktest/b_2')
|
||||||
self.assertEquals(errors[4][0], '/d/b_2')
|
self.assertEquals(errors[2][1], 'Etag Mismatch')
|
||||||
self.assertEquals(errors[4][1], 'Etag Mismatch')
|
self.assertEquals(errors[3][0], '/checktest/slob')
|
||||||
self.assertEquals(errors[-1][0], '/d/slob')
|
self.assertEquals(errors[3][1], 'Size Mismatch')
|
||||||
self.assertEquals(errors[-1][1], 'Etag Mismatch')
|
self.assertEquals(errors[4][0], '/checktest/slob')
|
||||||
else:
|
self.assertEquals(errors[4][1], 'Etag Mismatch')
|
||||||
self.assert_(False)
|
|
||||||
|
|
||||||
|
class TestSloDeleteManifest(SloTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSloDeleteManifest, self).setUp()
|
||||||
|
|
||||||
|
_submanifest_data = json.dumps(
|
||||||
|
[{'name': '/deltest/b_2', 'hash': 'a', 'bytes': '1'},
|
||||||
|
{'name': '/deltest/c_3', 'hash': 'b', 'bytes': '2'}])
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/man_404',
|
||||||
|
swob.HTTPNotFound, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/man',
|
||||||
|
swob.HTTPOk, {'Content-Type': 'application/json',
|
||||||
|
'X-Static-Large-Object': 'true'},
|
||||||
|
json.dumps([{'name': '/deltest/gone', 'hash': 'a', 'bytes': '1'},
|
||||||
|
{'name': '/deltest/b_2', 'hash': 'b', 'bytes': '2'}]))
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/man',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/man-all-there',
|
||||||
|
swob.HTTPOk, {'Content-Type': 'application/json',
|
||||||
|
'X-Static-Large-Object': 'true'},
|
||||||
|
json.dumps([{'name': '/deltest/b_2', 'hash': 'a', 'bytes': '1'},
|
||||||
|
{'name': '/deltest/c_3', 'hash': 'b', 'bytes': '2'}]))
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/gone',
|
||||||
|
swob.HTTPNotFound, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/a_1',
|
||||||
|
swob.HTTPOk, {'Content-Length': '1'}, 'a')
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/a_1',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/b_2',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/c_3',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/d_3',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/manifest-with-submanifest',
|
||||||
|
swob.HTTPOk, {'Content-Type': 'application/json',
|
||||||
|
'X-Static-Large-Object': 'true'},
|
||||||
|
json.dumps([{'name': '/deltest/a_1',
|
||||||
|
'hash': 'a', 'bytes': '1'},
|
||||||
|
{'name': '/deltest/submanifest', 'sub_slo': True,
|
||||||
|
'hash': 'submanifest-etag',
|
||||||
|
'bytes': len(_submanifest_data)},
|
||||||
|
{'name': '/deltest/d_3',
|
||||||
|
'hash': 'd', 'bytes': '3'}]))
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/manifest-with-submanifest',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/submanifest',
|
||||||
|
swob.HTTPOk, {'Content-Type': 'application/json',
|
||||||
|
'X-Static-Large-Object': 'true'},
|
||||||
|
_submanifest_data)
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/submanifest',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/manifest-missing-submanifest',
|
||||||
|
swob.HTTPOk, {'Content-Type': 'application/json',
|
||||||
|
'X-Static-Large-Object': 'true'},
|
||||||
|
json.dumps([{'name': '/deltest/a_1', 'hash': 'a', 'bytes': '1'},
|
||||||
|
{'name': '/deltest/missing-submanifest',
|
||||||
|
'hash': 'a', 'bytes': '2', 'sub_slo': True},
|
||||||
|
{'name': '/deltest/d_3', 'hash': 'd', 'bytes': '3'}]))
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/manifest-missing-submanifest',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/missing-submanifest',
|
||||||
|
swob.HTTPNotFound, {}, None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/manifest-badjson',
|
||||||
|
swob.HTTPOk, {'Content-Type': 'application/json',
|
||||||
|
'X-Static-Large-Object': 'true'},
|
||||||
|
"[not {json (at ++++all")
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'GET', '/v1/AUTH_test/deltest/manifest-with-unauth-segment',
|
||||||
|
swob.HTTPOk, {'Content-Type': 'application/json',
|
||||||
|
'X-Static-Large-Object': 'true'},
|
||||||
|
json.dumps([{'name': '/deltest/a_1', 'hash': 'a', 'bytes': '1'},
|
||||||
|
{'name': '/deltest-unauth/q_17',
|
||||||
|
'hash': '11', 'bytes': '17'}]))
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest/manifest-with-unauth-segment',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
|
||||||
|
self.app.register(
|
||||||
|
'DELETE', '/v1/AUTH_test/deltest-unauth/q_17',
|
||||||
|
swob.HTTPUnauthorized, {}, None)
|
||||||
|
|
||||||
def test_handle_multipart_delete_man(self):
|
def test_handle_multipart_delete_man(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_good/A/c/man', environ={'REQUEST_METHOD': 'DELETE'})
|
'/v1/AUTH_test/deltest/man',
|
||||||
|
environ={'REQUEST_METHOD': 'DELETE'})
|
||||||
self.slo(req.environ, fake_start_response)
|
self.slo(req.environ, fake_start_response)
|
||||||
self.assertEquals(self.app.calls, 1)
|
self.assertEquals(self.app.call_count, 1)
|
||||||
|
|
||||||
def test_handle_multipart_delete_whole_404(self):
|
def test_handle_multipart_delete_whole_404(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete_404/A/c/man_404?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/man_404?multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE',
|
environ={'REQUEST_METHOD': 'DELETE',
|
||||||
'HTTP_ACCEPT': 'application/json'})
|
'HTTP_ACCEPT': 'application/json'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
status, response, body = self.call_slo(req)
|
||||||
app_iter = list(app_iter) # iterate through whole response
|
resp_data = json.loads(body)
|
||||||
resp_data = json.loads(app_iter[0])
|
self.assertEquals(self.app.calls,
|
||||||
self.assertEquals(self.app.calls, 1)
|
[('GET', '/v1/AUTH_test/deltest/man_404')])
|
||||||
self.assertEquals(self.app.req_method_paths,
|
|
||||||
[('GET', '/test_delete_404/A/c/man_404')])
|
|
||||||
self.assertEquals(resp_data['Response Status'], '200 OK')
|
self.assertEquals(resp_data['Response Status'], '200 OK')
|
||||||
self.assertEquals(resp_data['Response Body'], '')
|
self.assertEquals(resp_data['Response Body'], '')
|
||||||
self.assertEquals(resp_data['Number Deleted'], 0)
|
self.assertEquals(resp_data['Number Deleted'], 0)
|
||||||
@ -410,68 +507,66 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
|
|
||||||
def test_handle_multipart_delete_segment_404(self):
|
def test_handle_multipart_delete_segment_404(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete_404/A/c/man?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/man?multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE',
|
environ={'REQUEST_METHOD': 'DELETE',
|
||||||
'HTTP_ACCEPT': 'application/json'})
|
'HTTP_ACCEPT': 'application/json'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
status, response, body = self.call_slo(req)
|
||||||
app_iter = list(app_iter) # iterate through whole response
|
resp_data = json.loads(body)
|
||||||
resp_data = json.loads(app_iter[0])
|
self.assertEquals(self.app.calls,
|
||||||
self.assertEquals(self.app.calls, 4)
|
[('GET', '/v1/AUTH_test/deltest/man'),
|
||||||
self.assertEquals(self.app.req_method_paths,
|
('DELETE', '/v1/AUTH_test/deltest/gone'),
|
||||||
[('GET', '/test_delete_404/A/c/man'),
|
('DELETE', '/v1/AUTH_test/deltest/b_2'),
|
||||||
('DELETE', '/test_delete_404/A/c/a_1'),
|
('DELETE', '/v1/AUTH_test/deltest/man')])
|
||||||
('DELETE', '/test_delete_404/A/d/b_2'),
|
|
||||||
('DELETE', '/test_delete_404/A/c/man')])
|
|
||||||
self.assertEquals(resp_data['Response Status'], '200 OK')
|
self.assertEquals(resp_data['Response Status'], '200 OK')
|
||||||
self.assertEquals(resp_data['Number Deleted'], 2)
|
self.assertEquals(resp_data['Number Deleted'], 2)
|
||||||
self.assertEquals(resp_data['Number Not Found'], 1)
|
self.assertEquals(resp_data['Number Not Found'], 1)
|
||||||
|
|
||||||
def test_handle_multipart_delete_whole(self):
|
def test_handle_multipart_delete_whole(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete/A/c/man?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/man-all-there?multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE'})
|
environ={'REQUEST_METHOD': 'DELETE'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
self.call_slo(req)
|
||||||
list(app_iter) # iterate through whole response
|
self.assertEquals(self.app.calls,
|
||||||
self.assertEquals(self.app.calls, 4)
|
[('GET', '/v1/AUTH_test/deltest/man-all-there'),
|
||||||
self.assertEquals(self.app.req_method_paths,
|
('DELETE', '/v1/AUTH_test/deltest/b_2'),
|
||||||
[('GET', '/test_delete/A/c/man'),
|
('DELETE', '/v1/AUTH_test/deltest/c_3'),
|
||||||
('DELETE', '/test_delete/A/c/a_1'),
|
('DELETE', '/v1/AUTH_test/deltest/man-all-there')])
|
||||||
('DELETE', '/test_delete/A/d/b_2'),
|
|
||||||
('DELETE', '/test_delete/A/c/man')])
|
|
||||||
|
|
||||||
def test_handle_multipart_delete_nested(self):
|
def test_handle_multipart_delete_nested(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete_nested/A/c/man?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/manifest-with-submanifest?' +
|
||||||
|
'multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE'})
|
environ={'REQUEST_METHOD': 'DELETE'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
self.call_slo(req)
|
||||||
list(app_iter) # iterate through whole response
|
|
||||||
self.assertEquals(self.app.calls, 8)
|
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
set(self.app.req_method_paths),
|
set(self.app.calls),
|
||||||
set([('GET', '/test_delete_nested/A/c/man'),
|
set([('GET', '/v1/AUTH_test/deltest/manifest-with-submanifest'),
|
||||||
('GET', '/test_delete_nested/A/a/sub_nest'),
|
('GET', '/v1/AUTH_test/deltest/submanifest'),
|
||||||
('DELETE', '/test_delete_nested/A/a/a_1'),
|
('DELETE', '/v1/AUTH_test/deltest/a_1'),
|
||||||
('DELETE', '/test_delete_nested/A/b/b_2'),
|
('DELETE', '/v1/AUTH_test/deltest/b_2'),
|
||||||
('DELETE', '/test_delete_nested/A/c/c_3'),
|
('DELETE', '/v1/AUTH_test/deltest/c_3'),
|
||||||
('DELETE', '/test_delete_nested/A/a/sub_nest'),
|
('DELETE', '/v1/AUTH_test/deltest/submanifest'),
|
||||||
('DELETE', '/test_delete_nested/A/d/d_3'),
|
('DELETE', '/v1/AUTH_test/deltest/d_3'),
|
||||||
('DELETE', '/test_delete_nested/A/c/man')]))
|
('DELETE', '/v1/AUTH_test/deltest/' +
|
||||||
|
'manifest-with-submanifest')]))
|
||||||
|
|
||||||
def test_handle_multipart_delete_nested_404(self):
|
def test_handle_multipart_delete_nested_404(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete_nested_404/A/c/man?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/manifest-missing-submanifest' +
|
||||||
|
'?multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE',
|
environ={'REQUEST_METHOD': 'DELETE',
|
||||||
'HTTP_ACCEPT': 'application/json'})
|
'HTTP_ACCEPT': 'application/json'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
status, response, body = self.call_slo(req)
|
||||||
app_iter = list(app_iter) # iterate through whole response
|
resp_data = json.loads(body)
|
||||||
resp_data = json.loads(app_iter[0])
|
self.assertEquals(self.app.calls,
|
||||||
self.assertEquals(self.app.calls, 5)
|
[('GET', '/v1/AUTH_test/deltest/' +
|
||||||
self.assertEquals(self.app.req_method_paths,
|
'manifest-missing-submanifest'),
|
||||||
[('GET', '/test_delete_nested_404/A/c/man'),
|
('DELETE', '/v1/AUTH_test/deltest/a_1'),
|
||||||
('DELETE', '/test_delete_nested_404/A/a/a_1'),
|
('GET', '/v1/AUTH_test/deltest/' +
|
||||||
('GET', '/test_delete_nested_404/A/a/sub_nest'),
|
'missing-submanifest'),
|
||||||
('DELETE', '/test_delete_nested_404/A/d/d_3'),
|
('DELETE', '/v1/AUTH_test/deltest/d_3'),
|
||||||
('DELETE', '/test_delete_nested_404/A/c/man')])
|
('DELETE', '/v1/AUTH_test/deltest/' +
|
||||||
|
'manifest-missing-submanifest')])
|
||||||
self.assertEquals(resp_data['Response Status'], '200 OK')
|
self.assertEquals(resp_data['Response Status'], '200 OK')
|
||||||
self.assertEquals(resp_data['Response Body'], '')
|
self.assertEquals(resp_data['Response Body'], '')
|
||||||
self.assertEquals(resp_data['Number Deleted'], 3)
|
self.assertEquals(resp_data['Number Deleted'], 3)
|
||||||
@ -480,60 +575,59 @@ class TestStaticLargeObject(unittest.TestCase):
|
|||||||
|
|
||||||
def test_handle_multipart_delete_not_a_manifest(self):
|
def test_handle_multipart_delete_not_a_manifest(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete_bad_man/A/c/man?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/a_1?multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE',
|
environ={'REQUEST_METHOD': 'DELETE',
|
||||||
'HTTP_ACCEPT': 'application/json'})
|
'HTTP_ACCEPT': 'application/json'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
status, response, body = self.call_slo(req)
|
||||||
app_iter = list(app_iter) # iterate through whole response
|
resp_data = json.loads(body)
|
||||||
resp_data = json.loads(app_iter[0])
|
self.assertEquals(self.app.calls,
|
||||||
self.assertEquals(self.app.calls, 1)
|
[('GET', '/v1/AUTH_test/deltest/a_1')])
|
||||||
self.assertEquals(self.app.req_method_paths,
|
|
||||||
[('GET', '/test_delete_bad_man/A/c/man')])
|
|
||||||
self.assertEquals(resp_data['Response Status'], '400 Bad Request')
|
self.assertEquals(resp_data['Response Status'], '400 Bad Request')
|
||||||
self.assertEquals(resp_data['Response Body'], '')
|
self.assertEquals(resp_data['Response Body'], '')
|
||||||
self.assertEquals(resp_data['Number Deleted'], 0)
|
self.assertEquals(resp_data['Number Deleted'], 0)
|
||||||
self.assertEquals(resp_data['Number Not Found'], 0)
|
self.assertEquals(resp_data['Number Not Found'], 0)
|
||||||
self.assertEquals(resp_data['Errors'],
|
self.assertEquals(resp_data['Errors'],
|
||||||
[['/c/man', 'Not an SLO manifest']])
|
[['/deltest/a_1', 'Not an SLO manifest']])
|
||||||
|
|
||||||
def test_handle_multipart_delete_bad_json(self):
|
def test_handle_multipart_delete_bad_json(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete_bad_json/A/c/man?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/manifest-badjson?multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE',
|
environ={'REQUEST_METHOD': 'DELETE',
|
||||||
'HTTP_ACCEPT': 'application/json'})
|
'HTTP_ACCEPT': 'application/json'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
status, response, body = self.call_slo(req)
|
||||||
app_iter = list(app_iter) # iterate through whole response
|
resp_data = json.loads(body)
|
||||||
resp_data = json.loads(app_iter[0])
|
self.assertEquals(self.app.calls,
|
||||||
self.assertEquals(self.app.calls, 1)
|
[('GET', '/v1/AUTH_test/deltest/manifest-badjson')])
|
||||||
self.assertEquals(self.app.req_method_paths,
|
|
||||||
[('GET', '/test_delete_bad_json/A/c/man')])
|
|
||||||
self.assertEquals(resp_data['Response Status'], '400 Bad Request')
|
self.assertEquals(resp_data['Response Status'], '400 Bad Request')
|
||||||
self.assertEquals(resp_data['Response Body'], '')
|
self.assertEquals(resp_data['Response Body'], '')
|
||||||
self.assertEquals(resp_data['Number Deleted'], 0)
|
self.assertEquals(resp_data['Number Deleted'], 0)
|
||||||
self.assertEquals(resp_data['Number Not Found'], 0)
|
self.assertEquals(resp_data['Number Not Found'], 0)
|
||||||
self.assertEquals(resp_data['Errors'],
|
self.assertEquals(resp_data['Errors'],
|
||||||
[['/c/man', 'Unable to load SLO manifest']])
|
[['/deltest/manifest-badjson',
|
||||||
|
'Unable to load SLO manifest']])
|
||||||
|
|
||||||
def test_handle_multipart_delete_401(self):
|
def test_handle_multipart_delete_401(self):
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/test_delete_401/A/c/man?multipart-manifest=delete',
|
'/v1/AUTH_test/deltest/manifest-with-unauth-segment' +
|
||||||
|
'?multipart-manifest=delete',
|
||||||
environ={'REQUEST_METHOD': 'DELETE',
|
environ={'REQUEST_METHOD': 'DELETE',
|
||||||
'HTTP_ACCEPT': 'application/json'})
|
'HTTP_ACCEPT': 'application/json'})
|
||||||
app_iter = self.slo(req.environ, fake_start_response)
|
status, response, body = self.call_slo(req)
|
||||||
app_iter = list(app_iter) # iterate through whole response
|
resp_data = json.loads(body)
|
||||||
resp_data = json.loads(app_iter[0])
|
self.assertEquals(self.app.calls,
|
||||||
self.assertEquals(self.app.calls, 4)
|
[('GET', '/v1/AUTH_test/deltest/' +
|
||||||
self.assertEquals(self.app.req_method_paths,
|
'manifest-with-unauth-segment'),
|
||||||
[('GET', '/test_delete_401/A/c/man'),
|
('DELETE', '/v1/AUTH_test/deltest/a_1'),
|
||||||
('DELETE', '/test_delete_401/A/c/a_1'),
|
('DELETE', '/v1/AUTH_test/deltest-unauth/q_17'),
|
||||||
('DELETE', '/test_delete_401/A/d/b_2'),
|
('DELETE', '/v1/AUTH_test/deltest/' +
|
||||||
('DELETE', '/test_delete_401/A/c/man')])
|
'manifest-with-unauth-segment')])
|
||||||
self.assertEquals(resp_data['Response Status'], '400 Bad Request')
|
self.assertEquals(resp_data['Response Status'], '400 Bad Request')
|
||||||
self.assertEquals(resp_data['Response Body'], '')
|
self.assertEquals(resp_data['Response Body'], '')
|
||||||
self.assertEquals(resp_data['Number Deleted'], 2)
|
self.assertEquals(resp_data['Number Deleted'], 2)
|
||||||
self.assertEquals(resp_data['Number Not Found'], 0)
|
self.assertEquals(resp_data['Number Not Found'], 0)
|
||||||
self.assertEquals(resp_data['Errors'],
|
self.assertEquals(resp_data['Errors'],
|
||||||
[['/d/b_2', '401 Unauthorized']])
|
[['/deltest-unauth/q_17', '401 Unauthorized']])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user