Add ability to pass args/kwargs to obj_class init
Because some subobjects of VersionedObject my require arguments to be passed into __init__(), there needs to be a way for the test_compatibility_routines() fixture to pass required args/kwargs to init on certain objects. This change adds the ability to pass 2 mappings to test_compatibility_routines, one for args and one for kwargs. The key of each mapping is the object class that needs the special init args. The value in the args dict will be a list of arguments to pass (becomes *args), and the value in the kwargs dict is a list of kwargs to pass (becomes **kwargs). If there is no key defined, the default value of the args dict is [], and the default of kwargs is {}. *[] is the equivalent of sending no arguments, and **{} is the equivalent of not sending kwargs. Change-Id: I62646b99adca47a9c9fe0f466f7a23ac8fa4553e Related-Bug: #1537882
This commit is contained in:
parent
1249da8675
commit
905799e580
oslo_versionedobjects
@ -299,7 +299,10 @@ class ObjectVersionChecker(object):
|
||||
|
||||
return expected, actual
|
||||
|
||||
def _test_object_compatibility(self, obj_class, manifest=None):
|
||||
def _test_object_compatibility(self, obj_class, manifest=None,
|
||||
init_args=None, init_kwargs=None):
|
||||
init_args = init_args or []
|
||||
init_kwargs = init_kwargs or {}
|
||||
version = vutils.convert_version_to_tuple(obj_class.VERSION)
|
||||
kwargs = {'version_manifest': manifest} if manifest else {}
|
||||
for n in range(version[1] + 1):
|
||||
@ -307,14 +310,31 @@ class ObjectVersionChecker(object):
|
||||
LOG.info('testing obj: %s version: %s' %
|
||||
(obj_class.obj_name(), test_version))
|
||||
kwargs['target_version'] = test_version
|
||||
obj_class().obj_to_primitive(**kwargs)
|
||||
obj_class(*init_args, **init_kwargs).obj_to_primitive(**kwargs)
|
||||
|
||||
def test_compatibility_routines(self, use_manifest=False):
|
||||
def test_compatibility_routines(self, use_manifest=False, init_args=None,
|
||||
init_kwargs=None):
|
||||
"""Test obj_make_compatible() on all object classes.
|
||||
|
||||
:param use_manifest: a boolean that determines if the version
|
||||
manifest should be passed to obj_make_compatible
|
||||
:param init_args: a dictionary of the format {obj_class: [arg1, arg2]}
|
||||
that will be used to pass arguments to init on the
|
||||
given obj_class. If no args are needed, the
|
||||
obj_class does not need to be added to the dict
|
||||
:param init_kwargs: a dictionary of the format
|
||||
{obj_class: {'kwarg1': val1}} that will be used to
|
||||
pass kwargs to init on the given obj_class. If no
|
||||
kwargs are needed, the obj_class does not need to
|
||||
be added to the dict
|
||||
"""
|
||||
# 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.
|
||||
init_args = init_args or {}
|
||||
init_kwargs = init_kwargs or {}
|
||||
for obj_name in self.obj_classes:
|
||||
obj_classes = self.obj_classes[obj_name]
|
||||
if use_manifest:
|
||||
@ -323,7 +343,11 @@ class ObjectVersionChecker(object):
|
||||
manifest = None
|
||||
|
||||
for obj_class in obj_classes:
|
||||
self._test_object_compatibility(obj_class, manifest=manifest)
|
||||
args_for_init = init_args.get(obj_class, [])
|
||||
kwargs_for_init = init_kwargs.get(obj_class, {})
|
||||
self._test_object_compatibility(obj_class, manifest=manifest,
|
||||
init_args=args_for_init,
|
||||
init_kwargs=kwargs_for_init)
|
||||
|
||||
def _test_relationships_in_order(self, obj_class):
|
||||
for field, versions in obj_class.obj_relationships.items():
|
||||
|
@ -354,7 +354,8 @@ class TestObjectVersionChecker(test.TestCase):
|
||||
with mock.patch.object(self.ovc, '_test_object_compatibility') as toc:
|
||||
self.ovc.test_compatibility_routines()
|
||||
|
||||
toc.assert_called_once_with(MyObject, manifest=None)
|
||||
toc.assert_called_once_with(MyObject, manifest=None, init_args=[],
|
||||
init_kwargs={})
|
||||
|
||||
def test_test_compatibility_routines_with_manifest(self):
|
||||
# Make sure test_compatibility_routines() uses the version manifest
|
||||
@ -368,7 +369,21 @@ class TestObjectVersionChecker(test.TestCase):
|
||||
self.ovc.test_compatibility_routines(use_manifest=True)
|
||||
|
||||
otgv.assert_called_once_with(MyObject.__name__)
|
||||
toc.assert_called_once_with(MyObject, manifest=man)
|
||||
toc.assert_called_once_with(MyObject, manifest=man, init_args=[],
|
||||
init_kwargs={})
|
||||
|
||||
def test_test_compatibility_routines_with_args_kwargs(self):
|
||||
# Make sure test_compatibility_routines() uses init args/kwargs
|
||||
del self.ovc.obj_classes[MyObject2.__name__]
|
||||
init_args = {MyObject: [1]}
|
||||
init_kwargs = {MyObject: {'foo': 'bar'}}
|
||||
|
||||
with mock.patch.object(self.ovc, '_test_object_compatibility') as toc:
|
||||
self.ovc.test_compatibility_routines(init_args=init_args,
|
||||
init_kwargs=init_kwargs)
|
||||
|
||||
toc.assert_called_once_with(MyObject, manifest=None, init_args=[1],
|
||||
init_kwargs={'foo': 'bar'})
|
||||
|
||||
def test_test_relationships_in_order(self):
|
||||
# Make sure test_relationships_in_order() tests the relationships
|
||||
@ -547,6 +562,32 @@ class TestObjectVersionChecker(test.TestCase):
|
||||
"_test_object_compatibility() did not test "
|
||||
"obj_to_primitive() on the correct target versions")
|
||||
|
||||
def test_test_object_compatibility_args_kwargs(self):
|
||||
# Make sure _test_object_compatibility() tests obj_to_primitive()
|
||||
# with the correct args and kwargs to init
|
||||
to_prim = mock.MagicMock(spec=callable)
|
||||
MyObject.obj_to_primitive = to_prim
|
||||
MyObject.VERSION = '1.1'
|
||||
args = [1]
|
||||
kwargs = {'foo': 'bar'}
|
||||
|
||||
with mock.patch.object(MyObject, '__init__',
|
||||
return_value=None) as mock_init:
|
||||
self.ovc._test_object_compatibility(MyObject, init_args=args,
|
||||
init_kwargs=kwargs)
|
||||
|
||||
expected_init = ((1,), {'foo': 'bar'})
|
||||
expected_init_calls = [expected_init, expected_init]
|
||||
self.assertEqual(expected_init_calls, mock_init.call_args_list,
|
||||
"_test_object_compatibility() did not call "
|
||||
"__init__() properly on the object")
|
||||
|
||||
expected_to_prim = [((), {'target_version': '1.0'}),
|
||||
((), {'target_version': '1.1'})]
|
||||
self.assertEqual(expected_to_prim, to_prim.call_args_list,
|
||||
"_test_object_compatibility() did not test "
|
||||
"obj_to_primitive() on the correct target versions")
|
||||
|
||||
def _add_class(self, obj_classes, cls):
|
||||
obj_classes[cls.__name__] = [cls]
|
||||
|
||||
|
@ -596,10 +596,14 @@ class TestFixture(_BaseTestCase):
|
||||
def test(mock_compat):
|
||||
checker.test_compatibility_routines()
|
||||
mock_compat.assert_has_calls(
|
||||
[mock.call(mock.sentinel.impl_one_one, manifest=None),
|
||||
mock.call(mock.sentinel.impl_one_two, manifest=None),
|
||||
mock.call(mock.sentinel.impl_two_one, manifest=None),
|
||||
mock.call(mock.sentinel.impl_two_two, manifest=None)],
|
||||
[mock.call(mock.sentinel.impl_one_one, manifest=None,
|
||||
init_args=[], init_kwargs={}),
|
||||
mock.call(mock.sentinel.impl_one_two, manifest=None,
|
||||
init_args=[], init_kwargs={}),
|
||||
mock.call(mock.sentinel.impl_two_one, manifest=None,
|
||||
init_args=[], init_kwargs={}),
|
||||
mock.call(mock.sentinel.impl_two_two, manifest=None,
|
||||
init_args=[], init_kwargs={})],
|
||||
any_order=True)
|
||||
test()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user