diff --git a/cinder/tests/test_api_urlmap.py b/cinder/tests/test_api_urlmap.py new file mode 100644 index 00000000000..fb12eccd35a --- /dev/null +++ b/cinder/tests/test_api_urlmap.py @@ -0,0 +1,261 @@ +# Copyright (c) 2013 OpenStack Foundation +# All Rights Reserved. +# +# 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. + +""" +Tests for cinder.api.urlmap.py +""" + +from cinder.api import urlmap +from cinder import test + + +class TestParseFunctions(test.TestCase): + def test_unquote_header_value_without_quotes(self): + arg = 'TestString' + result = urlmap.unquote_header_value(arg) + self.assertEqual(result, arg) + + def test_unquote_header_value_with_quotes(self): + result = urlmap.unquote_header_value('"TestString"') + self.assertEqual(result, 'TestString') + + def test_parse_list_header(self): + arg = 'token, "quoted value"' + result = urlmap.parse_list_header(arg) + self.assertEqual(result, ['token', 'quoted value']) + + def test_parse_options_header(self): + result = urlmap.parse_options_header('Content-Type: text/html;' + ' mimetype=text/html') + self.assertEqual(result, ('Content-Type:', {'mimetype': 'text/html'})) + + def test_parse_options_header_without_value(self): + result = urlmap.parse_options_header(None) + self.assertEqual(result, ('', {})) + + +class TestAccept(test.TestCase): + def test_best_match_ValueError(self): + arg = 'text/html; q=some_invalud_value' + accept = urlmap.Accept(arg) + self.assertEqual(accept.best_match(['text/html']), (None, {})) + + def test_best_match(self): + arg = '*/*; q=0.7, application/json; q=0.7, text/html; q=-0.8' + accept = urlmap.Accept(arg) + self.assertEqual(accept.best_match(['application/json', + 'application/xml', 'text/html']), + ('application/json', {'q': '0.7'})) + + def test_match_mask_one_asterisk(self): + arg = 'text/*; q=0.7' + accept = urlmap.Accept(arg) + self.assertEqual(accept.best_match(['text/html']), + ('text/html', {'q': '0.7'})) + + def test_match_mask_two_asterisk(self): + arg = '*/*; q=0.7' + accept = urlmap.Accept(arg) + self.assertEqual(accept.best_match(['text/html']), + ('text/html', {'q': '0.7'})) + + def test_match_mask_no_asterisk(self): + arg = 'application/json; q=0.7' + accept = urlmap.Accept(arg) + self.assertEqual(accept.best_match(['text/html']), (None, {})) + + def test_content_type_params(self): + arg = "application/xml; q=0.1, application/json; q=0.2," \ + " text/html; q=0.3" + accept = urlmap.Accept(arg) + self.assertEqual(accept.content_type_params('application/json'), + {'q': '0.2'}) + + def test_content_type_params_wrong_content_type(self): + arg = 'application/xml; q=0.1, text/html; q=0.1' + accept = urlmap.Accept(arg) + self.assertEqual(accept.content_type_params('application/json'), {}) + + +class TestUrlMapFactory(test.TestCase): + def setUp(self): + super(TestUrlMapFactory, self).setUp() + self.global_conf = {'not_found_app': 'app_global', + 'domain hoobar.com port 10 /': 'some_app_global'} + self.loader = self.mox.CreateMockAnything() + + def test_not_found_app_in_local_conf(self): + local_conf = {'not_found_app': 'app_local', + 'domain foobar.com port 20 /': 'some_app_local'} + self.loader.get_app('app_local', global_conf=self.global_conf).\ + AndReturn('app_local_loader') + self.loader.get_app('some_app_local', global_conf=self.global_conf).\ + AndReturn('some_app_loader') + self.mox.ReplayAll() + expected_urlmap = urlmap.URLMap(not_found_app='app_local_loader') + expected_urlmap['http://foobar.com:20'] = 'some_app_loader' + self.assertEqual(urlmap.urlmap_factory(self.loader, self.global_conf, + **local_conf), expected_urlmap) + + def test_not_found_app_not_in_local_conf(self): + local_conf = {'domain foobar.com port 20 /': 'some_app_local'} + self.loader.get_app('app_global', global_conf=self.global_conf).\ + AndReturn('app_global_loader') + self.loader.get_app('some_app_local', global_conf=self.global_conf).\ + AndReturn('some_app_returned_by_loader') + self.mox.ReplayAll() + expected_urlmap = urlmap.URLMap(not_found_app='app_global_loader') + expected_urlmap['http://foobar.com:20'] = 'some_app_returned'\ + '_by_loader' + self.assertEqual(urlmap.urlmap_factory(self.loader, self.global_conf, + **local_conf), expected_urlmap) + + def test_not_found_app_is_none(self): + local_conf = {'not_found_app': None, + 'domain foobar.com port 20 /': 'some_app_local'} + self.loader.get_app('some_app_local', global_conf=self.global_conf).\ + AndReturn('some_app_returned_by_loader') + self.mox.ReplayAll() + expected_urlmap = urlmap.URLMap(not_found_app=None) + expected_urlmap['http://foobar.com:20'] = 'some_app_returned'\ + '_by_loader' + self.assertEqual(urlmap.urlmap_factory(self.loader, self.global_conf, + **local_conf), expected_urlmap) + + +class TestURLMap(test.TestCase): + def setUp(self): + super(TestURLMap, self).setUp() + self.urlmap = urlmap.URLMap() + self.input_environ = {'HTTP_ACCEPT': "application/json;" + "version=9.0", 'REQUEST_METHOD': "GET", + 'CONTENT_TYPE': 'application/xml', + 'SCRIPT_NAME': '/scriptname', + 'PATH_INFO': "/resource.xml"} + self.environ = {'HTTP_ACCEPT': "application/json;" + "version=9.0", 'REQUEST_METHOD': "GET", + 'CONTENT_TYPE': 'application/xml', + 'SCRIPT_NAME': '/scriptname/app_url', + 'PATH_INFO': "/resource.xml"} + + def test_match_with_applications(self): + self.urlmap[('http://10.20.30.40:50', '/path/somepath')] = 'app' + self.assertEqual(self.urlmap._match('20.30.40.50', '20', + 'path/somepath'), (None, None)) + + def test_match_without_applications(self): + self.assertEqual(self.urlmap._match('host', 20, 'app_url/somepath'), + (None, None)) + + def test_match_path_info_equals_app_url(self): + self.urlmap[('http://20.30.40.50:60', '/app_url/somepath')] = 'app' + self.assertEqual(self.urlmap._match('http://20.30.40.50', '60', + '/app_url/somepath'), + ('app', '/app_url/somepath')) + + def test_match_path_info_equals_app_url_many_app(self): + self.urlmap[('http://20.30.40.50:60', '/path')] = 'app1' + self.urlmap[('http://20.30.40.50:60', '/path/somepath')] = 'app2' + self.urlmap[('http://20.30.40.50:60', '/path/somepath/elsepath')] = \ + 'app3' + self.assertEqual(self.urlmap._match('http://20.30.40.50', '60', + '/path/somepath/elsepath'), + ('app3', '/path/somepath/elsepath')) + + def test_set_script_name(self): + app = self.mox.CreateMockAnything() + start_response = self.mox.CreateMockAnything() + app.__call__(self.environ, start_response).AndReturn('value') + self.mox.ReplayAll() + wrap = self.urlmap._set_script_name(app, '/app_url') + self.assertEqual(wrap(self.input_environ, start_response), 'value') + + def test_munge_path(self): + app = self.mox.CreateMockAnything() + start_response = self.mox.CreateMockAnything() + app.__call__(self.environ, start_response).AndReturn('value') + self.mox.ReplayAll() + wrap = self.urlmap._munge_path(app, '/app_url/resource.xml', + '/app_url') + self.assertEqual(wrap(self.input_environ, start_response), 'value') + + def test_content_type_strategy_without_version(self): + self.assertEqual(self.urlmap._content_type_strategy('host', 20, + self.environ), + None) + + def test_content_type_strategy_with_version(self): + environ = {'HTTP_ACCEPT': "application/vnd.openstack.melange+xml;" + "version=9.0", 'REQUEST_METHOD': "GET", + 'PATH_INFO': "/resource.xml", + 'CONTENT_TYPE': 'application/xml; version=2.0'} + self.urlmap[('http://10.20.30.40:50', '/v2.0')] = 'app' + self.mox.StubOutWithMock(self.urlmap, '_set_script_name') + self.urlmap._set_script_name('app', '/v2.0').AndReturn('value') + self.mox.ReplayAll() + self.assertEqual(self.urlmap._content_type_strategy( + 'http://10.20.30.40', '50', environ), 'value') + + def test_path_strategy_wrong_path_info(self): + self.assertEqual(self.urlmap._path_strategy('http://10.20.30.40', '50', + '/resource'), + (None, None, None)) + + def test_path_strategy_mime_type_only(self): + self.assertEqual(self.urlmap._path_strategy('http://10.20.30.40', '50', + '/resource.xml'), + ('application/xml', None, None)) + + def test_path_strategy(self): + self.urlmap[('http://10.20.30.40:50', '/path/elsepath/')] = 'app' + self.mox.StubOutWithMock(self.urlmap, '_munge_path') + self.urlmap._munge_path('app', '/path/elsepath/resource.xml', + '/path/elsepath').AndReturn('value') + self.mox.ReplayAll() + self.assertEqual(self.urlmap._path_strategy( + 'http://10.20.30.40', '50', '/path/elsepath/resource.xml'), + ('application/xml', 'value', '/path/elsepath')) + + def test_path_strategy_wrong_mime_type(self): + self.urlmap[('http://10.20.30.40:50', '/path/elsepath/')] = 'app' + self.mox.StubOutWithMock(self.urlmap, '_munge_path') + self.urlmap._munge_path('app', '/path/elsepath/resource.abc', + '/path/elsepath').AndReturn('value') + self.mox.ReplayAll() + self.assertEqual(self.urlmap._path_strategy( + 'http://10.20.30.40', '50', '/path/elsepath/resource.abc'), + (None, 'value', '/path/elsepath')) + + def test_accept_strategy_version_not_in_params(self): + environ = {'HTTP_ACCEPT': "application/xml; q=0.1, application/json; " + "q=0.2", 'REQUEST_METHOD': "GET", + 'PATH_INFO': "/resource.xml", + 'CONTENT_TYPE': 'application/xml; version=2.0'} + self.assertEqual(self.urlmap._accept_strategy( + 'http://10.20.30.40', '50', environ, ['application/xml']), + ('application/xml', None)) + + def test_accept_strategy_version(self): + environ = {'HTTP_ACCEPT': "application/xml; q=0.1; version=1.0," + "application/json; q=0.2; version=2.0", + 'REQUEST_METHOD': "GET", 'PATH_INFO': "/resource.xml", + 'CONTENT_TYPE': 'application/xml; version=2.0'} + self.urlmap[('http://10.20.30.40:50', '/v1.0')] = 'app' + self.mox.StubOutWithMock(self.urlmap, '_set_script_name') + self.urlmap._set_script_name('app', '/v1.0').AndReturn('value') + self.mox.ReplayAll() + self.assertEqual(self.urlmap._accept_strategy( + 'http://10.20.30.40', '50', environ, ['application/xml']), + ('application/xml', 'value'))