storlets/tests/unit/swift_middleware/handlers/test_proxy.py

641 lines
28 KiB
Python

# Copyright (c) 2010-2015 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
import unittest
import itertools
from contextlib import contextmanager
from swift.common.swob import Request, HTTPOk, HTTPCreated, HTTPAccepted, \
HTTPNoContent, HTTPNotFound
from storlets.swift_middleware.handlers import StorletProxyHandler
from storlets.swift_middleware.handlers.proxy import REFERER_PREFIX
from tests.unit.swift_middleware.handlers import \
BaseTestStorletMiddleware, create_handler_config
@contextmanager
def fake_acc_info(acc_info):
with mock.patch('storlets.swift_middleware.handlers.proxy.'
'get_account_info') as ai:
ai.return_value = acc_info
yield
@contextmanager
def storlet_enabled():
acc_info = {'meta': {'storlet-enabled': 'true'}}
with fake_acc_info(acc_info):
yield
class TestStorletMiddlewareProxy(BaseTestStorletMiddleware):
def setUp(self):
super(TestStorletMiddlewareProxy, self).setUp(exec_server='proxy')
def test_load_app(self):
try:
self.get_app(self.base_app, self.conf)
except Exception:
self.fail('Application loading got an error')
def get_request_response(self, target, method, headers=None, body=None):
req = Request.blank(target, environ={'REQUEST_METHOD': method},
headers=headers, body=body)
return self.get_response(req)
def test_GET_without_storlets(self):
def basic_get(path):
self.base_app.register('GET', path, HTTPOk, body='FAKE APP')
resp = self.get_request_response(path, 'GET')
self.assertEqual('200 OK', resp.status)
self.assertEqual('FAKE APP', resp.body)
self.base_app.reset_all()
for target in ('AUTH_a', 'AUTH_a/c', 'AUTH_a/c/o'):
path = '/'.join(['', 'v1', target])
basic_get(path)
def test_GET_with_storlets(self):
# TODO(takashi): decide request path based on config value
target = '/v1/AUTH_a/c/o'
self.base_app.register('GET', target, HTTPOk, body='FAKE RESULT')
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, headers={},
body='jar binary')
acc_info = {'meta': {'storlet-enabled': 'true'}}
with fake_acc_info(acc_info):
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('200 OK', resp.status)
self.assertEqual('FAKE RESULT', resp.body)
calls = self.base_app.get_calls()
# Make sure now we sent two requests to swift
self.assertEqual(2, len(calls))
# The first one is HEAD request to storlet object
self.assertEqual('HEAD', calls[0][0])
self.assertEqual(storlet, calls[0][1])
# The last one is exexution GET call
self.assertEqual(target, calls[-1][1])
self.assertIn('X-Run-Storlet', calls[-1][2])
def test_GET_with_storlets_disabled_account(self):
target = '/v1/AUTH_a/c/o'
acc_info = {'meta': {}}
with fake_acc_info(acc_info):
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('400 Bad Request', resp.status)
calls = self.base_app.get_calls()
self.assertEqual(0, len(calls))
def test_GET_with_storlets_object_404(self):
target = '/v1/AUTH_a/c/o'
self.base_app.register('GET', target, HTTPNotFound)
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('404 Not Found', resp.status)
calls = self.base_app.get_calls()
self.assertEqual(2, len(calls))
def test_GET_with_storlets_and_http_range(self):
target = '/v1/AUTH_a/c/o'
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar',
'Range': 'bytes=10-20'}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('400 Bad Request', resp.status)
def test_GET_with_storlets_and_storlet_range(self):
target = '/v1/AUTH_a/c/o'
self.base_app.register('GET', target, HTTPOk, body='FAKE APP')
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
req_range = 'bytes=1-6'
headers = {'X-Run-Storlet': 'Storlet-1.0.jar',
'X-Storlet-Run-On-Proxy': '',
'X-Storlet-Range': req_range}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('200 OK', resp.status)
self.assertEqual('AKE AP', resp.body)
self.assertNotIn('Content-Range', resp.headers)
self.assertEqual(resp.headers['Storlet-Input-Range'],
'bytes 1-6/8')
raw_req = self.base_app.get_calls('GET', target)[0]
for key in ['Range', 'X-Storlet-Range']:
self.assertEqual(raw_req[2][key], req_range)
def test_GET_with_storlets_and_object_storlet_range(self):
# Create a single range request that needs to be
# processed by the object handler
target = '/v1/AUTH_a/c/o'
self.base_app.register('GET', target, HTTPOk, body='FAKE APP')
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
req_range = 'bytes=1-6'
headers = {'X-Run-Storlet': 'Storlet-1.0.jar',
'X-Storlet-Range': req_range}
resp = self.get_request_response(target, 'GET', headers=headers)
# We assert that nothing actually happens
# by the proxy handler
self.assertEqual('200 OK', resp.status)
self.assertEqual('FAKE APP', resp.body)
def test_GET_with_storlets_and_extra_resourece(self):
target = '/v1/AUTH_a/c/o'
self.base_app.register('GET', target, HTTPOk, body='FAKE APP')
extra_target = '/v1/AUTH_a/c2/o2'
self.base_app.register('GET', extra_target, HTTPOk, body='Whooa')
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar',
'X-Storlet-Extra-Resources': '/c2/o2'}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('200 OK', resp.status)
self.assertEqual('FAKE APP', resp.body)
# GET target called
self.assertTrue(any(self.base_app.get_calls('GET', target)))
# GET extra target also called
self.assertTrue(any(self.base_app.get_calls('GET', extra_target)))
def test_GET_slo_without_storlets(self):
target = '/v1/AUTH_a/c/slo_manifest'
self.base_app.register('GET', target, HTTPOk,
headers={'x-static-large-object': 'True'},
body='FAKE APP')
resp = self.get_request_response(target, 'GET')
self.assertEqual('FAKE APP', resp.body)
def test_GET_slo_with_storlets(self):
target = '/v1/AUTH_a/c/slo_manifest'
self.base_app.register('GET', target, HTTPOk,
headers={'x-static-large-object': 'True'},
body='FAKE APP')
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('200 OK', resp.status)
self.assertEqual('FAKE APP', resp.body)
calls = self.base_app.get_calls()
self.assertEqual(2, len(calls))
def test_GET_with_storlets_no_object(self):
target = '/v1/AUTH_a/c/'
self.base_app.register('GET', target, HTTPOk,
body='FAKE APP')
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response(target, 'GET', headers=headers)
self.assertEqual('200 OK', resp.status)
self.assertEqual('FAKE APP', resp.body)
# Make sure now we sent one request to swift
# that is, storlets path was not executed
# due to no object in target
calls = self.base_app.get_calls()
self.assertEqual(1, len(calls))
def test_PUT_without_storlets(self):
def basic_put(path):
self.base_app.register('PUT', path, HTTPCreated)
resp = self.get_request_response(path, 'PUT')
self.assertEqual('201 Created', resp.status)
self.base_app.reset_all()
for target in ('AUTH_a', 'AUTH_a/c', 'AUTH_a/c/o'):
path = '/'.join(['', 'v1', target])
basic_put(path)
def test_PUT_with_storlets(self):
target = '/v1/AUTH_a/c/o'
self.base_app.register('PUT', target, HTTPCreated)
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response(target, 'PUT', headers=headers,
body='FAKE APP')
self.assertEqual('201 Created', resp.status)
calls = self.base_app.get_calls()
# Make sure now we sent two requests to swift
self.assertEqual(2, len(calls))
# The first one is HEAD request to storlet object
self.assertEqual('HEAD', calls[0][0])
self.assertEqual(storlet, calls[0][1])
# The last one is PUT request about processed object
self.assertEqual('PUT', calls[-1][0])
self.assertEqual(target, calls[-1][1])
self.assertEqual(calls[-1][3], 'FAKE APP')
def test_PUT_with_storlets_no_object(self):
target = '/v1/AUTH_a/c/'
self.base_app.register('PUT', target, HTTPCreated)
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response(target, 'PUT', headers=headers,
body='FAKE APP')
self.assertEqual('201 Created', resp.status)
calls = self.base_app.get_calls()
# Make sure now we sent one request to swift
# that is, storlets path was not executed
# due to no object in target
self.assertEqual(1, len(calls))
def test_PUT_copy_without_storlets(self):
target = '/v1/AUTH_a/c/to'
copy_from = 'c/so'
self.base_app.register('PUT', target, HTTPCreated)
headers = {'X-Copy-From': copy_from,
'X-Backend-Storage-Policy-Index': 0}
resp = self.get_request_response(target, 'PUT', headers=headers)
self.assertEqual('201 Created', resp.status)
def test_PUT_copy_with_storlets(self):
source = '/v1/AUTH_a/c/so'
target = '/v1/AUTH_a/c/to'
copy_from = 'c/so'
self.base_app.register('GET', source, HTTPOk, body='source body')
self.base_app.register('PUT', target, HTTPCreated)
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
headers = {'X-Copy-From': copy_from,
'X-Run-Storlet': 'Storlet-1.0.jar',
'X-Backend-Storage-Policy-Index': 0}
resp = self.get_request_response(target, 'PUT', headers=headers)
self.assertEqual('201 Created', resp.status)
get_calls = self.base_app.get_calls('GET', source)
self.assertEqual(len(get_calls), 1)
self.assertEqual(get_calls[-1][3], '')
self.assertEqual(get_calls[-1][1], source)
put_calls = self.base_app.get_calls('PUT', target)
self.assertEqual(len(put_calls), 1)
self.assertEqual(put_calls[-1][3], 'source body')
def test_COPY_verb_without_storlets(self):
source = '/v1/AUTH_a/c/so'
destination = 'c/to'
self.base_app.register('COPY', source, HTTPCreated)
headers = {'Destination': destination,
'X-Backend-Storage-Policy-Index': 0}
resp = self.get_request_response(source, 'COPY', headers=headers)
self.assertEqual('201 Created', resp.status)
def test_COPY_verb_with_storlets(self):
source = '/v1/AUTH_a/c/so'
target = '/v1/AUTH_a/c/to'
destination = 'c/to'
self.base_app.register('GET', source, HTTPOk, body='source body')
self.base_app.register('PUT', target, HTTPCreated)
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
with storlet_enabled():
headers = {'Destination': destination,
'X-Run-Storlet': 'Storlet-1.0.jar',
'X-Backend-Storage-Policy-Index': 0}
resp = self.get_request_response(source, 'COPY', headers=headers)
self.assertEqual('201 Created', resp.status)
get_calls = self.base_app.get_calls('GET', source)
self.assertEqual(len(get_calls), 1)
self.assertEqual(get_calls[-1][3], '')
self.assertEqual(get_calls[-1][1], source)
put_calls = self.base_app.get_calls('PUT', target)
self.assertEqual(len(put_calls), 1)
self.assertEqual(put_calls[-1][3], 'source body')
def test_copy_with_unsupported_headers(self):
target = '/v1/AUTH_a/c/o'
storlet = '/v1/AUTH_a/storlet/Storlet-1.0.jar'
self.base_app.register('GET', storlet, HTTPOk, body='jar binary')
def copy_400(method, copy_header):
base_headers = {'X-Run-Storlet': 'Storlet-1.0.jar',
'X-Backend-Storage-Policy-Index': 0}
base_headers.update(copy_header)
resp = self.get_request_response(target, method,
headers=base_headers)
self.assertEqual('400 Bad Request', resp.status)
cases = [('COPY', {'Destination-Account': 'a', 'Destination': 'c/o'}),
('COPY', {'X-Fresh-Metadata': '', 'Destination': 'c/o'}),
('PUT', {'X-Copy-From-Account': 'a', 'X-Copy-From': 'c/o'}),
('PUT', {'X-Fresh-Metadata': '', 'X-Copy-From': 'c/o'})]
for case in cases:
with storlet_enabled():
copy_400(case[0], case[1])
def test_PUT_storlet(self):
target = '/v1/AUTH_a/storlet/storlet-1.0.jar'
self.base_app.register('PUT', target, HTTPCreated)
with storlet_enabled():
sheaders = {'X-Object-Meta-Storlet-Language': 'Java',
'X-Object-Meta-Storlet-Interface-Version': '1.0',
'X-Object-Meta-Storlet-Dependency': 'dependency',
'X-Object-Meta-Storlet-Main':
'org.openstack.storlet.Storlet'}
resp = self.get_request_response(target, 'PUT', headers=sheaders)
self.assertEqual('201 Created', resp.status)
def test_PUT_storlet_mandatory_parameter_fails(self):
target = '/v1/AUTH_a/storlet/storlet-1.0.jar'
self.base_app.register('PUT', target, HTTPCreated)
drop_headers = [
('X-Object-Meta-Storlet-Language', 'Language'),
('X-Object-Meta-Storlet-Interface-Version', 'Interface-Version'),
('X-Object-Meta-Storlet-Dependency', 'Dependency'),
('X-Object-Meta-Storlet-Main', 'Main'),
]
def put(path, header, assertion):
sheaders = {'X-Object-Meta-Storlet-Language': 'Java',
'X-Object-Meta-Storlet-Interface-Version': '1.0',
'X-Object-Meta-Storlet-Dependency': 'dependency',
'X-Object-Meta-Storlet-Main':
'org.openstack.storlet.Storlet'}
del sheaders[header]
resp = self.get_request_response(path, 'PUT', headers=sheaders)
# FIXME(kota_): Unfortunately, we can not test yet here because
# the validation is not in stub gateway but in docker gateway so
# need more refactor to parse the functionality to be easy testing
# self.assertEqual('400 BadRequest', resp.status)
self.assertEqual('201 Created', resp.status)
for header, assertion in drop_headers:
with storlet_enabled():
put(target, header, assertion)
def test_POST_storlet(self):
target = '/v1/AUTH_a/storlet/storlet-1.0.jar'
self.base_app.register('POST', target, HTTPAccepted)
with storlet_enabled():
sheaders = {'X-Object-Meta-Storlet-Language': 'Java',
'X-Object-Meta-Storlet-Interface-Version': '1.0',
'X-Object-Meta-Storlet-Dependency': 'dependency',
'X-Object-Meta-Storlet-Main':
'org.openstack.storlet.Storlet'}
resp = self.get_request_response(target, 'POST', headers=sheaders)
self.assertEqual('202 Accepted', resp.status)
def test_GET_storlet(self):
target = '/v1/AUTH_a/storlet/storlet-1.0.jar'
sheaders = {'X-Object-Meta-Storlet-Language': 'Java',
'X-Object-Meta-Storlet-Interface-Version': '1.0',
'X-Object-Meta-Storlet-Dependency': 'dependency',
'X-Object-Meta-Storlet-Main':
'org.openstack.storlet.Storlet'}
self.base_app.register('GET', target, HTTPOk, headers=sheaders,
body='jar binary')
with storlet_enabled():
resp = self.get_request_response(target, 'GET')
self.assertEqual('200 OK', resp.status)
self.assertEqual('jar binary', resp.body)
for key in sheaders:
self.assertEqual(sheaders[key], resp.headers.get(key))
def test_PUT_dependency(self):
target = '/v1/AUTH_a/dependency/dependency'
self.base_app.register('PUT', target, HTTPCreated)
with storlet_enabled():
sheaders = {'X-Object-Meta-Storlet-Dependency-Version': '1',
'X-Object-Meta-Storlet-Dependency-Permissions': '0755'}
resp = self.get_request_response(target, 'PUT', headers=sheaders)
self.assertEqual('201 Created', resp.status)
def test_POST_dependency(self):
target = '/v1/AUTH_a/dependency/dependency'
self.base_app.register('POST', target, HTTPAccepted)
with storlet_enabled():
sheaders = {'X-Object-Meta-Storlet-Dependency-Version': '1',
'X-Object-Meta-Storlet-Dependency-Permissions': '0755'}
resp = self.get_request_response(target, 'POST', headers=sheaders)
self.assertEqual('202 Accepted', resp.status)
def test_GET_dependency(self):
target = '/v1/AUTH_a/dependency/dependency'
sheaders = {'X-Object-Meta-Storlet-Dependency-Version': '1',
'X-Object-Meta-Storlet-Dependency-Permissions': '0755'}
self.base_app.register('GET', target, HTTPOk, headers=sheaders,
body='FAKE APP')
with storlet_enabled():
resp = self.get_request_response(target, 'GET')
self.assertEqual('200 OK', resp.status)
self.assertEqual('FAKE APP', resp.body)
for key in sheaders:
self.assertEqual(sheaders[key], resp.headers.get(key))
def test_storlets_with_invalid_method(self):
with storlet_enabled():
headers = {'X-Run-Storlet': 'Storlet-1.0.jar'}
resp = self.get_request_response('/v1/AUTH_a/c/o',
'_parse_vaco',
headers=headers)
self.assertEqual('405 Method Not Allowed', resp.status)
def test_POST_storlet_acl_bad_request(self):
# Test wrong target elements
headers = {'X-Storlet-Container-Read': 'aa',
'X-Storlet-Name': 'bb'}
target = '/v1/AUTH_a/c/o'
self.base_app.register('POST', target, HTTPNoContent, body='')
with storlet_enabled():
resp = self.get_request_response(target, 'POST', headers=headers)
self.assertEqual('204 No Content', resp.status)
# Test wrong target containers
targets = ['/v1/AUTH_a/dependency/', '/v1/AUTH_a/storlet/']
with storlet_enabled():
for target in targets:
resp = self.get_request_response(target, 'POST',
headers=headers)
self.assertEqual('400 Bad Request', resp.status)
self.assertEqual(('storlet ACL update cannot be'
' a storlet container'),
resp.body)
# Test wrong headers content
hlist = [{'X-Storlet-Container-Read': ''},
{'X-Storlet-Container-Read': 'a'},
{'X-Storlet-Container-Read': 'a',
'X-Storlet-Name': ''}]
target = '/v1/AUTH_a/c/'
with storlet_enabled():
for headers in hlist:
resp = self.get_request_response(target, 'POST',
headers=headers)
self.assertEqual('400 Bad Request', resp.status)
self.assertTrue('missing a mandatory header' in resp.body)
# Test wrong ACL content
hlist = [{'X-Storlet-Container-Read': 'a,b',
'X-Storlet-Name': 'c'},
{'X-Storlet-Container-Read': 'a',
'X-Storlet-Name': 'b,c'}]
target = '/v1/AUTH_a/c/'
with storlet_enabled():
for headers in hlist:
resp = self.get_request_response(target, 'POST',
headers=headers)
self.assertEqual('400 Bad Request', resp.status)
self.assertTrue('mulformed storlet or user name' in resp.body)
def test_POST_storlet_acl(self):
target = '/v1/AUTH_a/c'
head_headers = {'x-container-read': 'adam'}
self.base_app.register('HEAD', target, HTTPNoContent, head_headers)
self.base_app.register('POST', target, HTTPNoContent)
headers = {'X-Storlet-Container-Read': 'a',
'X-Storlet-Name': 'b'}
expected_read_acl = 'adam,.r:storlets.a_b'
with storlet_enabled():
resp = self.get_request_response(target, 'POST', headers=headers)
self.assertEqual('204 No Content', resp.status)
head_calls = self.base_app.get_calls('HEAD', target)
self.assertEqual(len(head_calls), 1)
post_calls = self.base_app.get_calls('POST', target)
self.assertEqual(len(post_calls), 1)
self.assertEqual(post_calls[-1][2]['X-Container-Read'],
expected_read_acl)
def test_GET_with_invalid_referrer(self):
headers = [{'Referer': REFERER_PREFIX},
{'Referer': 'a.b.%s' % REFERER_PREFIX},
{'Referer': 'a.b.%s.c.d' % REFERER_PREFIX},
{'Referer': '//%s' % REFERER_PREFIX},
{'Referer': '%s.c.d' % REFERER_PREFIX}]
targets = ['/v1/AUTH_a/c', '/v1/AUTH_a/c/o']
ops = ['GET', 'HEAD']
for target, op, header in itertools.product(targets, ops, headers):
resp = self.get_request_response(target, op, headers=header)
self.assertEqual('403 Forbidden', resp.status)
class TestStorletProxyHandler(unittest.TestCase):
def setUp(self):
self.handler_class = StorletProxyHandler
self.conf = create_handler_config('proxy')
self.gateway_conf = {}
def test_init_handler(self):
req = Request.blank(
'/v1/acc/cont/obj', environ={'REQUEST_METHOD': 'GET'},
headers={'X-Backend-Storlet-Policy-Index': '0',
'X-Run-Storlet': 'Storlet-1.0.jar'})
with storlet_enabled():
handler = self.handler_class(
req, self.conf, self.gateway_conf,
mock.MagicMock(), mock.MagicMock())
self.assertEqual('/v1/acc/cont/obj', handler.request.path)
self.assertEqual('v1', handler.api_version)
self.assertEqual('acc', handler.account)
self.assertEqual('cont', handler.container)
self.assertEqual('obj', handler.obj)
# overwrite the request
# TODO(kota_): is it good to raise an error immediately?
# or re-validate the req again?
req = Request.blank(
'/v2/acc2/cont2/obj2', environ={'REQUEST_METHOD': 'GET'},
headers={'X-Backend-Storlet-Policy-Index': '0',
'X-Run-Storlet': 'Storlet-1.0.jar'})
handler.request = req
self.assertEqual('/v2/acc2/cont2/obj2', handler.request.path)
self.assertEqual('v2', handler.api_version)
self.assertEqual('acc2', handler.account)
self.assertEqual('cont2', handler.container)
self.assertEqual('obj2', handler.obj)
# no direct assignment allowed
with self.assertRaises(AttributeError):
handler.api_version = '1'
with self.assertRaises(AttributeError):
handler.account = 'acc'
with self.assertRaises(AttributeError):
handler.container = 'cont'
with self.assertRaises(AttributeError):
handler.obj = 'obj'
def test_remove_storlet_headers(self):
req = Request.blank(
'/v1/acc/cont/obj', environ={'REQUEST_METHOD': 'GET'},
headers={'X-Backend-Storlet-Policy-Index': '0',
'X-Run-Storlet': 'Storlet-1.0.jar'})
with storlet_enabled():
handler = self.handler_class(
req, self.conf, self.gateway_conf,
mock.MagicMock(), mock.MagicMock())
headers = {'X-Storlet-Key1': 'Value1',
'X-Key2': 'Value2',
'X-Object-Meta-Storlet-Key3': 'Value3',
'X-Object-Meta-Key4': 'Value4'}
handler._remove_storlet_headers(headers)
self.assertNotIn('X-Storlet-Key1', headers)
self.assertEqual(headers['X-Key2'], 'Value2')
self.assertNotIn('X-Object-Meta-Storlet-Key3', headers)
self.assertEqual(headers['X-Object-Meta-Key4'], 'Value4')
if __name__ == '__main__':
unittest.main()