/* * 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.jms.message; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import javax.jms.JMSException; import javax.jms.MessageFormatException; import javax.jms.MessageNotReadableException; import javax.jms.MessageNotWriteableException; import javax.jms.ObjectMessage; import org.apache.qpid.jms.message.facade.JmsObjectMessageFacade; import org.apache.qpid.jms.message.facade.test.JmsTestMessageFactory; import org.apache.qpid.jms.message.facade.test.JmsTestObjectMessageFacade; import org.junit.Test; import org.mockito.Mockito; /** * */ public class JmsObjectMessageTest { private final JmsMessageFactory factory = new JmsTestMessageFactory(); /** * Test that attempting to write bytes to a received message (without calling {@link ObjectMessage#clearBody()} first) * causes a {@link MessageNotWriteableException} to be thrown due to being read-only. * * @throws Exception if an error occurs during the test. */ @Test public void testReceivedObjectMessageThrowsMessageNotWriteableExceptionOnSetObject() throws Exception { String content = "myStringContent"; JmsObjectMessageFacade facade = new JmsTestObjectMessageFacade(); facade.setObject(content); JmsObjectMessage objectMessage = new JmsObjectMessage(facade); objectMessage.onDispatch(); try { objectMessage.setObject("newObject"); fail("Expected exception to be thrown"); } catch (MessageNotWriteableException mnwe) { // expected } } /** * Test that calling {@link ObjectMessage#toString()} returns a meaningful value * * @throws Exception if an error occurs during the test. */ @Test public void testToString() throws Exception { String content = "myStringContent"; JmsObjectMessageFacade facade = new JmsTestObjectMessageFacade(); facade.setObject(content); JmsObjectMessage objectMessage = new JmsObjectMessage(facade); objectMessage.onDispatch(); assertTrue(objectMessage.toString().startsWith("JmsObjectMessageFacade")); } /** * Test that calling {@link ObjectMessage#clearBody()} causes a received * message to become writable * * @throws Exception if an error occurs during the test. */ @Test public void testClearBodyOnReceivedObjectMessageMakesMessageWritable() throws Exception { String content = "myStringContent"; JmsObjectMessageFacade facade = new JmsTestObjectMessageFacade(); facade.setObject(content); JmsObjectMessage objectMessage = new JmsObjectMessage(facade); objectMessage.onDispatch(); assertTrue("Message should not be writable", objectMessage.isReadOnlyBody()); objectMessage.clearBody(); assertFalse("Message should be writable", objectMessage.isReadOnlyBody()); } /** * Test that calling {@link ObjectMessage#clearBody()} of a received message * causes the body of the underlying message facade to be emptied. * * @throws Exception if an error occurs during the test. */ @Test public void testClearBodyOnReceivedObjectMessageClearsUnderlyingMessageBody() throws Exception { String content = "myStringContent"; JmsTestObjectMessageFacade facade = new JmsTestObjectMessageFacade(); facade.setObject(content); JmsObjectMessage objectMessage = new JmsObjectMessage(facade); objectMessage.onDispatch(); assertNotNull("Expected body section but none was present", facade.getSerializedObject()); objectMessage.clearBody(); // check that the returned object is now null assertNull("Unexpected object value", objectMessage.getObject()); // verify the underlying message facade has no body assertNull("Expected no body section", facade.getSerializedObject()); } /** * Test that setting an object on a new message and later getting the value, returns an * equal but different object that does not pick up intermediate changes to the set object. * * @throws Exception if an error occurs during the test. */ @Test public void testSetThenGetObjectReturnsSnapshot() throws Exception { Map<String,String> origMap = new HashMap<String,String>(); origMap.put("key1", "value1"); JmsTestObjectMessageFacade facade = new JmsTestObjectMessageFacade(); facade.setObject((Serializable) origMap); JmsObjectMessage objectMessage = new JmsObjectMessage(facade); objectMessage.onDispatch(); // verify we get a different-but-equal object back Serializable serialized = objectMessage.getObject(); assertTrue("Unexpected object type returned", serialized instanceof Map<?,?>); Map<?,?> returnedObject1 = (Map<?,?>) serialized; assertNotSame("Expected different objects, due to snapshot being taken", origMap, returnedObject1); assertEquals("Expected equal objects, due to snapshot being taken", origMap, returnedObject1); // mutate the original object origMap.put("key2", "value2"); // verify we get a different-but-equal object back when compared to the previously retrieved object Serializable serialized2 = objectMessage.getObject(); assertTrue("Unexpected object type returned", serialized2 instanceof Map<?,?>); Map<?,?> returnedObject2 = (Map<?,?>) serialized2; assertNotSame("Expected different objects, due to snapshot being taken", origMap, returnedObject2); assertEquals("Expected equal objects, due to snapshot being taken", returnedObject1, returnedObject2); // verify the mutated map is a different and not equal object assertNotSame("Expected different objects, due to snapshot being taken", returnedObject1, returnedObject2); assertNotEquals("Expected objects to differ, due to snapshot being taken", origMap, returnedObject2); } /** * Test that setting an object on a new message which contains non-serializable content results * in an {@link MessageFormatException} being thrown due to failure to encode the object. * * @throws Exception if an error occurs during the test. */ @Test public void testSetObjectWithNonSerializableThrowsJMSMFE() throws Exception { Map<String, Object> origMap = new HashMap<String, Object>(); origMap.put("key1", "value1"); origMap.put("notSerializable", new NotSerializable()); JmsObjectMessage objectMessage = factory.createObjectMessage(); try { objectMessage.setObject((Serializable) origMap); fail("Expected exception to be thrown"); } catch (MessageFormatException mfe) { // expected } } // Test class private static class NotSerializable { public NotSerializable() {} } /** * Test that failure during deserialization of an object in a message results * in an {@link MessageFormatException} being throw. * * @throws Exception if an error occurs during the test. */ @Test(expected=MessageFormatException.class) public void testGetObjectWithFailedDeserialisationThrowsJMSMFE() throws Exception { JmsObjectMessageFacade facade = Mockito.mock(JmsTestObjectMessageFacade.class); Mockito.when(facade.getObject()).thenThrow(new ClassCastException("Failed to get object")); JmsObjectMessage objectMessage = new JmsObjectMessage(facade); objectMessage.getObject(); } @Test public void testBytes() throws JMSException, IOException { JmsObjectMessage msg = factory.createObjectMessage(); String str = "testText"; msg.setObject(str); msg = msg.copy(); assertEquals(msg.getObject(), str); } @Test public void testSetObject() throws JMSException { JmsObjectMessage msg = factory.createObjectMessage(); String str = "testText"; msg.setObject(str); assertEquals(str, msg.getObject()); } @Test public void testClearBody() throws JMSException { JmsObjectMessage objectMessage = factory.createObjectMessage(); try { objectMessage.setObject("String"); objectMessage.clearBody(); assertFalse(objectMessage.isReadOnlyBody()); assertNull(objectMessage.getObject()); objectMessage.setObject("String"); objectMessage.getObject(); } catch (MessageNotWriteableException mnwe) { fail("should be writeable"); } } @Test public void testReadOnlyBody() throws JMSException { JmsObjectMessage msg = factory.createObjectMessage(); msg.setObject("test"); msg.setReadOnlyBody(true); try { msg.getObject(); } catch (MessageNotReadableException e) { fail("should be readable"); } try { msg.setObject("test"); fail("should throw exception"); } catch (MessageNotWriteableException e) { } } @Test public void testWriteOnlyBody() throws JMSException { // should always be readable JmsObjectMessage msg = factory.createObjectMessage(); msg.setReadOnlyBody(false); try { msg.setObject("test"); msg.getObject(); } catch (MessageNotReadableException e) { fail("should be readable"); } msg.setReadOnlyBody(true); try { msg.getObject(); msg.setObject("test"); fail("should throw exception"); } catch (MessageNotReadableException e) { fail("should be readable"); } catch (MessageNotWriteableException mnwe) { } } }