diff options
author | Ryan Rossiter <rlrossit@us.ibm.com> | 2016-01-14 00:21:02 +0000 |
---|---|---|
committer | Ryan Rossiter <rlrossit@us.ibm.com> | 2016-01-25 17:14:29 +0000 |
commit | 9a46586dcf96db567a999380dcaef02bdfd1592a (patch) | |
tree | 79386dff2fddb9f7106abeeb0245729cd0043d48 /nova/tests/unit/test_rpc.py | |
parent | c6c48b8bb78439059bdabed1c88902d4c6bfe48c (diff) | |
download | nova-9a46586dcf96db567a999380dcaef02bdfd1592a.tar.gz |
Add tests for nova.rpc module
This change adds test for the nova.rpc module, including the public
functions and 2 classes within the module.
Change-Id: I368ed5146210948c95de5a647097b98dcf8a3ca6
Closes-bug: #1533741
Diffstat (limited to 'nova/tests/unit/test_rpc.py')
-rw-r--r-- | nova/tests/unit/test_rpc.py | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/nova/tests/unit/test_rpc.py b/nova/tests/unit/test_rpc.py new file mode 100644 index 0000000000..e098ef1009 --- /dev/null +++ b/nova/tests/unit/test_rpc.py @@ -0,0 +1,322 @@ +# Copyright 2016 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 copy + +import fixtures +import mock +import oslo_messaging as messaging +from oslo_serialization import jsonutils +import testtools + +from nova import context +from nova import rpc +from nova import test + + +# Make a class that resets all of the global variables in nova.rpc +class RPCResetFixture(fixtures.Fixture): + def _setUp(self): + self.trans = copy.copy(rpc.TRANSPORT) + self.noti = copy.copy(rpc.NOTIFIER) + self.all_mods = copy.copy(rpc.ALLOWED_EXMODS) + self.ext_mods = copy.copy(rpc.EXTRA_EXMODS) + self.addCleanup(self._reset_everything) + + def _reset_everything(self): + rpc.TRANSPORT = self.trans + rpc.NOTIFIER = self.noti + rpc.ALLOWED_EXMODS = self.all_mods + rpc.EXTRA_EXMODS = self.ext_mods + + +# We can't import nova.test.TestCase because that sets up an RPCFixture +# that pretty much nullifies all of this testing +class TestRPC(testtools.TestCase): + def setUp(self): + super(TestRPC, self).setUp() + self.useFixture(RPCResetFixture()) + + @mock.patch.object(rpc, 'get_allowed_exmods') + @mock.patch.object(rpc, 'RequestContextSerializer') + @mock.patch.object(messaging, 'get_transport') + @mock.patch.object(messaging, 'Notifier') + def test_init_unversioned(self, mock_notif, mock_trans, mock_ser, + mock_exmods): + # The expected call to get the legacy notifier will require no new + # kwargs, and we expect the new notifier will need the noop driver + expected = [{}, {'driver': 'noop'}] + self._test_init(mock_notif, mock_trans, mock_ser, mock_exmods, + 'unversioned', expected) + + @mock.patch.object(rpc, 'get_allowed_exmods') + @mock.patch.object(rpc, 'RequestContextSerializer') + @mock.patch.object(messaging, 'get_transport') + @mock.patch.object(messaging, 'Notifier') + def test_init_both(self, mock_notif, mock_trans, mock_ser, mock_exmods): + expected = [{}, {'topic': 'versioned_notifications'}] + self._test_init(mock_notif, mock_trans, mock_ser, mock_exmods, + 'both', expected) + + @mock.patch.object(rpc, 'get_allowed_exmods') + @mock.patch.object(rpc, 'RequestContextSerializer') + @mock.patch.object(messaging, 'get_transport') + @mock.patch.object(messaging, 'Notifier') + def test_init_versioned(self, mock_notif, mock_trans, mock_ser, + mock_exmods): + expected = [{'driver': 'noop'}, {'topic': 'versioned_notifications'}] + self._test_init(mock_notif, mock_trans, mock_ser, mock_exmods, + 'versioned', expected) + + def test_cleanup_transport_null(self): + rpc.LEGACY_NOTIFIER = mock.Mock() + rpc.NOTIFIER = mock.Mock() + self.assertRaises(AssertionError, rpc.cleanup) + + def test_cleanup_legacy_notifier_null(self): + rpc.TRANSPORT = mock.Mock() + rpc.NOTIFIER = mock.Mock() + self.assertRaises(AssertionError, rpc.cleanup) + + def test_cleanup_notifier_null(self): + rpc.TRANSPORT = mock.Mock() + rpc.LEGACY_NOTIFIER = mock.Mock() + self.assertRaises(AssertionError, rpc.cleanup) + + def test_cleanup(self): + rpc.LEGACY_NOTIFIER = mock.Mock() + rpc.NOTIFIER = mock.Mock() + rpc.TRANSPORT = mock.Mock() + trans_cleanup = mock.Mock() + rpc.TRANSPORT.cleanup = trans_cleanup + + rpc.cleanup() + + trans_cleanup.assert_called_once_with() + self.assertIsNone(rpc.TRANSPORT) + self.assertIsNone(rpc.LEGACY_NOTIFIER) + self.assertIsNone(rpc.NOTIFIER) + + @mock.patch.object(messaging, 'set_transport_defaults') + def test_set_defaults(self, mock_set): + control_exchange = mock.Mock() + + rpc.set_defaults(control_exchange) + + mock_set.assert_called_once_with(control_exchange) + + def test_add_extra_exmods(self): + rpc.EXTRA_EXMODS = [] + + rpc.add_extra_exmods('foo', 'bar') + + self.assertEqual(['foo', 'bar'], rpc.EXTRA_EXMODS) + + def test_clear_extra_exmods(self): + rpc.EXTRA_EXMODS = ['foo', 'bar'] + + rpc.clear_extra_exmods() + + self.assertEqual(0, len(rpc.EXTRA_EXMODS)) + + def test_get_allowed_exmods(self): + rpc.ALLOWED_EXMODS = ['foo'] + rpc.EXTRA_EXMODS = ['bar'] + + exmods = rpc.get_allowed_exmods() + + self.assertEqual(['foo', 'bar'], exmods) + + @mock.patch.object(messaging, 'TransportURL') + def test_get_transport_url(self, mock_url): + conf = mock.Mock() + rpc.CONF = conf + mock_url.parse.return_value = 'foo' + + url = rpc.get_transport_url(url_str='bar') + + self.assertEqual('foo', url) + mock_url.parse.assert_called_once_with(conf, 'bar', + rpc.TRANSPORT_ALIASES) + + @mock.patch.object(messaging, 'TransportURL') + def test_get_transport_url_null(self, mock_url): + conf = mock.Mock() + rpc.CONF = conf + mock_url.parse.return_value = 'foo' + + url = rpc.get_transport_url() + + self.assertEqual('foo', url) + mock_url.parse.assert_called_once_with(conf, None, + rpc.TRANSPORT_ALIASES) + + @mock.patch.object(rpc, 'RequestContextSerializer') + @mock.patch.object(messaging, 'RPCClient') + def test_get_client(self, mock_client, mock_ser): + rpc.TRANSPORT = mock.Mock() + tgt = mock.Mock() + ser = mock.Mock() + mock_client.return_value = 'client' + mock_ser.return_value = ser + + client = rpc.get_client(tgt, version_cap='1.0', serializer='foo') + + mock_ser.assert_called_once_with('foo') + mock_client.assert_called_once_with(rpc.TRANSPORT, + tgt, version_cap='1.0', + serializer=ser) + self.assertEqual('client', client) + + @mock.patch.object(rpc, 'RequestContextSerializer') + @mock.patch.object(messaging, 'get_rpc_server') + def test_get_server(self, mock_get, mock_ser): + rpc.TRANSPORT = mock.Mock() + ser = mock.Mock() + tgt = mock.Mock() + ends = mock.Mock() + mock_ser.return_value = ser + mock_get.return_value = 'server' + + server = rpc.get_server(tgt, ends, serializer='foo') + + mock_ser.assert_called_once_with('foo') + mock_get.assert_called_once_with(rpc.TRANSPORT, tgt, ends, + executor='eventlet', serializer=ser) + self.assertEqual('server', server) + + def test_get_notifier(self): + rpc.LEGACY_NOTIFIER = mock.Mock() + mock_prep = mock.Mock() + mock_prep.return_value = 'notifier' + rpc.LEGACY_NOTIFIER.prepare = mock_prep + + notifier = rpc.get_notifier('service', publisher_id='foo') + + mock_prep.assert_called_once_with(publisher_id='foo') + self.assertEqual('notifier', notifier) + + def test_get_notifier_null_publisher(self): + rpc.LEGACY_NOTIFIER = mock.Mock() + mock_prep = mock.Mock() + mock_prep.return_value = 'notifier' + rpc.LEGACY_NOTIFIER.prepare = mock_prep + + notifier = rpc.get_notifier('service', host='bar') + + mock_prep.assert_called_once_with(publisher_id='service.bar') + self.assertEqual('notifier', notifier) + + def test_get_versioned_notifier(self): + rpc.NOTIFIER = mock.Mock() + mock_prep = mock.Mock() + mock_prep.return_value = 'notifier' + rpc.NOTIFIER.prepare = mock_prep + + notifier = rpc.get_versioned_notifier('service.foo') + + mock_prep.assert_called_once_with(publisher_id='service.foo') + self.assertEqual('notifier', notifier) + + def _test_init(self, mock_notif, mock_trans, mock_ser, mock_exmods, + notif_format, expected_driver_topic_kwargs): + legacy_notifier = mock.Mock() + notifier = mock.Mock() + transport = mock.Mock() + serializer = mock.Mock() + conf = mock.Mock() + + conf.notification_format = notif_format + mock_exmods.return_value = ['foo'] + mock_trans.return_value = transport + mock_ser.return_value = serializer + mock_notif.side_effect = [legacy_notifier, notifier] + + rpc.init(conf) + + mock_exmods.assert_called_once_with() + mock_trans.assert_called_once_with(conf, + allowed_remote_exmods=['foo'], + aliases=rpc.TRANSPORT_ALIASES) + self.assertIsNotNone(rpc.TRANSPORT) + self.assertIsNotNone(rpc.LEGACY_NOTIFIER) + self.assertIsNotNone(rpc.NOTIFIER) + self.assertEqual(legacy_notifier, rpc.LEGACY_NOTIFIER) + self.assertEqual(notifier, rpc.NOTIFIER) + + expected_calls = [] + for kwargs in expected_driver_topic_kwargs: + expected_kwargs = {'serializer': serializer} + expected_kwargs.update(kwargs) + expected_calls.append(((transport,), expected_kwargs)) + + self.assertEqual(expected_calls, mock_notif.call_args_list, + "The calls to messaging.Notifier() did not create " + "the legacy and versioned notifiers properly.") + + +class TestJsonPayloadSerializer(test.TestCase): + def test_serialize_entity(self): + with mock.patch.object(jsonutils, 'to_primitive') as mock_prim: + rpc.JsonPayloadSerializer.serialize_entity('context', 'entity') + + mock_prim.assert_called_once_with('entity', convert_instances=True) + + +class TestRequestContextSerializer(test.TestCase): + def setUp(self): + super(TestRequestContextSerializer, self).setUp() + self.mock_base = mock.Mock() + self.ser = rpc.RequestContextSerializer(self.mock_base) + self.ser_null = rpc.RequestContextSerializer(None) + + def test_serialize_entity(self): + self.mock_base.serialize_entity.return_value = 'foo' + + ser_ent = self.ser.serialize_entity('context', 'entity') + + self.mock_base.serialize_entity.assert_called_once_with('context', + 'entity') + self.assertEqual('foo', ser_ent) + + def test_serialize_entity_null_base(self): + ser_ent = self.ser_null.serialize_entity('context', 'entity') + + self.assertEqual('entity', ser_ent) + + def test_deserialize_entity(self): + self.mock_base.deserialize_entity.return_value = 'foo' + + deser_ent = self.ser.deserialize_entity('context', 'entity') + + self.mock_base.deserialize_entity.assert_called_once_with('context', + 'entity') + self.assertEqual('foo', deser_ent) + + def test_deserialize_entity_null_base(self): + deser_ent = self.ser_null.deserialize_entity('context', 'entity') + + self.assertEqual('entity', deser_ent) + + def test_serialize_context(self): + context = mock.Mock() + + self.ser.serialize_context(context) + + context.to_dict.assert_called_once_with() + + @mock.patch.object(context, 'RequestContext') + def test_deserialize_context(self, mock_req): + self.ser.deserialize_context('context') + + mock_req.from_dict.assert_called_once_with('context') |