diff options
author | Jason Kölker <jason@koelker.net> | 2011-11-01 13:26:51 -0500 |
---|---|---|
committer | Jason Kölker <jason@koelker.net> | 2011-11-01 13:26:51 -0500 |
commit | 12edc653f55015627b3f51dacf5c15e1d182da34 (patch) | |
tree | 577aa4a50fe0c2496d1a555e1a11075f3bc2de20 | |
parent | 997c2e8eb0ade364a8920dd085ec0e24f56182fb (diff) | |
parent | 99b2c6c202b1ec450e5f7bc1c4080f8c36773376 (diff) | |
download | oslo-12edc653f55015627b3f51dacf5c15e1d182da34.tar.gz oslo-12edc653f55015627b3f51dacf5c15e1d182da34.tar.xz oslo-12edc653f55015627b3f51dacf5c15e1d182da34.zip |
Merge commit '99b2c6c202b1ec450e5f7bc1c4080f8c36773376'
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | etc/openstack-common.conf.test | 3 | ||||
-rw-r--r-- | openstack/common/extensions.py | 20 | ||||
-rw-r--r-- | tests/unit/extensions/foxinsocks.py | 4 | ||||
-rw-r--r-- | tests/unit/test_config.py | 66 | ||||
-rw-r--r-- | tests/unit/test_extensions.py | 42 | ||||
-rw-r--r-- | tests/unit/test_wsgi.py | 22 |
7 files changed, 128 insertions, 30 deletions
@@ -1,6 +1,7 @@ *.swp *.pyc *.log +.coverage .openstack-common-venv/ skeleton.egg-info/ build/ diff --git a/etc/openstack-common.conf.test b/etc/openstack-common.conf.test index 89bdf2d..4206bff 100644 --- a/etc/openstack-common.conf.test +++ b/etc/openstack-common.conf.test @@ -18,6 +18,9 @@ log_file = /tmp/openstack-common.log # Send logs to syslog (/dev/log) instead of to file specified by `log_file` use_syslog = False +# Path to the extensions +api_extensions_path = tests/unit/extensions + [pipeline:extensions_app_with_filter] pipeline = extensions extensions_test_app diff --git a/openstack/common/extensions.py b/openstack/common/extensions.py index d2fab36..162a02a 100644 --- a/openstack/common/extensions.py +++ b/openstack/common/extensions.py @@ -206,6 +206,13 @@ class ExtensionsResource(wsgi.Resource): class ExtensionMiddleware(wsgi.Middleware): """Extensions middleware for WSGI.""" + @classmethod + def factory(cls, global_config, **local_config): + """Paste factory.""" + def _factory(app): + return cls(app, global_config, **local_config) + return _factory + def _action_ext_resources(self, application, ext_mgr, mapper): """Return a dict of ActionExtensionResource-s by collection.""" action_resources = {} @@ -245,9 +252,9 @@ class ExtensionMiddleware(wsgi.Middleware): return request_ext_resources - def __init__(self, application, ext_mgr): - self.ext_mgr = ext_mgr - + def __init__(self, application, config, ext_mgr=None): + ext_mgr = ext_mgr or ExtensionManager( + config['api_extensions_path']) mapper = routes.Mapper() # extended resources @@ -493,15 +500,16 @@ class ResourceExtension(object): class ExtensionsXMLSerializer(wsgi.XMLDictSerializer): - NSMAP = {None: DEFAULT_XMLNS, 'atom': XMLNS_ATOM} + def __init__(self): + self.nsmap = {None: DEFAULT_XMLNS, 'atom': XMLNS_ATOM} def show(self, ext_dict): - ext = etree.Element('extension', nsmap=self.NSMAP) + ext = etree.Element('extension', nsmap=self.nsmap) self._populate_ext(ext, ext_dict['extension']) return self._to_xml(ext) def index(self, exts_dict): - exts = etree.Element('extensions', nsmap=self.NSMAP) + exts = etree.Element('extensions', nsmap=self.nsmap) for ext_dict in exts_dict['extensions']: ext = etree.SubElement(exts, 'extension') self._populate_ext(ext, ext_dict) diff --git a/tests/unit/extensions/foxinsocks.py b/tests/unit/extensions/foxinsocks.py index a0efd7e..b2fd656 100644 --- a/tests/unit/extensions/foxinsocks.py +++ b/tests/unit/extensions/foxinsocks.py @@ -18,7 +18,6 @@ import json from openstack.common import extensions -from openstack.common import wsgi class FoxInSocksController(object): @@ -26,9 +25,6 @@ class FoxInSocksController(object): def index(self, request): return "Try to say this Mr. Knox, sir..." - def create_resource(self): - return wsgi.Resource(self) - class Foxinsocks(object): diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py new file mode 100644 index 0000000..7555b44 --- /dev/null +++ b/tests/unit/test_config.py @@ -0,0 +1,66 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# 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. + +import optparse +import unittest + +from openstack.common import config + + +class TestConfig(unittest.TestCase): + + def test_common_options(self): + parser = optparse.OptionParser() + self.assertEquals(0, len(parser.option_groups)) + config.add_common_options(parser) + self.assertEquals(1, len(parser.option_groups)) + + expected_options = ['--verbose', '--debug', '--config-file'] + for e in expected_options: + self.assertTrue(parser.option_groups[0].get_option(e), + "Missing required common option: %s" % e) + + def test_parse_options(self): + # test empty args and that parse_options() returns a mapping + # of typed values + parser = optparse.OptionParser() + config.add_common_options(parser) + parsed_options, args = config.parse_options(parser, []) + + expected_options = {'verbose': False, 'debug': False, + 'config_file': None} + self.assertEquals(expected_options, parsed_options) + + # test non-empty args and that parse_options() returns a mapping + # of typed values matching supplied args + parser = optparse.OptionParser() + config.add_common_options(parser) + parsed_options, args = config.parse_options(parser, ['--verbose']) + + expected_options = {'verbose': True, 'debug': False, + 'config_file': None} + self.assertEquals(expected_options, parsed_options) + + # test non-empty args that contain unknown options raises + # a SystemExit exception. Not ideal, but unfortunately optparse + # raises a sys.exit() when it runs into an error instead of raising + # something a bit more useful for libraries. optparse must have been + # written by the same group that wrote unittest ;) + parser = optparse.OptionParser() + config.add_common_options(parser) + self.assertRaises(SystemExit, config.parse_options, + parser, ['--unknown']) diff --git a/tests/unit/test_extensions.py b/tests/unit/test_extensions.py index 841bf4d..fb5fdb1 100644 --- a/tests/unit/test_extensions.py +++ b/tests/unit/test_extensions.py @@ -19,22 +19,15 @@ from lxml import etree import os.path import routes import unittest - from webtest import TestApp - -from openstack.common import wsgi from openstack.common import config from openstack.common import extensions -from tests.unit.extension_stubs import (StubExtension, - StubBaseAppController) -from openstack.common.extensions import (ExtensionManager, - ExtensionMiddleware) - +from openstack.common import wsgi +from tests.unit import extension_stubs test_conf_file = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'etc', 'openstack-common.conf.test') -extensions_path = os.path.join(os.path.dirname(__file__), "extensions") NS = "{http://docs.openstack.org/}" ATOMNS = "{http://www.w3.org/2005/Atom}" @@ -44,7 +37,7 @@ class ExtensionsTestApp(wsgi.Router): def __init__(self, options={}): mapper = routes.Mapper() - controller = StubBaseAppController() + controller = extension_stubs.StubBaseAppController() mapper.resource("dummy_resource", "/dummy_resources", controller=controller.create_resource()) super(ExtensionsTestApp, self).__init__(mapper) @@ -296,9 +289,9 @@ class ExtensionManagerTest(unittest.TestCase): def get_alias(self): return "invalid_extension" - ext_mgr = ExtensionManager('') + ext_mgr = extensions.ExtensionManager('') ext_mgr.add_extension(InvalidExtension()) - ext_mgr.add_extension(StubExtension("valid_extension")) + ext_mgr.add_extension(extension_stubs.StubExtension("valid_extension")) self.assertTrue('valid_extension' in ext_mgr.extensions) self.assertFalse('invalid_extension' in ext_mgr.extensions) @@ -376,6 +369,27 @@ class ExtensionControllerTest(unittest.TestCase): 'The Fox In Socks Extension') +class DefaultXmlnsTest(unittest.TestCase): + + def setUp(self): + super(DefaultXmlnsTest, self).setUp() + self.original_default_xmlns = extensions.DEFAULT_XMLNS + extensions.DEFAULT_XMLNS = "http://blah" + self.test_app = setup_extensions_test_app() + + def test_default_xmlns_can_be_changed(self): + response = self.test_app.get("/extensions/FOXNSOX.xml") + self.assertEqual(200, response.status_int) + xml = response.body + + root = etree.XML(xml) + self.assertEqual(root.tag.split('extension')[0], "{http://blah}") + + def tearDown(self): + super(DefaultXmlnsTest, self).tearDown() + extensions.DEFAULT_XMLNS = self.original_default_xmlns + + class ExtensionsXMLSerializerTest(unittest.TestCase): def test_serialize_extenstion(self): @@ -467,11 +481,9 @@ def setup_base_app(): def setup_extensions_middleware(extension_manager=None): - extension_manager = (extension_manager or - ExtensionManager(extensions_path)) options = {'config_file': test_conf_file} conf, app = config.load_paste_app('extensions_test_app', options, None) - return ExtensionMiddleware(app, extension_manager) + return extensions.ExtensionMiddleware(app, conf, extension_manager) def setup_extensions_test_app(extension_manager=None): diff --git a/tests/unit/test_wsgi.py b/tests/unit/test_wsgi.py index 7a5eaa4..10af93c 100644 --- a/tests/unit/test_wsgi.py +++ b/tests/unit/test_wsgi.py @@ -275,7 +275,7 @@ class ResponseSerializerTest(unittest.TestCase): self.body_serializers = { 'application/json': JSONSerializer(), - 'application/XML': XMLSerializer(), + 'application/xml': XMLSerializer(), } self.serializer = wsgi.ResponseSerializer(self.body_serializers, @@ -294,12 +294,18 @@ class ResponseSerializerTest(unittest.TestCase): self.serializer.get_body_serializer, 'application/unknown') - def test_serialize_response(self): + def test_serialize_json_response(self): response = self.serializer.serialize({}, 'application/json') self.assertEqual(response.headers['Content-Type'], 'application/json') self.assertEqual(response.body, 'pew_json') self.assertEqual(response.status_int, 404) + def test_serialize_xml_response(self): + response = self.serializer.serialize({}, 'application/xml') + self.assertEqual(response.headers['Content-Type'], 'application/xml') + self.assertEqual(response.body, 'pew_xml') + self.assertEqual(response.status_int, 404) + def test_serialize_response_None(self): response = self.serializer.serialize(None, 'application/json') @@ -326,14 +332,20 @@ class RequestDeserializerTest(unittest.TestCase): self.body_deserializers = { 'application/json': JSONDeserializer(), - 'application/XML': XMLDeserializer(), + 'application/xml': XMLDeserializer(), } self.deserializer = wsgi.RequestDeserializer(self.body_deserializers) def test_get_deserializer(self): - expected = self.deserializer.get_body_deserializer('application/json') - self.assertEqual(expected, self.body_deserializers['application/json']) + expected_json_serializer = self.deserializer.get_body_deserializer( + 'application/json') + expected_xml_serializer = self.deserializer.get_body_deserializer( + 'application/xml') + self.assertEqual(expected_json_serializer, + self.body_deserializers['application/json']) + self.assertEqual(expected_xml_serializer, + self.body_deserializers['application/xml']) def test_get_deserializer_unknown_content_type(self): self.assertRaises(exception.InvalidContentType, |