diff options
author | Eric Windisch <eric@cloudscaling.com> | 2012-12-12 22:19:18 -0500 |
---|---|---|
committer | Eric Windisch <eric@cloudscaling.com> | 2013-01-08 13:10:44 -0500 |
commit | 1e6b9b7bc7ed3430c442c6bc075ec541850f495d (patch) | |
tree | de10e962313ff4c6bde5ff35763cc71a230476f3 | |
parent | 91c9631bd3e3a0c72b36840ddf90e1db483f9a14 (diff) | |
download | oslo-1e6b9b7bc7ed3430c442c6bc075ec541850f495d.tar.gz oslo-1e6b9b7bc7ed3430c442c6bc075ec541850f495d.tar.xz oslo-1e6b9b7bc7ed3430c442c6bc075ec541850f495d.zip |
rpc method arguments should be dict, not list
default arguments were being set to a
list instead of a dict. This caused
problems if the args key was missing
in the msg argument to the call/cast methods.
Adds tests to check if RPC cast/call work
without arguments. Changes and documents
the _test_cast method arguments, allowing
for more flexibility and code reuse.
fixes bug 1089750
Change-Id: I854dc3fcad8936695feb4414f3862672cf98c5d1
-rw-r--r-- | openstack/common/rpc/impl_zmq.py | 4 | ||||
-rw-r--r-- | tests/unit/rpc/common.py | 50 |
2 files changed, 39 insertions, 15 deletions
diff --git a/openstack/common/rpc/impl_zmq.py b/openstack/common/rpc/impl_zmq.py index 33562b0..85c5fe5 100644 --- a/openstack/common/rpc/impl_zmq.py +++ b/openstack/common/rpc/impl_zmq.py @@ -250,7 +250,7 @@ class InternalContext(object): """Process a curried message and cast the result to topic.""" LOG.debug(_("Running func with context: %s"), ctx.to_dict()) data.setdefault('version', None) - data.setdefault('args', []) + data.setdefault('args', {}) try: result = proxy.dispatch( @@ -321,7 +321,7 @@ class ConsumerBase(object): return data.setdefault('version', None) - data.setdefault('args', []) + data.setdefault('args', {}) proxy.dispatch(ctx, data['version'], data['method'], **data['args']) diff --git a/tests/unit/rpc/common.py b/tests/unit/rpc/common.py index 70a1ad0..40803aa 100644 --- a/tests/unit/rpc/common.py +++ b/tests/unit/rpc/common.py @@ -74,6 +74,14 @@ class BaseRpcTestCase(test_utils.BaseTestCase): {"method": "echo", "args": {"value": value}}) self.assertEqual(value, result) + def test_call_succeed_despite_missing_args(self): + if not self.rpc: + raise nose.SkipTest('rpc driver not available.') + + result = self.rpc.call(FLAGS, self.context, self.topic, + {"method": "fortytwo"}) + self.assertEqual(42, result) + def test_call_succeed_despite_multiple_returns_yield(self): if not self.rpc: raise nose.SkipTest('rpc driver not available.') @@ -135,9 +143,14 @@ class BaseRpcTestCase(test_utils.BaseTestCase): "args": {"value": value}}) self.assertEqual(self.context.to_dict(), result) - def _test_cast(self, fanout=False): - """Test casts by pushing items through a channeled queue.""" + def _test_cast(self, method, value, args=None, fanout=False): + """Test casts by pushing items through a channeled queue. + @param: method a reference to a method returning a value + @param: value the value expected from method + @param: args optional dictionary arguments to method + @param: fanout boolean for use of rpc fanout method + """ # Not a true global, but capitalized so # it is clear it is leaking scope into Nested() QUEUE = eventlet.queue.Queue() @@ -149,19 +162,22 @@ class BaseRpcTestCase(test_utils.BaseTestCase): # global, and do not keep state outside this test. class Nested(object): @staticmethod - def put_queue(context, value): - LOG.debug(_("Got value in put_queue: %s"), value) - QUEUE.put(value) + def curry(*args, **kwargs): + QUEUE.put(method(*args, **kwargs)) nested = Nested() conn = self._create_consumer(nested, self.topic_nested, fanout) - value = 42 - method = (self.rpc.cast, self.rpc.fanout_cast)[fanout] - method(FLAGS, self.context, - self.topic_nested, - {"method": "put_queue", - "args": {"value": value}}) + rpc_method = (self.rpc.cast, self.rpc.fanout_cast)[fanout] + + msg = {'method': 'curry'} + if args and isinstance(args, dict): + msg['args'] = {} + msg['args'].update(args) + + rpc_method(FLAGS, self.context, + self.topic_nested, + msg) try: # If it does not succeed in 2 seconds, give up and assume @@ -174,10 +190,13 @@ class BaseRpcTestCase(test_utils.BaseTestCase): self.assertEqual(value, result) def test_cast_success(self): - self._test_cast(False) + self._test_cast(TestReceiver.echo, 42, {"value": 42}, fanout=False) def test_fanout_success(self): - self._test_cast(True) + self._test_cast(TestReceiver.echo, 42, {"value": 42}, fanout=True) + + def test_cast_success_despite_missing_args(self): + self._test_cast(TestReceiver.fortytwo, 42, fanout=True) def test_nested_calls(self): if not self.rpc: @@ -290,6 +309,11 @@ class TestReceiver(object): return value @staticmethod + def fortytwo(context): + """Simply returns 42.""" + return 42 + + @staticmethod def context(context, value): """Returns dictionary version of context.""" LOG.debug(_("Received %s"), context) |