From 5332ec9bb9d74a6c45ad134160d92b5dc33e6732 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 18 Feb 2015 09:48:34 -0800 Subject: [PATCH] Generalize compatibility testing This makes the test_obj_make_compatible() into a generalized thing that scans the object repository and makes sure that, for every version between X.0 and X.Y, obj.obj_make_compatible(target_version=version) works (i.e. doesn't raise an exception). Change-Id: I01efbf45d8df385bd245bee0c3cedc780fd4cd97 --- oslo_versionedobjects/checks.py | 25 +++++++++++ oslo_versionedobjects/tests/test_objects.py | 49 ++++++++++++++------- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/oslo_versionedobjects/checks.py b/oslo_versionedobjects/checks.py index 816859f8..b715eb82 100644 --- a/oslo_versionedobjects/checks.py +++ b/oslo_versionedobjects/checks.py @@ -12,15 +12,20 @@ import hashlib import inspect +import logging import mock import six import fixtures from oslo_serialization import jsonutils +from oslo_versionedobjects import _utils as utils from oslo_versionedobjects import base from oslo_versionedobjects import fields +LOG = logging.getLogger(__name__) + + class FakeIndirectionAPI(base.VersionedObjectIndirectionAPI): def __init__(self): super(FakeIndirectionAPI, self).__init__() @@ -190,3 +195,23 @@ class ObjectVersionChecker(object): actual[name] = actual_tree.get(name) return expected, actual + + def _test_object_compatibility(self, obj_class): + version = utils.convert_version_to_tuple(obj_class.VERSION) + for n in range(version[1] + 1): + test_version = '%d.%d' % (version[0], n) + LOG.info('testing obj: %s version: %s' % + (obj_class.obj_name(), test_version)) + obj_class().obj_to_primitive(target_version=test_version) + + def test_compatibility_routines(self): + # Iterate all object classes and verify that we can run + # obj_make_compatible with every older version than current. + # This doesn't actually test the data conversions, but it at least + # makes sure the method doesn't blow up on something basic like + # expecting the wrong version format. + all_obj_classes = base.VersionedObjectRegistry.obj_classes() + for obj_name in all_obj_classes: + obj_classes = base.VersionedObjectRegistry.obj_classes()[obj_name] + for obj_class in obj_classes: + self._test_object_compatibility(obj_class) diff --git a/oslo_versionedobjects/tests/test_objects.py b/oslo_versionedobjects/tests/test_objects.py index 51decd0d..3993a30d 100755 --- a/oslo_versionedobjects/tests/test_objects.py +++ b/oslo_versionedobjects/tests/test_objects.py @@ -430,6 +430,40 @@ class TestChecks(_BaseTestCase): self.assertEqual({'MyOwnedObject': '1.0'}, actual['TestSubclassedObject']) + def test_test_compatibility(self): + registry = base.VersionedObjectRegistry() + checker = checks.ObjectVersionChecker() + fake_classes = {mock.sentinel.class_one: [mock.sentinel.impl_one_one, + mock.sentinel.impl_one_two], + mock.sentinel.class_two: [mock.sentinel.impl_two_one, + mock.sentinel.impl_two_two], + } + + @mock.patch.object(checker, '_test_object_compatibility') + def test(mock_compat): + checker.test_compatibility_routines() + mock_compat.assert_has_calls( + [mock.call(mock.sentinel.impl_one_one), + mock.call(mock.sentinel.impl_one_two), + mock.call(mock.sentinel.impl_two_one), + mock.call(mock.sentinel.impl_two_two)], + any_order=True) + + with mock.patch.object(registry, '_obj_classes', new=fake_classes): + test() + + def test_test_compatibility_checks_obj_to_primitive(self): + fake = mock.MagicMock() + fake.VERSION = '1.3' + + checker = checks.ObjectVersionChecker() + checker._test_object_compatibility(fake) + fake().obj_to_primitive.assert_has_calls( + [mock.call(target_version='1.0'), + mock.call(target_version='1.1'), + mock.call(target_version='1.2'), + mock.call(target_version='1.3')]) + class _LocalTest(_BaseTestCase): def setUp(self): @@ -1126,21 +1160,6 @@ class TestObjectVersions(test.TestCase): def setUp(self): self.skip('disabled in the library for now') - def test_obj_make_compatible(self): - # Iterate all object classes and verify that we can run - # obj_make_compatible with every older version than current. - # This doesn't actually test the data conversions, but it at least - # makes sure the method doesn't blow up on something basic like - # expecting the wrong version format. - for obj_name in base.VersionedObjectRegistry.obj_classes(): - obj_class = base.VersionedObjectRegistry.obj_classes()[obj_name][0] - version = utils.convert_version_to_tuple(obj_class.VERSION) - for n in range(version[1]): - test_version = '%d.%d' % (version[0], n) - LOG.info('testing obj: %s version: %s' % - (obj_name, test_version)) - obj_class().obj_to_primitive(target_version=test_version) - def test_obj_relationships_in_order(self): # Iterate all object classes and verify that we can run # obj_make_compatible with every older version than current.