Add test for Neutron object versions
Adds a test to Neutron to check object versions for any changes to objects. It prompts the developer to update the version of the changed object. It uses oslo.versionedobjects. Change-Id: I99454b28ae0b5fa663354eeccdf709d4030a280b Co-Authored-By: Ryan Rossiter <rlrossit@us.ibm.com>
This commit is contained in:
parent
b01e3084d1
commit
074268f74c
@ -27,6 +27,8 @@ from neutron.objects.qos import rule as rule_obj_impl
|
|||||||
|
|
||||||
@obj_base.VersionedObjectRegistry.register
|
@obj_base.VersionedObjectRegistry.register
|
||||||
class QosPolicy(base.NeutronDbObject):
|
class QosPolicy(base.NeutronDbObject):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
db_model = qos_db_model.QosPolicy
|
db_model = qos_db_model.QosPolicy
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@ class QosRule(base.NeutronDbObject):
|
|||||||
|
|
||||||
@obj_base.VersionedObjectRegistry.register
|
@obj_base.VersionedObjectRegistry.register
|
||||||
class QosBandwidthLimitRule(QosRule):
|
class QosBandwidthLimitRule(QosRule):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
db_model = qos_db_model.QosBandwidthLimitRule
|
db_model = qos_db_model.QosBandwidthLimitRule
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ class RuleTypeField(obj_fields.BaseEnumField):
|
|||||||
|
|
||||||
@obj_base.VersionedObjectRegistry.register
|
@obj_base.VersionedObjectRegistry.register
|
||||||
class QosRuleType(base.NeutronObject):
|
class QosRuleType(base.NeutronObject):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'type': RuleTypeField(),
|
'type': RuleTypeField(),
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_versionedobjects import base as obj_base
|
from oslo_versionedobjects import base as obj_base
|
||||||
from oslo_versionedobjects import fields as obj_fields
|
from oslo_versionedobjects import fields as obj_fields
|
||||||
@ -38,8 +40,9 @@ def _create_test_resource(context=None):
|
|||||||
return resource
|
return resource
|
||||||
|
|
||||||
|
|
||||||
@obj_base.VersionedObjectRegistry.register
|
|
||||||
class FakeResource(objects_base.NeutronObject):
|
class FakeResource(objects_base.NeutronObject):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'id': obj_fields.UUIDField(),
|
'id': obj_fields.UUIDField(),
|
||||||
@ -55,8 +58,22 @@ class ResourcesRpcBaseTestCase(base.BaseTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ResourcesRpcBaseTestCase, self).setUp()
|
super(ResourcesRpcBaseTestCase, self).setUp()
|
||||||
|
|
||||||
|
# TODO(mhickey) This is using temp registry pattern. The
|
||||||
|
# pattern solution is to backup the object registry, register
|
||||||
|
# a class locally, and then restore the original registry.
|
||||||
|
# Refer to https://review.openstack.org/#/c/263800/ for more
|
||||||
|
# details. This code should be updated when the patch is merged.
|
||||||
|
self._base_test_backup = copy.copy(
|
||||||
|
obj_base.VersionedObjectRegistry._registry._obj_classes)
|
||||||
|
self.addCleanup(self._restore_obj_registry)
|
||||||
|
|
||||||
self.context = context.get_admin_context()
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
|
def _restore_obj_registry(self):
|
||||||
|
obj_base.VersionedObjectRegistry._registry._obj_classes = (
|
||||||
|
self._base_test_backup)
|
||||||
|
|
||||||
|
|
||||||
class _ValidateResourceTypeTestCase(base.BaseTestCase):
|
class _ValidateResourceTypeTestCase(base.BaseTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -103,6 +120,7 @@ class ResourcesPullRpcApiTestCase(ResourcesRpcBaseTestCase):
|
|||||||
self.assertIs(self.rpc, resources_rpc.ResourcesPullRpcApi())
|
self.assertIs(self.rpc, resources_rpc.ResourcesPullRpcApi())
|
||||||
|
|
||||||
def test_pull(self):
|
def test_pull(self):
|
||||||
|
obj_base.VersionedObjectRegistry.register(FakeResource)
|
||||||
expected_obj = _create_test_resource(self.context)
|
expected_obj = _create_test_resource(self.context)
|
||||||
resource_id = expected_obj.id
|
resource_id = expected_obj.id
|
||||||
self.cctxt_mock.call.return_value = expected_obj.obj_to_primitive()
|
self.cctxt_mock.call.return_value = expected_obj.obj_to_primitive()
|
||||||
@ -128,6 +146,7 @@ class ResourcesPullRpcCallbackTestCase(ResourcesRpcBaseTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ResourcesPullRpcCallbackTestCase, self).setUp()
|
super(ResourcesPullRpcCallbackTestCase, self).setUp()
|
||||||
|
obj_base.VersionedObjectRegistry.register(FakeResource)
|
||||||
self.callbacks = resources_rpc.ResourcesPullRpcCallback()
|
self.callbacks = resources_rpc.ResourcesPullRpcCallback()
|
||||||
self.resource_obj = _create_test_resource(self.context)
|
self.resource_obj = _create_test_resource(self.context)
|
||||||
|
|
||||||
@ -207,6 +226,7 @@ class ResourcesPushRpcCallbackTestCase(ResourcesRpcBaseTestCase):
|
|||||||
|
|
||||||
@mock.patch.object(resources_rpc.cons_registry, 'push')
|
@mock.patch.object(resources_rpc.cons_registry, 'push')
|
||||||
def test_push(self, reg_push_mock):
|
def test_push(self, reg_push_mock):
|
||||||
|
obj_base.VersionedObjectRegistry.register(FakeResource)
|
||||||
self.callbacks.push(self.context, self.resource_prim, 'TYPE')
|
self.callbacks.push(self.context, self.resource_prim, 'TYPE')
|
||||||
reg_push_mock.assert_called_once_with(self.resource_obj.obj_name(),
|
reg_push_mock.assert_called_once_with(self.resource_obj.obj_name(),
|
||||||
self.resource_obj, 'TYPE')
|
self.resource_obj, 'TYPE')
|
||||||
|
@ -36,8 +36,10 @@ class FakeModel(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@obj_base.VersionedObjectRegistry.register
|
@obj_base.VersionedObjectRegistry.register_if(False)
|
||||||
class FakeNeutronObject(base.NeutronDbObject):
|
class FakeNeutronObject(base.NeutronDbObject):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
db_model = FakeModel
|
db_model = FakeModel
|
||||||
|
|
||||||
|
48
neutron/tests/unit/objects/test_objects.py
Normal file
48
neutron/tests/unit/objects/test_objects.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Copyright 2015 IBM Corp.
|
||||||
|
#
|
||||||
|
# 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 os
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
from oslo_versionedobjects import base as obj_base
|
||||||
|
from oslo_versionedobjects import fixture
|
||||||
|
|
||||||
|
from neutron.tests import base as test_base
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: The hashes in this list should only be changed if they come with a
|
||||||
|
# corresponding version bump in the affected objects.
|
||||||
|
object_data = {
|
||||||
|
'QosBandwidthLimitRule': '1.0-4e44a8f5c2895ab1278399f87b40a13d',
|
||||||
|
'QosRuleType': '1.0-d0df298d49eeffab91af18d1a4cf7eaf',
|
||||||
|
'QosPolicy': '1.0-721fa60ea8f0e8f15d456d6e917dfe59',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestObjectVersions(test_base.BaseTestCase):
|
||||||
|
|
||||||
|
def test_versions(self):
|
||||||
|
checker = fixture.ObjectVersionChecker(
|
||||||
|
obj_base.VersionedObjectRegistry.obj_classes())
|
||||||
|
fingerprints = checker.get_hashes()
|
||||||
|
|
||||||
|
if os.getenv('GENERATE_HASHES'):
|
||||||
|
file('object_hashes.txt', 'w').write(
|
||||||
|
pprint.pformat(fingerprints))
|
||||||
|
|
||||||
|
expected, actual = checker.test_hashes(object_data)
|
||||||
|
self.assertEqual(expected, actual,
|
||||||
|
'Some objects have changed; please make sure the '
|
||||||
|
'versions have been bumped, and then update their '
|
||||||
|
'hashes in the object_data map in this test module.')
|
@ -14,6 +14,8 @@ ignore_regexes=(
|
|||||||
# The following vendor plugins are not required to confrm to the
|
# The following vendor plugins are not required to confrm to the
|
||||||
# structural requirements.
|
# structural requirements.
|
||||||
"^plugins/ibm.*$"
|
"^plugins/ibm.*$"
|
||||||
|
# The following test is required for oslo.versionedobjects
|
||||||
|
"^objects/test_objects.py$"
|
||||||
# The following open source plugin tests are not actually unit
|
# The following open source plugin tests are not actually unit
|
||||||
# tests and are ignored pending their relocation to the functional
|
# tests and are ignored pending their relocation to the functional
|
||||||
# test tree.
|
# test tree.
|
||||||
|
2
tox.ini
2
tox.ini
@ -5,7 +5,7 @@ skipsdist = True
|
|||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
setenv = VIRTUAL_ENV={envdir}
|
setenv = VIRTUAL_ENV={envdir}
|
||||||
passenv = TRACE_FAILONLY
|
passenv = TRACE_FAILONLY GENERATE_HASHES
|
||||||
usedevelop = True
|
usedevelop = True
|
||||||
install_command =
|
install_command =
|
||||||
constraints: {[testenv:common-constraints]install_command}
|
constraints: {[testenv:common-constraints]install_command}
|
||||||
|
Loading…
Reference in New Issue
Block a user