QPID-7434: Add unit tests for property conversion of internal messages to AMQP 0-8 messages
Project: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/commit/8ab67e0c Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/8ab67e0c Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/8ab67e0c Branch: refs/heads/master Commit: 8ab67e0c145b5a18df424c829e99b47b63d65726 Parents: 392187c Author: Alex Rudyy <[email protected]> Authored: Tue Aug 1 17:08:58 2017 +0100 Committer: Alex Rudyy <[email protected]> Committed: Tue Aug 1 17:08:58 2017 +0100 ---------------------------------------------------------------------- .../v0_8/MessageConverter_Internal_to_v0_8.java | 47 ++- .../PropertyConverter_Internal_to_v0_8Test.java | 336 +++++++++++++++++++ 2 files changed, 378 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/8ab67e0c/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java ---------------------------------------------------------------------- diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java index 82bbb29..a83f4df 100644 --- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java +++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java @@ -32,6 +32,7 @@ import org.apache.qpid.server.message.mimecontentconverter.ObjectToMimeContentCo import org.apache.qpid.server.model.NamedAddressSpace; import org.apache.qpid.server.plugin.MessageConverter; import org.apache.qpid.server.plugin.PluggableService; +import org.apache.qpid.server.protocol.converter.MessageConversionException; import org.apache.qpid.server.protocol.v0_8.transport.BasicContentHeaderProperties; import org.apache.qpid.server.protocol.v0_8.transport.ContentHeaderBody; import org.apache.qpid.server.protocol.v0_8.transport.MessagePublishInfo; @@ -166,15 +167,17 @@ public class MessageConverter_Internal_to_v0_8 implements MessageConverter<Inter final BasicContentHeaderProperties props = new BasicContentHeaderProperties(); props.setAppId(serverMsg.getMessageHeader().getAppId()); props.setContentType(bodyMimeType); - props.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId()); + props.setCorrelationId(convertToShortStringForProperty("correlation-id", serverMsg.getMessageHeader().getCorrelationId())); props.setDeliveryMode(serverMsg.isPersistent() ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT); props.setExpiration(serverMsg.getExpiration()); - props.setMessageId(serverMsg.getMessageHeader().getMessageId()); + props.setMessageId(convertToOptionalAMQPShortString(serverMsg.getMessageHeader().getMessageId())); props.setPriority(serverMsg.getMessageHeader().getPriority()); - props.setReplyTo(serverMsg.getMessageHeader().getReplyTo()); + props.setReplyTo(convertToOptionalAMQPShortString(serverMsg.getMessageHeader().getReplyTo())); props.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); - props.setUserId(serverMsg.getMessageHeader().getUserId()); + props.setUserId(convertToOptionalAMQPShortString(serverMsg.getMessageHeader().getUserId())); + + props.setEncoding(convertToShortStringForProperty("encoding", serverMsg.getMessageHeader().getEncoding())); Map<String,Object> headerProps = new LinkedHashMap<String, Object>(); @@ -183,13 +186,47 @@ public class MessageConverter_Internal_to_v0_8 implements MessageConverter<Inter headerProps.put(headerName, serverMsg.getMessageHeader().getHeader(headerName)); } - props.setHeaders(FieldTable.convertToFieldTable(headerProps)); + try + { + props.setHeaders(FieldTable.convertToFieldTable(headerProps)); + } + catch (IllegalArgumentException | AMQPInvalidClassException e) + { + throw new MessageConversionException("Could not convert message from internal to 0-8 because headers conversion failed.", e); + } final ContentHeaderBody chb = new ContentHeaderBody(props); chb.setBodySize(size); return new MessageMetaData(publishInfo, chb, serverMsg.getArrivalTime()); } + private AMQShortString convertToOptionalAMQPShortString(final String stringValue) + { + AMQShortString result; + try + { + result = AMQShortString.valueOf(stringValue); + } + catch (IllegalArgumentException e) + { + result = null; + } + return result; + } + + private AMQShortString convertToShortStringForProperty(String propertyName, String s) + { + try + { + return AMQShortString.valueOf(s); + } + catch (IllegalArgumentException e) + { + throw new MessageConversionException(String.format( + "Could not convert message from internal to 0-8 because conversion of '%s' failed.", propertyName), e); + } + } + @Override public String getType() http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/8ab67e0c/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/PropertyConverter_Internal_to_v0_8Test.java ---------------------------------------------------------------------- diff --git a/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/PropertyConverter_Internal_to_v0_8Test.java b/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/PropertyConverter_Internal_to_v0_8Test.java new file mode 100644 index 0000000..6915812 --- /dev/null +++ b/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/PropertyConverter_Internal_to_v0_8Test.java @@ -0,0 +1,336 @@ + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.message.internal.InternalMessageHeader; +import org.apache.qpid.server.message.internal.InternalMessageMetaData; +import org.apache.qpid.server.message.internal.InternalMessageMetaDataType; +import org.apache.qpid.server.model.NamedAddressSpace; +import org.apache.qpid.server.protocol.converter.MessageConversionException; +import org.apache.qpid.server.protocol.v0_8.transport.BasicContentHeaderProperties; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.test.utils.QpidTestCase; + +public class PropertyConverter_Internal_to_v0_8Test extends QpidTestCase +{ + private MessageConverter_Internal_to_v0_8 _messageConverter; + private NamedAddressSpace _addressSpace; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _messageConverter = new MessageConverter_Internal_to_v0_8(); + _addressSpace = mock(NamedAddressSpace.class); + } + + public void testDurableTrueConversion() + { + final AMQMessageHeader header = mock(AMQMessageHeader.class); + InternalMessage originalMessage = createTestMessage(header, null, true); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected delivery mode", + BasicContentHeaderProperties.PERSISTENT, + convertedMessage.getContentHeaderBody().getProperties().getDeliveryMode()); + assertTrue("Unexpected persistence of message", convertedMessage.isPersistent()); + assertTrue("Unexpected persistence of meta data", + convertedMessage.getStoredMessage().getMetaData().isPersistent()); + } + + public void testDurableFalseConversion() + { + final AMQMessageHeader header = mock(AMQMessageHeader.class); + InternalMessage originalMessage = createTestMessage(header, null, false); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected delivery mode", + BasicContentHeaderProperties.NON_PERSISTENT, + convertedMessage.getContentHeaderBody().getProperties().getDeliveryMode()); + assertFalse("Unexpected persistence of message", convertedMessage.isPersistent()); + assertFalse("Unexpected persistence of meta data", + convertedMessage.getStoredMessage().getMetaData().isPersistent()); + } + + public void testPriorityConversion() + { + final AMQMessageHeader header = mock(AMQMessageHeader.class); + byte priority = (byte) 7; + when(header.getPriority()).thenReturn(priority); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected priority", + priority, + convertedMessage.getContentHeaderBody().getProperties().getPriority()); + } + + public void testExpirationConversion() throws InterruptedException + { + long ttl = 10000; + long expiryTime = System.currentTimeMillis() + ttl; + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getExpiration()).thenReturn(expiryTime); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected expiration time", + expiryTime, + convertedMessage.getContentHeaderBody().getProperties().getExpiration()); + } + + public void testContentEncodingConversion() + { + String contentEncoding = "my-test-encoding"; + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getEncoding()).thenReturn(contentEncoding); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected content encoding", + contentEncoding, + convertedMessage.getContentHeaderBody().getProperties().getEncodingAsString()); + } + + public void testLongContentEncodingConversion() + { + String contentEncoding = generateLongString(); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getEncoding()).thenReturn(contentEncoding); + InternalMessage originalMessage = createTestMessage(header); + + try + { + _messageConverter.convert(originalMessage, _addressSpace); + fail("Expected exception is not thrown"); + } + catch (MessageConversionException e) + { + // pass + } + } + + public void testMessageIdConversion() + { + final String messageId = "testMessageId"; + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getMessageId()).thenReturn(messageId); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected messageId", + messageId, + convertedMessage.getContentHeaderBody().getProperties().getMessageIdAsString()); + } + + public void testMessageIdConversionWhenLengthExceeds255() + { + final String messageId = generateLongString(); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getMessageId()).thenReturn(messageId); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertNull("Unexpected messageId", convertedMessage.getContentHeaderBody().getProperties().getMessageId()); + } + + public void testCorrelationIdConversionWhenLengthExceeds255() + { + final String correlationId = generateLongString(); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getCorrelationId()).thenReturn(correlationId); + InternalMessage originalMessage = createTestMessage(header); + + try + { + _messageConverter.convert(originalMessage, _addressSpace); + fail("Expected exception is not thrown"); + } + catch (MessageConversionException e) + { + // pass + } + } + + public void testUserIdConversion() + { + final String userId = "testUserId"; + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getUserId()).thenReturn(userId); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected userId", + userId, + convertedMessage.getContentHeaderBody().getProperties().getUserIdAsString()); + } + + public void testUserIdConversionWhenLengthExceeds255() + { + final String userId = generateLongString(); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getUserId()).thenReturn(userId); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertNull("Unexpected userId", convertedMessage.getContentHeaderBody().getProperties().getUserId()); + } + + public void testTimestampConversion() + { + final long timestamp = System.currentTimeMillis(); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getTimestamp()).thenReturn(timestamp); + InternalMessage originalMessage = createTestMessage(header); + + AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + assertEquals("Unexpected timestamp", + timestamp, + convertedMessage.getContentHeaderBody().getProperties().getTimestamp()); + } + + public void testHeadersConversion() + { + final Map<String, Object> properties = new HashMap<>(); + properties.put("testProperty1", "testProperty1Value"); + properties.put("intProperty", 1); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getHeaderNames()).thenReturn(properties.keySet()); + doAnswer(invocation -> + { + final String originalArgument = (String) (invocation.getArguments())[0]; + return properties.get(originalArgument); + }).when(header).getHeader(any(String.class)); + InternalMessage originalMessage = createTestMessage(header); + + final AMQMessage convertedMessage = _messageConverter.convert(originalMessage, _addressSpace); + + Map<String, Object> convertedHeaders = + FieldTable.convertToMap(convertedMessage.getContentHeaderBody().getProperties().getHeaders()); + assertEquals("Unexpected application properties", properties, new HashMap<>(convertedHeaders)); + } + + public void testHeadersConversionWithUnsupportedTypes() + { + final Map<String, Object> properties = Collections.singletonMap("uuidProperty", UUID.randomUUID()); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getHeaderNames()).thenReturn(properties.keySet()); + doAnswer(invocation -> + { + final String originalArgument = (String) (invocation.getArguments())[0]; + return properties.get(originalArgument); + }).when(header).getHeader(any(String.class)); + InternalMessage originalMessage = createTestMessage(header); + + try + { + _messageConverter.convert(originalMessage, _addressSpace); + fail("Expected exception not thrown"); + } + catch (MessageConversionException e) + { + // pass + } + } + + + public void testHeadersConversionWhenKeyLengthExceeds255() + { + final Map<String, Object> properties = Collections.singletonMap(generateLongString(), "test"); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(header.getHeaderNames()).thenReturn(properties.keySet()); + doAnswer(invocation -> + { + final String originalArgument = (String) (invocation.getArguments())[0]; + return properties.get(originalArgument); + }).when(header).getHeader(any(String.class)); + InternalMessage originalMessage = createTestMessage(header); + + try + { + _messageConverter.convert(originalMessage, _addressSpace); + fail("Expected exception not thrown"); + } + catch (MessageConversionException e) + { + // pass + } + } + + private InternalMessage createTestMessage(final AMQMessageHeader header) + { + return createTestMessage(header, null, false); + } + + private InternalMessage createTestMessage(final AMQMessageHeader header, + byte[] content, + final boolean persistent) + { + final InternalMessageHeader internalMessageHeader = new InternalMessageHeader(header); + final int contentSize = content == null ? 0 : content.length; + final InternalMessageMetaData metaData = + new InternalMessageMetaData(persistent, internalMessageHeader, contentSize); + final StoredMessage<InternalMessageMetaData> storedMessage = mock(StoredMessage.class); + + when(storedMessage.getMetaData()).thenReturn(metaData); + when(storedMessage.getContentSize()).thenReturn(contentSize); + return ((InternalMessage) InternalMessageMetaDataType.INSTANCE.createMessage(storedMessage)); + } + + private String generateLongString() + { + return generateLongString(AMQShortString.MAX_LENGTH + 1); + } + + private String generateLongString(int stringLength) + { + StringBuilder buffer = new StringBuilder(); + for (int i = 0; i < stringLength; i++) + { + buffer.append('x'); + } + + return buffer.toString(); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
