Added unittests for wsgi and api.

This commit is contained in:
Eric Day
2010-08-17 23:46:16 -07:00
parent 1e403e56dc
commit 67ea462ead
5 changed files with 224 additions and 15 deletions

View File

@@ -32,7 +32,6 @@ class API(wsgi.Router):
def __init__(self):
mapper = routes.Mapper()
mapper.connect(None, "/v1.0/{path_info:.*}",
controller=rackspace.API())
mapper.connect(None, "/ec2/{path_info:.*}", controller=ec2.API())
mapper.connect("/v1.0/{path_info:.*}", controller=rackspace.API())
mapper.connect("/ec2/{path_info:.*}", controller=ec2.API())
super(API, self).__init__(mapper)

70
nova/api/test.py Normal file
View File

@@ -0,0 +1,70 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 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.
"""
Test for the root WSGI middleware for all API controllers.
"""
import unittest
import stubout
from nova import api
from nova import wsgi_test
class Test(unittest.TestCase):
def setUp(self): # pylint: disable-msg=C0103
self.called = False
self.stubs = stubout.StubOutForTesting()
def tearDown(self): # pylint: disable-msg=C0103
self.stubs.UnsetAll()
def test_rackspace(self):
self.stubs.Set(api.rackspace, 'API', get_api_stub(self))
api.API()(wsgi_test.get_environ({'PATH_INFO': '/v1.0/cloud'}),
wsgi_test.start_response)
self.assertTrue(self.called)
def test_ec2(self):
self.stubs.Set(api.ec2, 'API', get_api_stub(self))
api.API()(wsgi_test.get_environ({'PATH_INFO': '/ec2/cloud'}),
wsgi_test.start_response)
self.assertTrue(self.called)
def test_not_found(self):
self.stubs.Set(api.ec2, 'API', get_api_stub(self))
self.stubs.Set(api.rackspace, 'API', get_api_stub(self))
api.API()(wsgi_test.get_environ({'PATH_INFO': '/'}),
wsgi_test.start_response)
self.assertFalse(self.called)
def get_api_stub(test_object):
"""Get a stub class that verifies next part of the request."""
class APIStub(object):
"""Class to verify request and mark it was called."""
test = test_object
def __call__(self, environ, start_response):
self.test.assertEqual(environ['PATH_INFO'], '/cloud')
self.test.called = True
return APIStub

View File

