diff options
author | Ben Nemec <bnemec@us.ibm.com> | 2013-05-09 19:06:45 +0000 |
---|---|---|
committer | Ben Nemec <bnemec@us.ibm.com> | 2013-06-03 22:08:12 +0000 |
commit | 7ce54410485b33cffc39c7ffb96eae422b88601c (patch) | |
tree | 5f4f6d38d5b8c9089e463068801e8a40a72a0106 /tests | |
parent | e3e497915f0cc47bba10aad4ef5e940669801cb3 (diff) | |
download | oslo-7ce54410485b33cffc39c7ffb96eae422b88601c.tar.gz oslo-7ce54410485b33cffc39c7ffb96eae422b88601c.tar.xz oslo-7ce54410485b33cffc39c7ffb96eae422b88601c.zip |
Fix problem with long messages in Qpid
Qpid has a limitation where it cannot serialize a dict containing
a string greater than 65535 characters. This change alters the
Qpid implementation to JSON encode the dict before sending it, but
only if Qpid would fail to serialize it. This maintains as much
backward compatibility as possible, though long messages will
still fail if they are sent to an older receiver.
Fixes bug 1175808
Change-Id: I5d104e099f523508dae2b657f7d06d96984b10f0
Diffstat (limited to 'tests')
-rw-r--r-- | tests/unit/rpc/test_qpid.py | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/tests/unit/rpc/test_qpid.py b/tests/unit/rpc/test_qpid.py index 1630ac4..4af4f35 100644 --- a/tests/unit/rpc/test_qpid.py +++ b/tests/unit/rpc/test_qpid.py @@ -28,6 +28,7 @@ import mox from oslo.config import cfg from openstack.common import context +from openstack.common import jsonutils from openstack.common.rpc import amqp as rpc_amqp from openstack.common.rpc import common as rpc_common from tests import utils @@ -491,6 +492,88 @@ class RpcQpidTestCase(utils.BaseTestCase): def test_multicall(self): self._test_call(multi=True) + def _test_publisher(self, message=True): + """Test that messages containing long strings are correctly serialized + in a way that Qpid can handle. + + :param message: The publisher may be passed either a Qpid Message + object or a bare dict. This parameter controls which of those the test + will send. + """ + self.sent_msg = None + + def send_stub(msg): + self.sent_msg = msg + + # Qpid cannot serialize a dict containing a string > 65535 chars. + raw_msg = {'test': 'a' * 65536} + if message: + base_msg = qpid.messaging.Message(raw_msg) + else: + base_msg = raw_msg + expected_msg = qpid.messaging.Message(jsonutils.dumps(raw_msg)) + expected_msg.content_type = impl_qpid.JSON_CONTENT_TYPE + mock_session = self.mox.CreateMock(self.orig_session) + mock_sender = self.mox.CreateMock(self.orig_sender) + mock_session.sender(mox.IgnoreArg()).AndReturn(mock_sender) + self.stubs.Set(mock_sender, 'send', send_stub) + self.mox.ReplayAll() + + publisher = impl_qpid.Publisher(mock_session, 'test_node') + publisher.send(base_msg) + + self.assertEqual(self.sent_msg.content, expected_msg.content) + self.assertEqual(self.sent_msg.content_type, expected_msg.content_type) + + def test_publisher_long_message(self): + self._test_publisher(message=True) + + def test_publisher_long_dict(self): + self._test_publisher(message=False) + + def _test_consumer_long_message(self, json=True): + """Verify that the Qpid implementation correctly deserializes + message content. + + :param json: For compatibility, this code needs to support both + messages that are and are not JSON encoded. This param + specifies which is being tested. + """ + def fake_callback(msg): + self.received_msg = msg + + # The longest string Qpid can handle itself + chars = 65535 + if json: + # The first length that requires JSON encoding + chars = 65536 + raw_msg = {'test': 'a' * chars} + if json: + fake_message = qpid.messaging.Message(jsonutils.dumps(raw_msg)) + fake_message.content_type = impl_qpid.JSON_CONTENT_TYPE + else: + fake_message = qpid.messaging.Message(raw_msg) + mock_session = self.mox.CreateMock(self.orig_session) + mock_receiver = self.mox.CreateMock(self.orig_receiver) + mock_session.receiver(mox.IgnoreArg()).AndReturn(mock_receiver) + mock_receiver.fetch().AndReturn(fake_message) + mock_session.acknowledge(mox.IgnoreArg()) + self.mox.ReplayAll() + + consumer = impl_qpid.DirectConsumer(None, + mock_session, + 'bogus_msg_id', + fake_callback) + consumer.consume() + + self.assertEqual(self.received_msg, raw_msg) + + def test_consumer_long_message(self): + self._test_consumer_long_message(json=True) + + def test_consumer_long_message_no_json(self): + self._test_consumer_long_message(json=False) + # #from nova.tests.rpc import common |