From d8928e4a7ca59fb153967ef436962a4658975129 Mon Sep 17 00:00:00 2001 From: He Jie Xu Date: Wed, 19 Jul 2017 15:02:29 +0800 Subject: [PATCH] Using plain routes for the microversions test Few microversions unittest still depend on the stevedore to load few fake controller. This patch uses the plain routes to instead of stevedore. For the unittest can injects routes which are used for test, the `custom_routes` parameter is added to the APIRouterV21. Partial-implement-blueprint api-no-more-extensions-pike Change-Id: I1a7c653ab21be41b1a41f748a35ec9a57dd8b15d --- nova/api/openstack/compute/routes.py | 11 +- .../api/openstack/compute/microversions.py | 82 +++++++----- .../openstack/compute/test_microversions.py | 123 ++++++------------ nova/tests/unit/api/openstack/fakes.py | 5 +- setup.cfg | 3 - 5 files changed, 100 insertions(+), 124 deletions(-) diff --git a/nova/api/openstack/compute/routes.py b/nova/api/openstack/compute/routes.py index d21e6314849..6570bd80fc2 100644 --- a/nova/api/openstack/compute/routes.py +++ b/nova/api/openstack/compute/routes.py @@ -877,11 +877,18 @@ class APIRouterV21(nova.api.openstack.APIRouterV21): and method. The URL mapping based on the plain list `ROUTE_LIST` is built at here. The stevedore based API loading will be replaced by this. """ - def __init__(self): + def __init__(self, custom_routes=None): + """:param custom_routes: the additional routes can be added by this + parameter. This parameter is used to test on some fake routes + primarily. + """ self._loaded_extension_info = extension_info.LoadedExtensionInfo() super(APIRouterV21, self).__init__() - for path, methods in ROUTE_LIST: + if custom_routes is None: + custom_routes = tuple() + + for path, methods in ROUTE_LIST + custom_routes: # NOTE(alex_xu): The variable 'methods' is a dict in normal, since # the dict includes all the methods supported in the path. But # if the variable 'method' is a string, it means a redirection. diff --git a/nova/tests/unit/api/openstack/compute/microversions.py b/nova/tests/unit/api/openstack/compute/microversions.py index 89f720d97ff..862be55d0d8 100644 --- a/nova/tests/unit/api/openstack/compute/microversions.py +++ b/nova/tests/unit/api/openstack/compute/microversions.py @@ -13,16 +13,15 @@ # under the License. """Microversions Test Extension""" +import functools import webob -from nova.api.openstack import extensions +from nova.api.openstack.compute import routes from nova.api.openstack import wsgi from nova.api import validation from nova.tests.unit.api.openstack.compute import dummy_schema -ALIAS = 'test-microversions' - class MicroversionsController(wsgi.Controller): @@ -124,32 +123,51 @@ def show(self, req, resp_obj, id): resp_obj.obj['extend_ctrlr3'] = 'val_3' -class Microversions(extensions.V21APIExtensionBase): - """Basic Microversions Extension.""" - - name = "Microversions" - alias = ALIAS - version = 1 - - def get_resources(self): - res1 = extensions.ResourceExtension('microversions', - MicroversionsController()) - res2 = extensions.ResourceExtension('microversions2', - MicroversionsController2()) - res3 = extensions.ResourceExtension('microversions3', - MicroversionsController3(), - member_actions={"action": "POST"}) - res4 = extensions.ResourceExtension('microversions4', - MicroversionsController4()) - res5 = extensions.ResourceExtension( - 'microversions5', MicroversionsExtendsBaseController()) - return [res1, res2, res3, res4, res5] - - def get_controller_extensions(self): - extension1 = extensions.ControllerExtension( - self, 'microversions5', MicroversionsExtendsController1()) - extension2 = extensions.ControllerExtension( - self, 'microversions5', MicroversionsExtendsController2()) - extension3 = extensions.ControllerExtension( - self, 'microversions5', MicroversionsExtendsController3()) - return [extension1, extension2, extension3] +mv_controller = functools.partial(routes._create_controller, + MicroversionsController, [], []) + + +mv2_controller = functools.partial(routes._create_controller, + MicroversionsController2, [], []) + + +mv3_controller = functools.partial(routes._create_controller, + MicroversionsController3, [], []) + + +mv4_controller = functools.partial(routes._create_controller, + MicroversionsController4, [], []) + + +mv5_controller = functools.partial(routes._create_controller, + MicroversionsExtendsBaseController, + [ + MicroversionsExtendsController1, + MicroversionsExtendsController2, + MicroversionsExtendsController3 + ], []) + + +ROUTES = ( + ('/microversions', { + 'GET': [mv_controller, 'index'] + }), + ('/microversions2', { + 'GET': [mv2_controller, 'index'] + }), + ('/microversions3', { + 'POST': [mv3_controller, 'create'] + }), + ('/microversions3/{id}', { + 'PUT': [mv3_controller, 'update'] + }), + ('/microversions3/{id}/action', { + 'POST': [mv3_controller, 'action'] + }), + ('/microversions4', { + 'POST': [mv4_controller, 'create'] + }), + ('/microversions5/{id}', { + 'GET': [mv5_controller, 'show'] + }), +) diff --git a/nova/tests/unit/api/openstack/compute/test_microversions.py b/nova/tests/unit/api/openstack/compute/test_microversions.py index 7405252e5ef..104c5eb4e29 100644 --- a/nova/tests/unit/api/openstack/compute/test_microversions.py +++ b/nova/tests/unit/api/openstack/compute/test_microversions.py @@ -17,6 +17,7 @@ from nova.api.openstack import api_version_request as api_version from nova import test +from nova.tests.unit.api.openstack.compute import microversions from nova.tests.unit.api.openstack import fakes @@ -24,6 +25,10 @@ class LegacyMicroversionsTest(test.NoDBTestCase): header_name = 'X-OpenStack-Nova-API-Version' + def setUp(self): + super(LegacyMicroversionsTest, self).setUp() + self.app = fakes.wsgi_app_v21(custom_routes=microversions.ROUTES) + def _test_microversions(self, app, req, ret_code, ret_header=None): req.environ['CONTENT_TYPE'] = "application/json" @@ -43,22 +48,16 @@ def _make_header(self, req_header): headers = {self.header_name: 'compute %s' % req_header} return headers - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_no_header(self, mock_namespace): - app = fakes.wsgi_app_v21() - req = fakes.HTTPRequest.blank('/v2/fake/microversions') - res = req.get_response(app) + def test_microversions_no_header(self): + req = fakes.HTTPRequest.blank('/v2/fake/microversions', method='GET') + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual('val', resp_json['param']) - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_return_header(self, mock_namespace): - app = fakes.wsgi_app_v21() + def test_microversions_return_header(self): req = fakes.HTTPRequest.blank('/v2/fake/microversions') - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual('val', resp_json['param']) @@ -69,16 +68,13 @@ def test_microversions_return_header(self, mock_namespace): self.assertIn(self.header_name, res.headers.getall('Vary')) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_return_header_non_default(self, mock_namespace, - mock_maxver): + def test_microversions_return_header_non_default(self, + mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("2.3") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions') req.headers = self._make_header('2.3') - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual('val2', resp_json['param']) @@ -89,16 +85,12 @@ def test_microversions_return_header_non_default(self, mock_namespace, self.assertIn(self.header_name, res.headers.getall('Vary')) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_return_header_fault(self, mock_namespace, - mock_maxver): + def test_microversions_return_header_fault(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.0") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions') req.headers = self._make_header('3.0') - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(400, res.status_int) if 'nova' in self.header_name.lower(): self.assertEqual("3.0", res.headers[self.header_name]) @@ -107,16 +99,13 @@ def test_microversions_return_header_fault(self, mock_namespace, self.assertIn(self.header_name, res.headers.getall('Vary')) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') def _check_microversion_response(self, url, req_version, resp_param, - mock_namespace, mock_maxver): + mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest('2.3') - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank(url) req.headers = self._make_header(req_version) - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual(resp_param, resp_json['param']) @@ -134,52 +123,39 @@ def test_microversions2_no_2_1_version(self): '2.3', 'controller2_val1') @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions2_later_version(self, mock_namespace, mock_maxver): + def test_microversions2_later_version(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.1") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions2') req.headers = self._make_header('3.0') - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(202, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual('controller2_val2', resp_json['param']) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions2_version_too_high(self, mock_namespace, - mock_maxver): + def test_microversions2_version_too_high(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.5") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions2') req.headers = {self.header_name: '3.2'} - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(404, res.status_int) - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions2_version_too_low(self, mock_namespace): - app = fakes.wsgi_app_v21() + def test_microversions2_version_too_low(self): req = fakes.HTTPRequest.blank('/v2/fake/microversions2') req.headers = {self.header_name: '2.1'} - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(404, res.status_int) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_global_version_too_high(self, mock_namespace, + def test_microversions_global_version_too_high(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.5") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions2') req.headers = self._make_header('3.7') - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(406, res.status_int) res_json = jsonutils.loads(res.body) self.assertEqual("Version 3.7 is not supported by the API. " @@ -187,19 +163,16 @@ def test_microversions_global_version_too_high(self, mock_namespace, res_json['computeFault']['message']) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_schema(self, mock_namespace, mock_maxver): + def test_microversions_schema(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.3") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions3') req.method = 'POST' req.headers = self._make_header('2.2') req.environ['CONTENT_TYPE'] = "application/json" req.body = jsonutils.dump_as_bytes({'dummy': {'val': 'foo'}}) - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual('create_val1', resp_json['param']) @@ -210,39 +183,33 @@ def test_microversions_schema(self, mock_namespace, mock_maxver): self.assertIn(self.header_name, res.headers.getall('Vary')) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_schema_fail(self, mock_namespace, mock_maxver): + def test_microversions_schema_fail(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.3") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions3') req.method = 'POST' req.headers = {self.header_name: '2.2'} req.environ['CONTENT_TYPE'] = "application/json" req.body = jsonutils.dump_as_bytes({'dummy': {'invalid_param': 'foo'}}) - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(400, res.status_int) resp_json = jsonutils.loads(res.body) self.assertTrue(resp_json['badRequest']['message'].startswith( "Invalid input for field/attribute dummy.")) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_schema_out_of_version_check(self, mock_namespace, + def test_microversions_schema_out_of_version_check(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.3") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions3/1') req.method = 'PUT' req.headers = self._make_header('2.2') req.body = jsonutils.dump_as_bytes({'dummy': {'inv_val': 'foo'}}) req.environ['CONTENT_TYPE'] = "application/json" - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual('update_val1', resp_json['param']) @@ -252,20 +219,17 @@ def test_microversions_schema_out_of_version_check(self, mock_namespace, self.assertEqual("compute 2.2", res.headers[self.header_name]) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_microversions_schema_second_version(self, mock_namespace, - mock_maxver): + def test_microversions_schema_second_version(self, + mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("3.3") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions3/1') req.headers = self._make_header('2.10') req.environ['CONTENT_TYPE'] = "application/json" req.method = 'PUT' req.body = jsonutils.dump_as_bytes({'dummy': {'val2': 'foo'}}) - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual('update_val1', resp_json['param']) @@ -275,20 +239,16 @@ def test_microversions_schema_second_version(self, mock_namespace, self.assertEqual("compute 2.10", res.headers[self.header_name]) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') def _test_microversions_inner_function(self, version, expected_resp, - mock_namespace, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("2.2") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions4') req.headers = self._make_header(version) req.environ['CONTENT_TYPE'] = "application/json" req.method = 'POST' req.body = b'' - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) resp_json = jsonutils.loads(res.body) self.assertEqual(expected_resp, resp_json['param']) @@ -303,15 +263,12 @@ def test_microversions_inner_function_v21(self): self._test_microversions_inner_function('2.1', 'controller4_val1') @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') - def test_with_extends_decorator(self, mock_namespace, mock_maxver): + def test_with_extends_decorator(self, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest('2.4') - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions5/item') req.headers = {'X-OpenStack-Nova-API-Version': '2.4'} - res = req.get_response(app) + res = req.get_response(self.app) self.assertEqual(200, res.status_int) expected_res = { @@ -326,21 +283,17 @@ def test_with_extends_decorator(self, mock_namespace, mock_maxver): self.assertEqual(3, len(resp_json)) @mock.patch("nova.api.openstack.api_version_request.max_api_version") - @mock.patch("nova.api.openstack.APIRouterV21.api_extension_namespace", - return_value='nova.api.v21.test_extensions') def _test_microversions_actions(self, ret_code, ret_header, req_header, - mock_namespace, mock_maxver): mock_maxver.return_value = api_version.APIVersionRequest("2.3") - app = fakes.wsgi_app_v21() req = fakes.HTTPRequest.blank('/v2/fake/microversions3/1/action') if req_header: req.headers = self._make_header(req_header) req.method = 'POST' req.body = jsonutils.dump_as_bytes({'foo': None}) - res = self._test_microversions(app, req, ret_code, + res = self._test_microversions(self.app, req, ret_code, ret_header=ret_header) if ret_code == 202: resp_json = jsonutils.loads(res.body) diff --git a/nova/tests/unit/api/openstack/fakes.py b/nova/tests/unit/api/openstack/fakes.py index 74c3f26955d..8167b34e2a3 100644 --- a/nova/tests/unit/api/openstack/fakes.py +++ b/nova/tests/unit/api/openstack/fakes.py @@ -63,9 +63,10 @@ def fake_wsgi(self, req): return self.application -def wsgi_app_v21(fake_auth_context=None, v2_compatible=False): +def wsgi_app_v21(fake_auth_context=None, v2_compatible=False, + custom_routes=None): - inner_app_v21 = compute.APIRouterV21() + inner_app_v21 = compute.APIRouterV21(custom_routes=custom_routes) if v2_compatible: inner_app_v21 = openstack_api.LegacyV2CompatibleWrapper(inner_app_v21) diff --git a/setup.cfg b/setup.cfg index 73768fa9d19..b02cec4f376 100644 --- a/setup.cfg +++ b/setup.cfg @@ -73,9 +73,6 @@ wsgi_scripts = nova-api-wsgi = nova.api.openstack.compute.wsgi:init_application nova-metadata-wsgi = nova.api.metadata.wsgi:init_application -nova.api.v21.test_extensions = - microversions = nova.tests.unit.api.openstack.compute.microversions:Microversions - nova.ipv6_backend = rfc2462 = nova.ipv6.rfc2462 account_identifier = nova.ipv6.account_identifier