# Copyright 2013 Red Hat, Inc. # # 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 testscenarios from oslo import messaging from oslo.messaging import exceptions from oslo.messaging import serializer as msg_serializer from oslo_config import cfg from oslo_messaging.tests import utils as test_utils load_tests = testscenarios.load_tests_apply_scenarios class _FakeTransport(object): def __init__(self, conf): self.conf = conf def _send(self, *args, **kwargs): pass class TestCastCall(test_utils.BaseTestCase): scenarios = [ ('cast_no_ctxt_no_args', dict(call=False, ctxt={}, args={})), ('call_no_ctxt_no_args', dict(call=True, ctxt={}, args={})), ('cast_ctxt_and_args', dict(call=False, ctxt=dict(user='testuser', project='testtenant'), args=dict(bar='blaa', foobar=11.01))), ('call_ctxt_and_args', dict(call=True, ctxt=dict(user='testuser', project='testtenant'), args=dict(bar='blaa', foobar=11.01))), ] def test_cast_call(self): self.config(rpc_response_timeout=None) transport = _FakeTransport(self.conf) client = messaging.RPCClient(transport, messaging.Target()) self.mox.StubOutWithMock(transport, '_send') msg = dict(method='foo', args=self.args) kwargs = {'retry': None} if self.call: kwargs['wait_for_reply'] = True kwargs['timeout'] = None transport._send(messaging.Target(), self.ctxt, msg, **kwargs) self.mox.ReplayAll() method = client.call if self.call else client.cast method(self.ctxt, 'foo', **self.args) class TestCastToTarget(test_utils.BaseTestCase): _base = [ ('all_none', dict(ctor={}, prepare={}, expect={})), ('ctor_exchange', dict(ctor=dict(exchange='testexchange'), prepare={}, expect=dict(exchange='testexchange'))), ('prepare_exchange', dict(ctor={}, prepare=dict(exchange='testexchange'), expect=dict(exchange='testexchange'))), ('prepare_exchange_none', dict(ctor=dict(exchange='testexchange'), prepare=dict(exchange=None), expect={})), ('both_exchange', dict(ctor=dict(exchange='ctorexchange'), prepare=dict(exchange='testexchange'), expect=dict(exchange='testexchange'))), ('ctor_topic', dict(ctor=dict(topic='testtopic'), prepare={}, expect=dict(topic='testtopic'))), ('prepare_topic', dict(ctor={}, prepare=dict(topic='testtopic'), expect=dict(topic='testtopic'))), ('prepare_topic_none', dict(ctor=dict(topic='testtopic'), prepare=dict(topic=None), expect={})), ('both_topic', dict(ctor=dict(topic='ctortopic'), prepare=dict(topic='testtopic'), expect=dict(topic='testtopic'))), ('ctor_namespace', dict(ctor=dict(namespace='testnamespace'), prepare={}, expect=dict(namespace='testnamespace'))), ('prepare_namespace', dict(ctor={}, prepare=dict(namespace='testnamespace'), expect=dict(namespace='testnamespace'))), ('prepare_namespace_none', dict(ctor=dict(namespace='testnamespace'), prepare=dict(namespace=None), expect={})), ('both_namespace', dict(ctor=dict(namespace='ctornamespace'), prepare=dict(namespace='testnamespace'), expect=dict(namespace='testnamespace'))), ('ctor_version', dict(ctor=dict(version='1.1'), prepare={}, expect=dict(version='1.1'))), ('prepare_version', dict(ctor={}, prepare=dict(version='1.1'), expect=dict(version='1.1'))), ('prepare_version_none', dict(ctor=dict(version='1.1'), prepare=dict(version=None), expect={})), ('both_version', dict(ctor=dict(version='ctorversion'), prepare=dict(version='1.1'), expect=dict(version='1.1'))), ('ctor_server', dict(ctor=dict(server='testserver'), prepare={}, expect=dict(server='testserver'))), ('prepare_server', dict(ctor={}, prepare=dict(server='testserver'), expect=dict(server='testserver'))), ('prepare_server_none', dict(ctor=dict(server='testserver'), prepare=dict(server=None), expect={})), ('both_server', dict(ctor=dict(server='ctorserver'), prepare=dict(server='testserver'), expect=dict(server='testserver'))), ('ctor_fanout', dict(ctor=dict(fanout=True), prepare={}, expect=dict(fanout=True))), ('prepare_fanout', dict(ctor={}, prepare=dict(fanout=True), expect=dict(fanout=True))), ('prepare_fanout_none', dict(ctor=dict(fanout=True), prepare=dict(fanout=None), expect={})), ('both_fanout', dict(ctor=dict(fanout=True), prepare=dict(fanout=False), expect=dict(fanout=False))), ] _prepare = [ ('single_prepare', dict(double_prepare=False)), ('double_prepare', dict(double_prepare=True)), ] @classmethod def generate_scenarios(cls): cls.scenarios = testscenarios.multiply_scenarios(cls._base, cls._prepare) def setUp(self): super(TestCastToTarget, self).setUp(conf=cfg.ConfigOpts()) def test_cast_to_target(self): target = messaging.Target(**self.ctor) expect_target = messaging.Target(**self.expect) transport = _FakeTransport(self.conf) client = messaging.RPCClient(transport, target) self.mox.StubOutWithMock(transport, '_send') msg = dict(method='foo', args={}) if 'namespace' in self.expect: msg['namespace'] = self.expect['namespace'] if 'version' in self.expect: msg['version'] = self.expect['version'] transport._send(expect_target, {}, msg, retry=None) self.mox.ReplayAll() if self.prepare: client = client.prepare(**self.prepare) if self.double_prepare: client = client.prepare(**self.prepare) client.cast({}, 'foo') TestCastToTarget.generate_scenarios() _notset = object() class TestCallTimeout(test_utils.BaseTestCase): scenarios = [ ('all_none', dict(confval=None, ctor=None, prepare=_notset, expect=None)), ('confval', dict(confval=21.1, ctor=None, prepare=_notset, expect=21.1)), ('ctor', dict(confval=None, ctor=21.1, prepare=_notset, expect=21.1)), ('ctor_zero', dict(confval=None, ctor=0, prepare=_notset, expect=0)), ('prepare', dict(confval=None, ctor=None, prepare=21.1, expect=21.1)), ('prepare_override', dict(confval=None, ctor=10.1, prepare=21.1, expect=21.1)), ('prepare_zero', dict(confval=None, ctor=None, prepare=0, expect=0)), ] def test_call_timeout(self): self.config(rpc_response_timeout=self.confval) transport = _FakeTransport(self.conf) client = messaging.RPCClient(transport, messaging.Target(), timeout=self.ctor) self.mox.StubOutWithMock(transport, '_send') msg = dict(method='foo', args={}) kwargs = dict(wait_for_reply=True, timeout=self.expect, retry=None) transport._send(messaging.Target(), {}, msg, **kwargs) self.mox.ReplayAll() if self.prepare is not _notset: client = client.prepare(timeout=self.prepare) client.call({}, 'foo') class TestCallRetry(test_utils.BaseTestCase): scenarios = [ ('all_none', dict(ctor=None, prepare=_notset, expect=None)), ('ctor', dict(ctor=21, prepare=_notset, expect=21)), ('ctor_zero', dict(ctor=0, prepare=_notset, expect=0)), ('prepare', dict(ctor=None, prepare=21, expect=21)), ('prepare_override', dict(ctor=10, prepare=21, expect=21)), ('prepare_zero', dict(ctor=None, prepare=0, expect=0)), ] def test_call_retry(self): transport = _FakeTransport(self.conf) client = messaging.RPCClient(transport, messaging.Target(), retry=self.ctor) self.mox.StubOutWithMock(transport, '_send') msg = dict(method='foo', args={}) kwargs = dict(wait_for_reply=True, timeout=60, retry=self.expect) transport._send(messaging.Target(), {}, msg, **kwargs) self.mox.ReplayAll() if self.prepare is not _notset: client = client.prepare(retry=self.prepare) client.call({}, 'foo') class TestCallFanout(test_utils.BaseTestCase): scenarios = [ ('target', dict(prepare=_notset, target={'fanout': True})), ('prepare', dict(prepare={'fanout': True}, target={})), ('both', dict(prepare={'fanout': True}, target={'fanout': True})), ] def test_call_fanout(self): transport = _FakeTransport(self.conf) client = messaging.RPCClient(transport, messaging.Target(**self.target)) if self.prepare is not _notset: client = client.prepare(**self.prepare) self.assertRaises(exceptions.InvalidTarget, client.call, {}, 'foo') class TestSerializer(test_utils.BaseTestCase): scenarios = [ ('cast', dict(call=False, ctxt=dict(user='bob'), args=dict(a='a', b='b', c='c'), retval=None)), ('call', dict(call=True, ctxt=dict(user='bob'), args=dict(a='a', b='b', c='c'), retval='d')), ] def test_call_serializer(self): self.config(rpc_response_timeout=None) transport = _FakeTransport(self.conf) serializer = msg_serializer.NoOpSerializer() client = messaging.RPCClient(transport, messaging.Target(), serializer=serializer) self.mox.StubOutWithMock(transport, '_send') msg = dict(method='foo', args=dict([(k, 's' + v) for k, v in self.args.items()])) kwargs = dict(wait_for_reply=True, timeout=None) if self.call else {} kwargs['retry'] = None transport._send(messaging.Target(), dict(user='alice'), msg, **kwargs).AndReturn(self.retval) self.mox.StubOutWithMock(serializer, 'serialize_entity') self.mox.StubOutWithMock(serializer, 'deserialize_entity') self.mox.StubOutWithMock(serializer, 'serialize_context') for arg in self.args: serializer.serialize_entity(self.ctxt, arg).AndReturn('s' + arg) if self.call: serializer.deserialize_entity(self.ctxt, self.retval).\ AndReturn('d' + self.retval) serializer.serialize_context(self.ctxt).AndReturn(dict(user='alice')) self.mox.ReplayAll() method = client.call if self.call else client.cast retval = method(self.ctxt, 'foo', **self.args) if self.retval is not None: self.assertEqual('d' + self.retval, retval) class TestVersionCap(test_utils.BaseTestCase): _call_vs_cast = [ ('call', dict(call=True)), ('cast', dict(call=False)), ] _cap_scenarios = [ ('all_none', dict(cap=None, prepare_cap=_notset, version=None, prepare_version=_notset, success=True)), ('ctor_cap_ok', dict(cap='1.1', prepare_cap=_notset, version='1.0', prepare_version=_notset, success=True)), ('ctor_cap_override_ok', dict(cap='2.0', prepare_cap='1.1', version='1.0', prepare_version='1.0', success=True)), ('ctor_cap_override_none_ok', dict(cap='1.1', prepare_cap=None, version='1.0', prepare_version=_notset, success=True)), ('ctor_cap_minor_fail', dict(cap='1.0', prepare_cap=_notset, version='1.1', prepare_version=_notset, success=False)), ('ctor_cap_major_fail', dict(cap='2.0', prepare_cap=_notset, version=None, prepare_version='1.0', success=False)), ] @classmethod def generate_scenarios(cls): cls.scenarios = ( testscenarios.multiply_scenarios(cls._call_vs_cast, cls._cap_scenarios)) def test_version_cap(self): self.config(rpc_response_timeout=None) transport = _FakeTransport(self.conf) target = messaging.Target(version=self.version) client = messaging.RPCClient(transport, target, version_cap=self.cap) if self.success: self.mox.StubOutWithMock(transport, '_send') if self.prepare_version is not _notset: target = target(version=self.prepare_version) msg = dict(method='foo', args={}) if target.version is not None: msg['version'] = target.version kwargs = {'retry': None} if self.call: kwargs['wait_for_reply'] = True kwargs['timeout'] = None transport._send(target, {}, msg, **kwargs) self.mox.ReplayAll() prep_kwargs = {} if self.prepare_cap is not _notset: prep_kwargs['version_cap'] = self.prepare_cap if self.prepare_version is not _notset: prep_kwargs['version'] = self.prepare_version if prep_kwargs: client = client.prepare(**prep_kwargs) method = client.call if self.call else client.cast try: method({}, 'foo') except Exception as ex: self.assertIsInstance(ex, messaging.RPCVersionCapError, ex) self.assertFalse(self.success) else: self.assertTrue(self.success) TestVersionCap.generate_scenarios() class TestCanSendVersion(test_utils.BaseTestCase): scenarios = [ ('all_none', dict(cap=None, prepare_cap=_notset, version=None, prepare_version=_notset, can_send_version=_notset, can_send=True)), ('ctor_cap_ok', dict(cap='1.1', prepare_cap=_notset, version='1.0', prepare_version=_notset, can_send_version=_notset, can_send=True)), ('ctor_cap_override_ok', dict(cap='2.0', prepare_cap='1.1', version='1.0', prepare_version='1.0', can_send_version=_notset, can_send=True)), ('ctor_cap_override_none_ok', dict(cap='1.1', prepare_cap=None, version='1.0', prepare_version=_notset, can_send_version=_notset, can_send=True)), ('ctor_cap_can_send_ok', dict(cap='1.1', prepare_cap=None, version='1.0', prepare_version=_notset, can_send_version='1.1', can_send=True)), ('ctor_cap_can_send_none_ok', dict(cap='1.1', prepare_cap=None, version='1.0', prepare_version=_notset, can_send_version=None, can_send=True)), ('ctor_cap_minor_fail', dict(cap='1.0', prepare_cap=_notset, version='1.1', prepare_version=_notset, can_send_version=_notset, can_send=False)), ('ctor_cap_major_fail', dict(cap='2.0', prepare_cap=_notset, version=None, prepare_version='1.0', can_send_version=_notset, can_send=False)), ] def test_version_cap(self): self.config(rpc_response_timeout=None) transport = _FakeTransport(self.conf) target = messaging.Target(version=self.version) client = messaging.RPCClient(transport, target, version_cap=self.cap) prep_kwargs = {} if self.prepare_cap is not _notset: prep_kwargs['version_cap'] = self.prepare_cap if self.prepare_version is not _notset: prep_kwargs['version'] = self.prepare_version if prep_kwargs: client = client.prepare(**prep_kwargs) if self.can_send_version is not _notset: can_send = client.can_send_version(version=self.can_send_version) else: can_send = client.can_send_version() self.assertEqual(self.can_send, can_send)