@@ -83,7 +83,7 @@ class Application(object):
raise NotImplementedError("You must implement __call__")
class Middleware(Application): # pylint: disable=W0223
class Middleware(Application):
"""
Base WSGI middleware wrapper. These classes require an application to be
initialized that will be called next. By default the middleware will
@@ -91,11 +91,11 @@ class Middleware(Application): # pylint: disable=W0223
behavior.
"""
def __init__(self, application): # pylint: disable=W0231
def __init__(self, application): # pylint: disable-msg=W0231
self.application = application
@webob.dec.wsgify
def __call__(self, req):
def __call__(self, req): # pylint: disable-msg=W0221
"""Override to implement middleware behavior."""
return self.application
@@ -113,7 +113,7 @@ class Debug(Middleware):
resp = req.get_response(self.application)
print ("*" * 40) + " RESPONSE HEADERS"
for (key, value) in resp.headers:
for (key, value) in resp.headers.iteritems():
print key, "=", value
print
@@ -127,7 +127,7 @@ class Debug(Middleware):
Iterator that prints the contents of a wrapper string iterator
when iterated.
"""
print ("*" * 40) + "BODY"
print ("*" * 40) + " BODY"
for part in app_iter:
sys.stdout.write(part)
sys.stdout.flush()
@@ -176,8 +176,9 @@ class Router(object):
"""
return self._router
@staticmethod
@webob.dec.wsgify
def _dispatch(self, req):
def _dispatch(req):
"""
Called by self._router after matching the incoming request to a route
and putting the information into req.environ. Either returns 404
@@ -197,6 +198,7 @@ class Controller(object):
must, in addition to their normal parameters, accept a 'req' argument
which is the incoming webob.Request.
"""
@webob.dec.wsgify
def __call__(self, req):
"""
@@ -249,6 +251,7 @@ class Serializer(object):
return repr(data)
def _to_xml_node(self, doc, metadata, nodename, data):
"""Recursive method to convert data members to XML nodes."""
result = doc.createElement(nodename)
if type(data) is list:
singular = metadata.get('plurals', {}).get(nodename, None)
@@ -262,7 +265,7 @@ class Serializer(object):
result.appendChild(node)
elif type(data) is dict:
attrs = metadata.get('attributes', {}).get(nodename, {})
for k,v in data.items():
for k, v in data.items():
if k in attrs:
result.setAttribute(k, str(v))
else:

133
nova/wsgi_test.py Normal file
View File

@@ -0,0 +1,133 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2010 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.
"""
Test WSGI basics and provide some helper functions for other WSGI tests.
"""
import unittest
import routes
from nova import wsgi
class Test(unittest.TestCase):
def setUp(self): # pylint: disable-msg=C0103
self.called = False
def test_debug(self):
class Application(wsgi.Application):
"""Dummy application to test debug."""
test = self
def __call__(self, environ, test_start_response):
test_start_response("200", [("X-Test", "checking")])
self.test.called = True
return ['Test response']
app = wsgi.Debug(Application())(get_environ(), start_response)
self.assertTrue(self.called)
for _ in app:
pass
def test_router(self):
class Application(wsgi.Application):
"""Test application to call from router."""
test = self
def __call__(self, environ, test_start_response):
test_start_response("200", [])
self.test.called = True
return []
class Router(wsgi.Router):
"""Test router."""
def __init__(self):
mapper = routes.Mapper()
mapper.connect("/test", controller=Application())
super(Router, self).__init__(mapper)
Router()(get_environ({'PATH_INFO': '/test'}), start_response)
self.assertTrue(self.called)
self.called = False
Router()(get_environ({'PATH_INFO': '/bad'}), start_response)
self.assertFalse(self.called)
def test_controller(self):
class Controller(wsgi.Controller):
"""Test controller to call from router."""
test = self
def show(self, **kwargs):
"""Mark that this has been called."""
self.test.called = True
self.test.assertEqual(kwargs['id'], '123')
return "Test"
class Router(wsgi.Router):
"""Test router."""
def __init__(self):
mapper = routes.Mapper()
mapper.resource("test", "tests", controller=Controller())
super(Router, self).__init__(mapper)
Router()(get_environ({'PATH_INFO': '/tests/123'}), start_response)
self.assertTrue(self.called)
self.called = False
Router()(get_environ({'PATH_INFO': '/test/123'}), start_response)
self.assertFalse(self.called)
def test_serializer(self):
# TODO(eday): Placeholder for serializer testing.
pass
def get_environ(overwrite={}): # pylint: disable-msg=W0102
"""Get a WSGI environment, overwriting any entries given."""
environ = {'SERVER_PROTOCOL': 'HTTP/1.1',
'GATEWAY_INTERFACE': 'CGI/1.1',
'wsgi.version': (1, 0),
'SERVER_PORT': '443',
'SERVER_NAME': '127.0.0.1',
'REMOTE_ADDR': '127.0.0.1',
'wsgi.run_once': False,
'wsgi.errors': None,
'wsgi.multiprocess': False,
'SCRIPT_NAME': '',
'wsgi.url_scheme': 'https',
'wsgi.input': None,
'REQUEST_METHOD': 'GET',
'PATH_INFO': '/',
'CONTENT_TYPE': 'text/plain',
'wsgi.multithread': True,
'QUERY_STRING': '',
'eventlet.input': None}
return dict(environ, **overwrite)
def start_response(_status, _headers):
"""Dummy start_response to use with WSGI tests."""
pass

View File

@@ -1,9 +1,7 @@
[Messages Control]
disable=C0103
# TODOs in code comments are fine...
disable=W0511
# *args and **kwargs are fine
disable=W0142
# W0511: TODOs in code comments are fine.
# W0142: *args and **kwargs are fine.
disable-msg=W0511,W0142
[Basic]
# Variables can be 1 to 31 characters long, with
@@ -14,6 +12,12 @@ variable-rgx=[a-z_][a-z0-9_]{0,30}$
# and be lowecased with underscores
method-rgx=[a-z_][a-z0-9_]{2,50}$
# Module names matching nova-* are ok (files in bin/)
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(nova-[a-z0-9_]+))$
# Don't require docstrings on tests.
no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$
[Design]
max-public-methods=100
min-public-methods=0