summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Kölker <jason@koelker.net>2011-11-01 13:26:51 -0500
committerJason Kölker <jason@koelker.net>2011-11-01 13:26:51 -0500
commit12edc653f55015627b3f51dacf5c15e1d182da34 (patch)
tree577aa4a50fe0c2496d1a555e1a11075f3bc2de20
parent997c2e8eb0ade364a8920dd085ec0e24f56182fb (diff)
parent99b2c6c202b1ec450e5f7bc1c4080f8c36773376 (diff)
downloadoslo-12edc653f55015627b3f51dacf5c15e1d182da34.tar.gz
oslo-12edc653f55015627b3f51dacf5c15e1d182da34.tar.xz
oslo-12edc653f55015627b3f51dacf5c15e1d182da34.zip
Merge commit '99b2c6c202b1ec450e5f7bc1c4080f8c36773376'
-rw-r--r--.gitignore1
-rw-r--r--etc/openstack-common.conf.test3
-rw-r--r--openstack/common/extensions.py20
-rw-r--r--tests/unit/extensions/foxinsocks.py4
-rw-r--r--tests/unit/test_config.py66
-rw-r--r--tests/unit/test_extensions.py42
-rw-r--r--tests/unit/test_wsgi.py22
7 files changed, 128 insertions, 30 deletions
diff --git a/.gitignore b/.gitignore
index b6415a9..9b2c21f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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,