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.ra;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertNotNull;
  import static org.junit.Assert.assertNull;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.fail;
  
  import java.beans.IntrospectionException;
  import java.beans.PropertyDescriptor;
  import java.util.Arrays;
  import java.util.List;
  
  import jakarta.jms.Queue;
  import jakarta.jms.Session;
  import jakarta.jms.Topic;
  import jakarta.resource.spi.InvalidPropertyException;
  
  import org.apache.activemq.command.ActiveMQDestination;
  import org.junit.Before;
  import org.junit.Test;
  
  public class ActiveMQActivationSpecTest {
  
      private static final String DESTINATION = "defaultQueue";
      private static final String DESTINATION_TYPE = Queue.class.getName();
      private static final String EMPTY_STRING = "   ";
  
      private ActiveMQActivationSpec activationSpec;
      private PropertyDescriptor destinationProperty;
      private PropertyDescriptor destinationTypeProperty;
      private PropertyDescriptor acknowledgeModeProperty;
      private PropertyDescriptor subscriptionDurabilityProperty;
      private PropertyDescriptor clientIdProperty;
      private PropertyDescriptor subscriptionNameProperty;
  
      @Before
      public void setUp() throws Exception {
  
          activationSpec = new ActiveMQActivationSpec();
          activationSpec.setDestination(DESTINATION);
          activationSpec.setDestinationType(DESTINATION_TYPE);
  
          destinationProperty = new PropertyDescriptor("destination", ActiveMQActivationSpec.class);
          destinationTypeProperty = new PropertyDescriptor("destinationType", ActiveMQActivationSpec.class);
          acknowledgeModeProperty = new PropertyDescriptor("acknowledgeMode", ActiveMQActivationSpec.class);
          subscriptionDurabilityProperty = new PropertyDescriptor("subscriptionDurability", ActiveMQActivationSpec.class);
          clientIdProperty = new PropertyDescriptor("clientId", ActiveMQActivationSpec.class);
          subscriptionNameProperty = new PropertyDescriptor("subscriptionName", ActiveMQActivationSpec.class);
      }
  
      @Test(timeout = 60000)
      public void testDefaultContructionValidation() throws IntrospectionException {
          PropertyDescriptor[] expected = {destinationTypeProperty, destinationProperty};
          assertActivationSpecInvalid(new ActiveMQActivationSpec(), expected);
      }
  
      @Test(timeout = 60000)
      public void testMinimalSettings() {
          assertEquals(DESTINATION, activationSpec.getDestination());
          assertEquals(DESTINATION_TYPE, activationSpec.getDestinationType());
          assertActivationSpecValid();
      }
  
      @Test(timeout = 60000)
      public void testNoDestinationTypeFailure() {
          activationSpec.setDestinationType(null);
          PropertyDescriptor[] expected = {destinationTypeProperty};
          assertActivationSpecInvalid(expected);
      }
  
      @Test(timeout = 60000)
      public void testInvalidDestinationTypeFailure() {
          activationSpec.setDestinationType("foobar");
          PropertyDescriptor[] expected = {destinationTypeProperty};
          assertActivationSpecInvalid(expected);
      }
  
      @Test(timeout = 60000)
      public void testQueueDestinationType() {
          activationSpec.setDestinationType(Queue.class.getName());
          assertActivationSpecValid();
      }
  
      @Test(timeout = 60000)
      public void testTopicDestinationType() {
          activationSpec.setDestinationType(Topic.class.getName());
          assertActivationSpecValid();
      }
  
      @Test(timeout = 60000)
      public void testSuccessfulCreateQueueDestination() {
          activationSpec.setDestinationType(Queue.class.getName());
          activationSpec.setDestination(DESTINATION);
          assertActivationSpecValid();
          ActiveMQDestination destination = activationSpec.createDestination();
          assertNotNull("ActiveMQDestination not created", destination);
          assertEquals("Physical name not the same", activationSpec.getDestination(), destination.getPhysicalName());
          assertTrue("Destination is not a Queue", destination instanceof Queue);
      }
  
      @Test(timeout = 60000)
      public void testSuccessfulCreateTopicDestination() {
          activationSpec.setDestinationType(Topic.class.getName());
          activationSpec.setDestination(DESTINATION);
          assertActivationSpecValid();
          ActiveMQDestination destination = activationSpec.createDestination();
          assertNotNull("ActiveMQDestination not created", destination);
          assertEquals("Physical name not the same", activationSpec.getDestination(), destination.getPhysicalName());
          assertTrue("Destination is not a Topic", destination instanceof Topic);
      }
  
      @Test(timeout = 60000)
      public void testCreateDestinationIncorrectType() {
          activationSpec.setDestinationType(null);
          activationSpec.setDestination(DESTINATION);
          ActiveMQDestination destination = activationSpec.createDestination();
          assertNull("ActiveMQDestination should not have been created", destination);
      }
  
      @Test(timeout = 60000)
      public void testCreateDestinationIncorrectDestinationName() {
          activationSpec.setDestinationType(Topic.class.getName());
          activationSpec.setDestination(null);
          ActiveMQDestination destination = activationSpec.createDestination();
          assertNull("ActiveMQDestination should not have been created", destination);
      }
  
      //----------- acknowledgeMode tests
  
      @Test(timeout = 60000)
      public void testDefaultAcknowledgeModeSetCorrectly() {
          assertEquals("Incorrect default value", ActiveMQActivationSpec.AUTO_ACKNOWLEDGE_MODE,
                  activationSpec.getAcknowledgeMode());
          assertEquals("Incorrect default value", Session.AUTO_ACKNOWLEDGE,
                  activationSpec.getAcknowledgeModeForSession());
      }
  
      @Test(timeout = 60000)
      public void testInvalidAcknowledgeMode() {
          activationSpec.setAcknowledgeMode("foobar");
          PropertyDescriptor[] expected = {acknowledgeModeProperty};
          assertActivationSpecInvalid(expected);
          assertEquals("Incorrect acknowledge mode", ActiveMQActivationSpec.INVALID_ACKNOWLEDGE_MODE,
                  activationSpec.getAcknowledgeModeForSession());
      }
  
      @Test(timeout = 60000)
      public void testNoAcknowledgeMode() {
          activationSpec.setAcknowledgeMode(null);
          PropertyDescriptor[] expected = {acknowledgeModeProperty};
          assertActivationSpecInvalid(expected);
          assertEquals("Incorrect acknowledge mode", ActiveMQActivationSpec.INVALID_ACKNOWLEDGE_MODE,
                  activationSpec.getAcknowledgeModeForSession());
      }
  
      @Test(timeout = 60000)
      public void testSettingAutoAcknowledgeMode() {
          activationSpec.setAcknowledgeMode(ActiveMQActivationSpec.AUTO_ACKNOWLEDGE_MODE);
          assertActivationSpecValid();
          assertEquals("Incorrect acknowledge mode", Session.AUTO_ACKNOWLEDGE,
                  activationSpec.getAcknowledgeModeForSession());
      }
  
      @Test(timeout = 60000)
      public void testSettingDupsOkAcknowledgeMode() {
          activationSpec.setAcknowledgeMode(ActiveMQActivationSpec.DUPS_OK_ACKNOWLEDGE_MODE);
          assertActivationSpecValid();
          assertEquals("Incorrect acknowledge mode", Session.DUPS_OK_ACKNOWLEDGE,
                  activationSpec.getAcknowledgeModeForSession());
      }
  
      //----------- subscriptionDurability tests
  
      @Test(timeout = 60000)
      public void testDefaultSubscriptionDurabilitySetCorrectly() {
          assertEquals("Incorrect default value", ActiveMQActivationSpec.NON_DURABLE_SUBSCRIPTION, activationSpec.getSubscriptionDurability());
      }
  
      @Test(timeout = 60000)
      public void testInvalidSubscriptionDurability() {
          activationSpec.setSubscriptionDurability("foobar");
          PropertyDescriptor[] expected = {subscriptionDurabilityProperty};
          assertActivationSpecInvalid(expected);
      }
  
      @Test(timeout = 60000)
      public void testNullSubscriptionDurability() {
          activationSpec.setSubscriptionDurability(null);
          PropertyDescriptor[] expected = {subscriptionDurabilityProperty};
          assertActivationSpecInvalid(expected);
      }
  
      @Test(timeout = 60000)
      public void testSettingNonDurableSubscriptionDurability() {
          activationSpec.setSubscriptionDurability(ActiveMQActivationSpec.NON_DURABLE_SUBSCRIPTION);
          assertActivationSpecValid();
      }
  
      //----------- durable subscriber tests
  
      @Test(timeout = 60000)
      public void testValidDurableSubscriber() {
          activationSpec.setDestinationType(Topic.class.getName());
          activationSpec.setSubscriptionDurability(ActiveMQActivationSpec.DURABLE_SUBSCRIPTION);
          activationSpec.setClientId("foobar");
          activationSpec.setSubscriptionName("foobar");
          assertActivationSpecValid();
          assertTrue(activationSpec.isDurableSubscription());
      }
  
      @Test(timeout = 60000)
      public void testDurableSubscriberWithQueueDestinationTypeFailure() {
          activationSpec.setDestinationType(Queue.class.getName());
          activationSpec.setSubscriptionDurability(ActiveMQActivationSpec.DURABLE_SUBSCRIPTION);
          activationSpec.setClientId("foobar");
          activationSpec.setSubscriptionName("foobar");
          PropertyDescriptor[] expected = {subscriptionDurabilityProperty};
          assertActivationSpecInvalid(expected);
      }
  
      @Test(timeout = 60000)
      public void testDurableSubscriberNoClientIdNoSubscriptionNameFailure() {
          activationSpec.setDestinationType(Topic.class.getName());
          activationSpec.setSubscriptionDurability(ActiveMQActivationSpec.DURABLE_SUBSCRIPTION);
          activationSpec.setClientId(null);
          assertNull(activationSpec.getClientId());
          activationSpec.setSubscriptionName(null);
          assertNull(activationSpec.getSubscriptionName());
          PropertyDescriptor[] expected = {clientIdProperty, subscriptionNameProperty};
          assertActivationSpecInvalid(expected);
      }
  
      @Test(timeout = 60000)
      public void testDurableSubscriberEmptyClientIdEmptySubscriptionNameFailure() {
          activationSpec.setDestinationType(Topic.class.getName());
          activationSpec.setSubscriptionDurability(ActiveMQActivationSpec.DURABLE_SUBSCRIPTION);
          activationSpec.setClientId(EMPTY_STRING);
          assertNull(activationSpec.getClientId());
          activationSpec.setSubscriptionName(EMPTY_STRING);
          assertNull(activationSpec.getSubscriptionName());
          PropertyDescriptor[] expected = {clientIdProperty, subscriptionNameProperty};
          assertActivationSpecInvalid(expected);
      }
  
      @Test(timeout = 60000)
      public void testSetEmptyStringButGetNullValue() {
          ActiveMQActivationSpec activationSpec = new ActiveMQActivationSpec();
  
          activationSpec.setDestinationType(EMPTY_STRING);
          assertNull("Property not null", activationSpec.getDestinationType());
  
          activationSpec.setMessageSelector(EMPTY_STRING);
          assertNull("Property not null", activationSpec.getMessageSelector());
  
          activationSpec.setDestination(EMPTY_STRING);
          assertNull("Property not null", activationSpec.getDestination());
  
          activationSpec.setUserName(EMPTY_STRING);
          assertNull("Property not null", activationSpec.getUserName());
  
          activationSpec.setPassword(EMPTY_STRING);
          assertNull("Property not null", activationSpec.getPassword());
  
          activationSpec.setClientId(EMPTY_STRING);
          assertNull("Property not null", activationSpec.getClientId());
  
          activationSpec.setSubscriptionName(EMPTY_STRING);
          assertNull("Property not null", activationSpec.getSubscriptionName());
      }
  
      //----------- helper methods
  
      private void assertActivationSpecValid() {
          try {
              activationSpec.validate();
          } catch (InvalidPropertyException e) {
              fail("InvalidPropertyException should not be thrown");
          }
      }
  
      private void assertActivationSpecInvalid(PropertyDescriptor[] expected) {
          assertActivationSpecInvalid(activationSpec, expected);
      }
  
      private void assertActivationSpecInvalid(ActiveMQActivationSpec testActivationSpec, PropertyDescriptor[] expected) {
          try {
              testActivationSpec.validate();
              fail("InvalidPropertyException should have been thrown");
          } catch (InvalidPropertyException e) {
              PropertyDescriptor[] actual = e.getInvalidPropertyDescriptors();
              assertDescriptorsAreEqual(expected, actual);
          }
      }
  
      private static void assertDescriptorsAreEqual(PropertyDescriptor[] expected, PropertyDescriptor[] actual) {
          /*
          * This is kind of ugly.  I originally created two HashSets and did an assertEquals(set1, set2)
          * but because of a bug in the PropertyDescriptor class, it incorrectly fails.  The problem is that the
          * PropertyDescriptor class implements the equals() method but not the hashCode() method and almost all
          * of the java collection classes use hashCode() for testing equality.  The one exception I found was
          * the ArrayList class which uses equals() for testing equality.  Since Arrays.asList(...) returns an
          * ArrayList, I use it below.  Yes, ugly ... I know.
          *
          * see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4634390
          */
          assertNotNull("No PropertyDescriptors returned", expected);
          assertEquals("PropertyDescriptor array size is incorrect ", expected.length, actual.length);
          List<PropertyDescriptor> expectedList = Arrays.asList(expected);
          List<PropertyDescriptor> actualList = Arrays.asList(actual);
          assertTrue("Incorrect PropertyDescriptors returned", expectedList.containsAll(actualList));
      }
  
      public void testSelfEquality() {
          assertEquality(activationSpec, activationSpec);
      }
  
      public void testSamePropertiesButNotEqual() {
          assertNonEquality(new ActiveMQActivationSpec(), new ActiveMQActivationSpec());
      }
  
      private void assertEquality(ActiveMQActivationSpec leftSpec, ActiveMQActivationSpec rightSpec) {
          assertTrue("ActiveMQActivationSpecs are not equal", leftSpec.equals(rightSpec));
          assertTrue("ActiveMQActivationSpecs are not equal", rightSpec.equals(leftSpec));
          assertTrue("HashCodes are not equal", leftSpec.hashCode() == rightSpec.hashCode());
      }
  
      private void assertNonEquality(ActiveMQActivationSpec leftSpec, ActiveMQActivationSpec rightSpec) {
          assertFalse("ActiveMQActivationSpecs are equal", leftSpec.equals(rightSpec));
          assertFalse("ActiveMQActivationSpecs are equal", rightSpec.equals(leftSpec));
          assertFalse("HashCodes are equal", leftSpec.hashCode() == rightSpec.hashCode());
      }
  }
  