content: /*
   * 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.activemq.transport.amqp.message;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertNotNull;
  import static org.junit.Assert.assertNull;
  import static org.junit.Assert.assertTrue;
  
  import java.nio.charset.Charset;
  import java.nio.charset.StandardCharsets;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.UUID;
  
  import jakarta.jms.Destination;
  import jakarta.jms.MapMessage;
  import jakarta.jms.Queue;
  import jakarta.jms.TemporaryQueue;
  import jakarta.jms.TemporaryTopic;
  import jakarta.jms.TextMessage;
  import jakarta.jms.Topic;
  
  import org.apache.activemq.command.ActiveMQBytesMessage;
  import org.apache.activemq.command.ActiveMQMapMessage;
  import org.apache.activemq.command.ActiveMQMessage;
  import org.apache.activemq.command.ActiveMQObjectMessage;
  import org.apache.activemq.command.ActiveMQStreamMessage;
  import org.apache.activemq.command.ActiveMQTextMessage;
  import org.apache.qpid.proton.Proton;
  import org.apache.qpid.proton.amqp.Binary;
  import org.apache.qpid.proton.amqp.Symbol;
  import org.apache.qpid.proton.amqp.messaging.AmqpSequence;
  import org.apache.qpid.proton.amqp.messaging.AmqpValue;
  import org.apache.qpid.proton.amqp.messaging.Data;
  import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
  import org.apache.qpid.proton.message.Message;
  import org.junit.Test;
  
  public class JMSMappingInboundTransformerTest {
  
      //----- Null Body Section ------------------------------------------------//
  
      /**
       * Test that a message with no body section, but with the content type set to
       * {@value AmqpMessageSupport#OCTET_STREAM_CONTENT_TYPE} results in a BytesMessage
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateBytesMessageFromNoBodySectionAndContentType() throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          Message message = Message.Factory.create();
          message.setContentType(AmqpMessageSupport.OCTET_STREAM_CONTENT_TYPE);
  
          EncodedMessage em = encodeMessage(message);
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that a message with no body section, and no content-type results in a BytesMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateBytesMessageFromNoBodySectionAndNoContentType() throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          Message message = Message.Factory.create();
  
          EncodedMessage em = encodeMessage(message);
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that a message with no body section, but with the content type set to
       * {@value AmqpMessageSupport#SERIALIZED_JAVA_OBJECT_CONTENT_TYPE} results in an ObjectMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
      */
      @Test
      public void testCreateObjectMessageFromNoBodySectionAndContentType() throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          Message message = Message.Factory.create();
          message.setContentType(AmqpMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE);
  
          EncodedMessage em = encodeMessage(message);
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQObjectMessage.class, jmsMessage.getClass());
      }
  
      @Test
      public void testCreateTextMessageFromNoBodySectionAndContentType() throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          Message message = Message.Factory.create();
          message.setContentType("text/plain");
  
          EncodedMessage em = encodeMessage(message);
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQTextMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that a message with no body section, and with the content type set to
       * an unknown value results in a plain Message when not otherwise annotated to
       * indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      public void testCreateGenericMessageFromNoBodySectionAndUnknownContentType() throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          Message message = Message.Factory.create();
          message.setContentType("unknown-content-type");
  
          EncodedMessage em = encodeMessage(message);
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQMessage.class, jmsMessage.getClass());
      }
  
      //----- Data Body Section ------------------------------------------------//
  
      /**
       * Test that a data body containing nothing, but with the content type set to
       * {@value AmqpMessageSupport#OCTET_STREAM_CONTENT_TYPE} results in a BytesMessage when not
       * otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateBytesMessageFromDataWithEmptyBinaryAndContentType() throws Exception {
          Message message = Proton.message();
          Binary binary = new Binary(new byte[0]);
          message.setBody(new Data(binary));
          message.setContentType(AmqpMessageSupport.OCTET_STREAM_CONTENT_TYPE);
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that a message with an empty data body section, and with the content type
       * set to an unknown value results in a BytesMessage when not otherwise annotated
       * to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      public void testCreateBytesMessageFromDataWithUnknownContentType() throws Exception {
          Message message = Proton.message();
          Binary binary = new Binary(new byte[0]);
          message.setBody(new Data(binary));
          message.setContentType("unknown-content-type");
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that a receiving a data body containing nothing and no content type being set
       * results in a BytesMessage when not otherwise annotated to indicate the type of
       * JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateBytesMessageFromDataWithEmptyBinaryAndNoContentType() throws Exception {
          Message message = Proton.message();
          Binary binary = new Binary(new byte[0]);
          message.setBody(new Data(binary));
  
          assertNull(message.getContentType());
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that receiving a data body containing nothing, but with the content type set to
       * {@value AmqpMessageSupport#SERIALIZED_JAVA_OBJECT_CONTENT_TYPE} results in an ObjectMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateObjectMessageFromDataWithContentTypeAndEmptyBinary() throws Exception {
          Message message = Proton.message();
          Binary binary = new Binary(new byte[0]);
          message.setBody(new Data(binary));
          message.setContentType(AmqpMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE);
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQObjectMessage.class, jmsMessage.getClass());
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeTextPlain() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/plain", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeTextJson() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/json;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/json;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/json", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeTextHtml() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/html;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/html;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/html;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/html", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeTextFoo() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("text/foo", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeApplicationJson() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/json;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/json;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/json", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeApplicationJsonVariant() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+json", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeApplicationJavascript() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/javascript", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeApplicationEcmascript() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/ecmascript", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeApplicationXml() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeApplicationXmlVariant() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/something+xml", StandardCharsets.UTF_8);
      }
  
      @Test
      public void testCreateTextMessageFromDataWithContentTypeApplicationXmlDtd() throws Exception {
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd;charset=iso-8859-1", StandardCharsets.ISO_8859_1);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd;charset=us-ascii", StandardCharsets.US_ASCII);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd;charset=utf-8", StandardCharsets.UTF_8);
          doCreateTextMessageFromDataWithContentTypeTestImpl("application/xml-dtd", StandardCharsets.UTF_8);
      }
  
      private void doCreateTextMessageFromDataWithContentTypeTestImpl(String contentType, Charset expectedCharset) throws Exception {
          Message message = Proton.message();
          Binary binary = new Binary(new byte[0]);
          message.setBody(new Data(binary));
          message.setContentType(contentType);
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          if (StandardCharsets.UTF_8.equals(expectedCharset)) {
              assertEquals("Unexpected message class type", ActiveMQTextMessage.class, jmsMessage.getClass());
          } else {
              assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
          }
      }
  
      //----- AmqpValue transformations ----------------------------------------//
  
      /**
       * Test that an amqp-value body containing a string results in a TextMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateTextMessageFromAmqpValueWithString() throws Exception {
          Message message = Proton.message();
          message.setBody(new AmqpValue("content"));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQTextMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that an amqp-value body containing a null results in an TextMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateTextMessageFromAmqpValueWithNull() throws Exception {
          Message message = Proton.message();
          message.setBody(new AmqpValue(null));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQTextMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that a message with an AmqpValue section containing a Binary, but with the content type
       * set to {@value AmqpMessageSupport#SERIALIZED_JAVA_OBJECT_CONTENT_TYPE} results in an ObjectMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
      */
      @Test
      public void testCreateObjectMessageFromAmqpValueWithBinaryAndContentType() throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          Message message = Message.Factory.create();
          message.setBody(new AmqpValue(new Binary(new byte[0])));
          message.setContentType(AmqpMessageSupport.SERIALIZED_JAVA_OBJECT_CONTENT_TYPE);
  
          EncodedMessage em = encodeMessage(message);
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQObjectMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that an amqp-value body containing a map results in an MapMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateAmqpMapMessageFromAmqpValueWithMap() throws Exception {
          Message message = Proton.message();
          Map<String, String> map = new HashMap<String,String>();
          message.setBody(new AmqpValue(map));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQMapMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that an amqp-value body containing a map that has an AMQP Binary as one of the
       * entries encoded into the Map results in an MapMessage where a byte array can be read
       * from the entry.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateAmqpMapMessageFromAmqpValueWithMapContainingBinaryEntry() throws Exception {
          final String ENTRY_NAME = "bytesEntry";
  
          Message message = Proton.message();
          Map<String, Object> map = new HashMap<String, Object>();
  
          byte[] inputBytes = new byte[] { 1, 2, 3, 4, 5 };
          map.put(ENTRY_NAME, new Binary(inputBytes));
  
          message.setBody(new AmqpValue(map));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQMapMessage.class, jmsMessage.getClass());
  
          MapMessage mapMessage = (MapMessage) jmsMessage;
          byte[] outputBytes = mapMessage.getBytes(ENTRY_NAME);
          assertNotNull(outputBytes);
          assertTrue(Arrays.equals(inputBytes, outputBytes));
      }
  
      /**
       * Test that an amqp-value body containing a list results in an StreamMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateAmqpStreamMessageFromAmqpValueWithList() throws Exception {
          Message message = Proton.message();
          List<String> list = new ArrayList<String>();
          message.setBody(new AmqpValue(list));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQStreamMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that an amqp-sequence body containing a list results in an StreamMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateAmqpStreamMessageFromAmqpSequence() throws Exception {
          Message message = Proton.message();
          List<String> list = new ArrayList<String>();
          message.setBody(new AmqpSequence(list));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQStreamMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that an amqp-value body containing a binary value results in BytesMessage
       * when not otherwise annotated to indicate the type of JMS message it is.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateAmqpBytesMessageFromAmqpValueWithBinary() throws Exception {
          Message message = Proton.message();
          Binary binary = new Binary(new byte[0]);
          message.setBody(new AmqpValue(binary));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
      }
  
      /**
       * Test that an amqp-value body containing a value which can't be categorized results in
       * an exception from the transformer and then try the transformer's own fallback transformer
       * to result in an BytesMessage.
       *
       * @throws Exception if an error occurs during the test.
       */
      @Test
      public void testCreateBytesMessageFromAmqpValueWithUncategorisedContent() throws Exception {
          Message message = Proton.message();
          message.setBody(new AmqpValue(UUID.randomUUID()));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertNotNull("Message should not be null", jmsMessage);
          assertEquals("Unexpected message class type", ActiveMQBytesMessage.class, jmsMessage.getClass());
      }
  
      @Test
      public void testTransformMessageWithAmqpValueStringCreatesTextMessage() throws Exception {
          String contentString = "myTextMessageContent";
          Message message = Message.Factory.create();
          message.setBody(new AmqpValue(contentString));
  
          EncodedMessage em = encodeMessage(message);
  
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
          jakarta.jms.Message jmsMessage = transformer.transform(em);
  
          assertTrue("Expected TextMessage", jmsMessage instanceof TextMessage);
          assertEquals("Unexpected message class type", ActiveMQTextMessage.class, jmsMessage.getClass());
  
          TextMessage textMessage = (TextMessage) jmsMessage;
  
          assertNotNull(textMessage.getText());
          assertEquals(contentString, textMessage.getText());
      }
  
      //----- Destination Conversions ------------------------------------------//
  
      @Test
      public void testTransformWithNoToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithToTypeDestinationTypeAnnotationTestImpl(null, Destination.class);
      }
  
      @Test
      public void testTransformWithQueueStringToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithToTypeDestinationTypeAnnotationTestImpl("queue", Queue.class);
      }
  
      @Test
      public void testTransformWithTemporaryQueueStringToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithToTypeDestinationTypeAnnotationTestImpl("queue,temporary", TemporaryQueue.class);
      }
  
      @Test
      public void testTransformWithTopicStringToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithToTypeDestinationTypeAnnotationTestImpl("topic", Topic.class);
      }
  
      @Test
      public void testTransformWithTemporaryTopicStringToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithToTypeDestinationTypeAnnotationTestImpl("topic,temporary", TemporaryTopic.class);
      }
  
      private void doTransformWithToTypeDestinationTypeAnnotationTestImpl(Object toTypeAnnotationValue, Class<? extends Destination> expectedClass) throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          String toAddress = "toAddress";
          Message amqp = Message.Factory.create();
          amqp.setBody(new AmqpValue("myTextMessageContent"));
          amqp.setAddress(toAddress);
          if (toTypeAnnotationValue != null) {
              Map<Symbol, Object> map = new HashMap<Symbol, Object>();
              map.put(Symbol.valueOf("x-opt-to-type"), toTypeAnnotationValue);
              MessageAnnotations ma = new MessageAnnotations(map);
              amqp.setMessageAnnotations(ma);
          }
  
          EncodedMessage em = encodeMessage(amqp);
  
          jakarta.jms.Message jmsMessage = transformer.transform(em);
          assertTrue("Expected TextMessage", jmsMessage instanceof TextMessage);
      }
  
      //----- ReplyTo Conversions ----------------------------------------------//
  
      @Test
      public void testTransformWithNoReplyToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl(null, Destination.class);
      }
  
      @Test
      public void testTransformWithQueueStringReplyToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("queue", Queue.class);
      }
  
      @Test
      public void testTransformWithTemporaryQueueStringReplyToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("queue,temporary", TemporaryQueue.class);
      }
  
      @Test
      public void testTransformWithTopicStringReplyToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("topic", Topic.class);
      }
  
      @Test
      public void testTransformWithTemporaryTopicStringReplyToTypeDestinationTypeAnnotation() throws Exception {
          doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl("topic,temporary", TemporaryTopic.class);
      }
  
      private void doTransformWithReplyToTypeDestinationTypeAnnotationTestImpl(Object replyToTypeAnnotationValue, Class<? extends Destination> expectedClass) throws Exception {
          JMSMappingInboundTransformer transformer = new JMSMappingInboundTransformer();
  
          String replyToAddress = "replyToAddress";
          Message amqp = Message.Factory.create();
          amqp.setBody(new AmqpValue("myTextMessageContent"));
          amqp.setReplyTo(replyToAddress);
          if (replyToTypeAnnotationValue != null) {
              Map<Symbol, Object> map = new HashMap<Symbol, Object>();
              map.put(Symbol.valueOf("x-opt-reply-type"), replyToTypeAnnotationValue);
              MessageAnnotations ma = new MessageAnnotations(map);
              amqp.setMessageAnnotations(ma);
          }
  
          EncodedMessage em = encodeMessage(amqp);
  
          jakarta.jms.Message jmsMessage = transformer.transform(em);
          assertTrue("Expected TextMessage", jmsMessage instanceof TextMessage);
      }
  
      //----- Utility Methods --------------------------------------------------//
  
      private EncodedMessage encodeMessage(Message message) {
          byte[] encodeBuffer = new byte[1024 * 8];
          int encodedSize;
          while (true) {
              try {
                  encodedSize = message.encode(encodeBuffer, 0, encodeBuffer.length);
                  break;
              } catch (java.nio.BufferOverflowException e) {
                  encodeBuffer = new byte[encodeBuffer.length * 2];
              }
          }
  
          long messageFormat = 0;
          return new EncodedMessage(messageFormat, encodeBuffer, 0, encodedSize);
      }
  }
  