diff options
Diffstat (limited to 'java/systests/src/main')
95 files changed, 5889 insertions, 3403 deletions
diff --git a/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java b/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java deleted file mode 100644 index 5323ad28bf..0000000000 --- a/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * 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.mina.transport.vmpipe.support; - -import org.apache.mina.common.IdleStatus; - -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * This file is a patch to override MINA, because of the IdentityHashMap bug. Workaround to be supplied in MINA 1.0.7. - * This patched file will be removed once upgraded onto a newer MINA. - * - * Dectects idle sessions and fires <tt>sessionIdle</tt> events to them. - * - * @author The Apache Directory Project (mina-dev@directory.apache.org) - */ -public class VmPipeIdleStatusChecker -{ - private static final VmPipeIdleStatusChecker INSTANCE = new VmPipeIdleStatusChecker(); - - public static VmPipeIdleStatusChecker getInstance() - { - return INSTANCE; - } - - private final Map sessions = new HashMap(); // will use as a set - - private final Worker worker = new Worker(); - - private VmPipeIdleStatusChecker() - { - worker.start(); - } - - public void addSession(VmPipeSessionImpl session) - { - synchronized (sessions) - { - sessions.put(session, session); - } - } - - private class Worker extends Thread - { - private Worker() - { - super("VmPipeIdleStatusChecker"); - setDaemon(true); - } - - public void run() - { - for (;;) - { - try - { - Thread.sleep(1000); - } - catch (InterruptedException e) - { } - - long currentTime = System.currentTimeMillis(); - - synchronized (sessions) - { - Iterator it = sessions.keySet().iterator(); - while (it.hasNext()) - { - VmPipeSessionImpl session = (VmPipeSessionImpl) it.next(); - if (!session.isConnected()) - { - it.remove(); - } - else - { - notifyIdleSession(session, currentTime); - } - } - } - } - } - } - - private void notifyIdleSession(VmPipeSessionImpl session, long currentTime) - { - notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE), IdleStatus.BOTH_IDLE, - Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE))); - notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.READER_IDLE), IdleStatus.READER_IDLE, - Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE))); - notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE), IdleStatus.WRITER_IDLE, - Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE))); - } - - private void notifyIdleSession0(VmPipeSessionImpl session, long currentTime, long idleTime, IdleStatus status, - long lastIoTime) - { - if ((idleTime > 0) && (lastIoTime != 0) && ((currentTime - lastIoTime) >= idleTime)) - { - session.increaseIdleCount(status); - session.getFilterChain().fireSessionIdle(session, status); - } - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java index ca10126aa7..7ea4416f3b 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java @@ -30,19 +30,16 @@ import javax.jms.TextMessage; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.client.transport.TransportConnection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase { - - private static final int NUM_MESSAGES = 1000; - private Connection con; private Session session; private AMQQueue queue; private MessageConsumer consumer; + private int numMessages; private static final Logger _logger = LoggerFactory.getLogger(AMQQueueDeferredOrderingTest.class); @@ -88,6 +85,8 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase { super.setUp(); + numMessages = isBrokerStorePersistent() ? 300 : 1000; + _logger.info("Create Connection"); con = getConnection(); _logger.info("Create Session"); @@ -106,19 +105,19 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase // Setup initial messages _logger.info("Creating first producer thread"); - producerThread = new ASyncProducer(queue, 0, NUM_MESSAGES / 2); + producerThread = new ASyncProducer(queue, 0, numMessages / 2); producerThread.start(); // Wait for them to be done producerThread.join(); // Setup second set of messages to produce while we consume _logger.info("Creating second producer thread"); - producerThread = new ASyncProducer(queue, NUM_MESSAGES / 2, NUM_MESSAGES); + producerThread = new ASyncProducer(queue, numMessages / 2, numMessages); producerThread.start(); // Start consuming and checking they're in order _logger.info("Consuming messages"); - for (int i = 0; i < NUM_MESSAGES; i++) + for (int i = 0; i < numMessages; i++) { Message msg = consumer.receive(3000); assertNotNull("Message should not be null", msg); diff --git a/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java b/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java index a8a23c2c41..29a44ecec3 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java @@ -36,7 +36,6 @@ import javax.jms.Session; import javax.naming.Context; import javax.naming.spi.InitialContextFactory; -import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.slf4j.Logger; diff --git a/java/systests/src/main/java/org/apache/qpid/client/MultipleJCAProviderRegistrationTest.java b/java/systests/src/main/java/org/apache/qpid/client/MultipleJCAProviderRegistrationTest.java deleted file mode 100644 index 29b4dd82a7..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/client/MultipleJCAProviderRegistrationTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * 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.client; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.client.transport.TransportConnection; - -import java.io.File; -import java.security.Provider; -import java.security.Security; -import java.util.List; -import java.util.LinkedList; - -/** - * QPID-1394 : Test to ensure that the client can register their custom JCAProviders after the broker to ensure that - * the Qpid custom authentication SASL plugins are used. - */ -public class MultipleJCAProviderRegistrationTest extends QpidBrokerTestCase -{ - - public void setUp() throws Exception - { - _broker = VM; - - super.setUp(); - } - - public void test() throws Exception - { - // Get the providers before connection - Provider[] providers = Security.getProviders(); - - // Force the client to load the providers - getConnection(); - - Provider[] afterConnectionCreation = Security.getProviders(); - - // Find the additions - List additions = new LinkedList(); - for (Provider afterCreation : afterConnectionCreation) - { - boolean found = false; - for (Provider provider : providers) - { - if (provider == afterCreation) - { - found=true; - break; - } - } - - // Record added registies - if (!found) - { - additions.add(afterCreation); - } - } - - assertTrue("Client did not register any providers", additions.size() > 0); - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java b/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java index 303da29389..40a0d32b01 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java @@ -135,7 +135,7 @@ public class ResetMessageListenerTest extends QpidBrokerTestCase try { assertTrue("Did not receive all first batch of messages", - _allFirstMessagesSent.await(1000, TimeUnit.MILLISECONDS)); + _allFirstMessagesSent.await(MSG_COUNT, TimeUnit.SECONDS)); _logger.info("Received first batch of messages"); } catch (InterruptedException e) @@ -212,7 +212,7 @@ public class ResetMessageListenerTest extends QpidBrokerTestCase try { - assertTrue(_allSecondMessagesSent.await(1000, TimeUnit.MILLISECONDS)); + assertTrue(_allSecondMessagesSent.await(MSG_COUNT, TimeUnit.SECONDS)); } catch (InterruptedException e) { diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/AddressBasedFailoverBehaviourTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/AddressBasedFailoverBehaviourTest.java new file mode 100644 index 0000000000..980fc7285d --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/failover/AddressBasedFailoverBehaviourTest.java @@ -0,0 +1,14 @@ +package org.apache.qpid.client.failover; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Session; + +public class AddressBasedFailoverBehaviourTest extends FailoverBehaviourTest +{ + @Override + protected Destination createDestination(Session session) throws JMSException + { + return session.createQueue("ADDR:" +getTestQueueName() + "_" + System.currentTimeMillis() + "; {create: always}"); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java new file mode 100644 index 0000000000..a5b9c618bc --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java @@ -0,0 +1,1221 @@ +/* + * 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.client.failover; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.QueueBrowser; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.jms.TransactionRolledBackException; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.jms.FailoverPolicy; +import org.apache.qpid.test.utils.FailoverBaseCase; + +/** + * Test suite to test all possible failover corner cases + */ +public class FailoverBehaviourTest extends FailoverBaseCase implements ConnectionListener, ExceptionListener +{ + private static final String TEST_MESSAGE_FORMAT = "test message {0}"; + + /** Indicates whether tests are run against clustered broker */ + private static boolean CLUSTERED = Boolean.getBoolean("profile.clustered"); + + /** Default number of messages to send before failover */ + private static final int DEFAULT_NUMBER_OF_MESSAGES = 10; + + /** Actual number of messages to send before failover */ + protected int _messageNumber = Integer.getInteger("profile.failoverMsgCount", DEFAULT_NUMBER_OF_MESSAGES); + + /** Test connection */ + protected Connection _connection; + + /** + * Failover completion latch is used to wait till connectivity to broker is + * restored + */ + private CountDownLatch _failoverComplete; + + /** + * Consumer session + */ + private Session _consumerSession; + + /** + * Test destination + */ + private Destination _destination; + + /** + * Consumer + */ + private MessageConsumer _consumer; + + /** + * Producer session + */ + private Session _producerSession; + + /** + * Producer + */ + private MessageProducer _producer; + + /** + * Holds exception sent into {@link ExceptionListener} on failover + */ + private JMSException _exceptionListenerException; + + /** + * Latch to check that failover mutex is hold by a failover thread + */ + private CountDownLatch _failoverStarted; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _connection = getConnection(); + _connection.setExceptionListener(this); + ((AMQConnection) _connection).setConnectionListener(this); + _failoverComplete = new CountDownLatch(1); + _failoverStarted = new CountDownLatch(1); + } + + /** + * Test whether MessageProducer can successfully publish messages after + * failover and rollback transaction + */ + public void testMessageProducingAndRollbackAfterFailover() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + produceMessages(); + causeFailure(); + + assertFailoverException(); + // producer should be able to send messages after failover + _producer.send(_producerSession.createTextMessage("test message " + _messageNumber)); + + // rollback after failover + _producerSession.rollback(); + + // tests whether sending and committing is working after failover + produceMessages(); + _producerSession.commit(); + + // tests whether receiving and committing is working after failover + consumeMessages(); + _consumerSession.commit(); + } + + /** + * Test whether {@link TransactionRolledBackException} is thrown on commit + * of dirty transacted session after failover. + * <p> + * Verifies whether second after failover commit is successful. + */ + public void testTransactionRolledBackExceptionThrownOnCommitAfterFailoverOnProducingMessages() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + produceMessages(); + causeFailure(); + + assertFailoverException(); + + // producer should be able to send messages after failover + _producer.send(_producerSession.createTextMessage("test message " + _messageNumber)); + + try + { + _producerSession.commit(); + fail("TransactionRolledBackException is expected on commit after failover with dirty session!"); + } + catch (JMSException t) + { + assertTrue("Expected TransactionRolledBackException but thrown " + t, + t instanceof TransactionRolledBackException); + } + + // simulate process of user replaying the transaction + produceMessages("replayed test message {0}", _messageNumber, false); + + // no exception should be thrown + _producerSession.commit(); + + // only messages sent after rollback should be received + consumeMessages("replayed test message {0}", _messageNumber); + + // no exception should be thrown + _consumerSession.commit(); + } + + /** + * Tests JMSException is not thrown on commit with a clean session after + * failover + */ + public void testNoJMSExceptionThrownOnCommitAfterFailoverWithCleanProducerSession() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + + causeFailure(); + + assertFailoverException(); + + // should not throw an exception for a clean session + _producerSession.commit(); + + // tests whether sending and committing is working after failover + produceMessages(); + _producerSession.commit(); + + // tests whether receiving and committing is working after failover + consumeMessages(); + _consumerSession.commit(); + } + + /** + * Tests {@link TransactionRolledBackException} is thrown on commit of dirty + * transacted session after failover. + * <p> + * Verifies whether second after failover commit is successful. + */ + public void testTransactionRolledBackExceptionThrownOnCommitAfterFailoverOnMessageReceiving() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + produceMessages(); + _producerSession.commit(); + + // receive messages but do not commit + consumeMessages(); + + causeFailure(); + + assertFailoverException(); + + try + { + // should throw TransactionRolledBackException + _consumerSession.commit(); + fail("TransactionRolledBackException is expected on commit after failover"); + } + catch (Exception t) + { + assertTrue("Expected TransactionRolledBackException but thrown " + t, + t instanceof TransactionRolledBackException); + } + + resendMessagesIfNecessary(); + + // consume messages successfully + consumeMessages(); + _consumerSession.commit(); + } + + /** + * Tests JMSException is not thrown on commit with a clean session after failover + */ + public void testNoJMSExceptionThrownOnCommitAfterFailoverWithCleanConsumerSession() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + produceMessages(); + _producerSession.commit(); + + consumeMessages(); + _consumerSession.commit(); + + causeFailure(); + + assertFailoverException(); + + // should not throw an exception with a clean consumer session + _consumerSession.commit(); + } + + /** + * Test that TransactionRolledBackException is thrown on commit of + * dirty session in asynchronous consumer after failover. + */ + public void testTransactionRolledBackExceptionThrownOnCommitAfterFailoverOnReceivingMessagesAsynchronously() + throws Exception + { + init(Session.SESSION_TRANSACTED, false); + FailoverTestMessageListener ml = new FailoverTestMessageListener(); + _consumer.setMessageListener(ml); + + _connection.start(); + + produceMessages(); + _producerSession.commit(); + + // wait for message receiving + ml.awaitForEnd(); + + assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter()); + + // assert messages + int counter = 0; + for (Message message : ml.getReceivedMessages()) + { + assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++); + } + ml.reset(); + + causeFailure(); + assertFailoverException(); + + + try + { + _consumerSession.commit(); + fail("TransactionRolledBackException should be thrown!"); + } + catch (TransactionRolledBackException e) + { + // that is what is expected + } + + resendMessagesIfNecessary(); + + // wait for message receiving + ml.awaitForEnd(); + + assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter()); + + // assert messages + counter = 0; + for (Message message : ml.getReceivedMessages()) + { + assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++); + } + + // commit again. It should be successful + _consumerSession.commit(); + } + + /** + * Test that {@link Session#rollback()} does not throw exception after failover + * and that we are able to consume messages. + */ + public void testRollbackAfterFailover() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + + produceMessages(); + _producerSession.commit(); + + consumeMessages(); + + causeFailure(); + + assertFailoverException(); + + _consumerSession.rollback(); + + resendMessagesIfNecessary(); + + // tests whether receiving and committing is working after failover + consumeMessages(); + _consumerSession.commit(); + } + + /** + * Test that {@link Session#rollback()} does not throw exception after receiving further messages + * after failover, and we can receive published messages after rollback. + */ + public void testRollbackAfterReceivingAfterFailover() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + + produceMessages(); + _producerSession.commit(); + + consumeMessages(); + causeFailure(); + + assertFailoverException(); + + resendMessagesIfNecessary(); + + consumeMessages(); + + _consumerSession.rollback(); + + // tests whether receiving and committing is working after failover + consumeMessages(); + _consumerSession.commit(); + } + + /** + * Test that {@link Session#recover()} does not throw an exception after failover + * and that we can consume messages after recover. + */ + public void testRecoverAfterFailover() throws Exception + { + init(Session.CLIENT_ACKNOWLEDGE, true); + + produceMessages(); + + // consume messages but do not acknowledge them + consumeMessages(); + + causeFailure(); + + assertFailoverException(); + + _consumerSession.recover(); + + resendMessagesIfNecessary(); + + // tests whether receiving and acknowledgment is working after recover + Message lastMessage = consumeMessages(); + lastMessage.acknowledge(); + } + + /** + * Test that receiving more messages after failover and then calling + * {@link Session#recover()} does not throw an exception + * and that we can consume messages after recover. + */ + public void testRecoverWithConsumedMessagesAfterFailover() throws Exception + { + init(Session.CLIENT_ACKNOWLEDGE, true); + + produceMessages(); + + // consume messages but do not acknowledge them + consumeMessages(); + + causeFailure(); + + assertFailoverException(); + + // publishing should work after failover + resendMessagesIfNecessary(); + + // consume messages again on a dirty session + consumeMessages(); + + // recover should successfully restore session + _consumerSession.recover(); + + // tests whether receiving and acknowledgment is working after recover + Message lastMessage = consumeMessages(); + lastMessage.acknowledge(); + } + + /** + * Test that first call to {@link Message#acknowledge()} after failover + * throws a JMSEXception if session is dirty. + */ + public void testAcknowledgeAfterFailover() throws Exception + { + init(Session.CLIENT_ACKNOWLEDGE, true); + + produceMessages(); + + // consume messages but do not acknowledge them + Message lastMessage = consumeMessages(); + causeFailure(); + + assertFailoverException(); + + try + { + // an implicit recover performed when acknowledge throws an exception due to failover + lastMessage.acknowledge(); + fail("JMSException should be thrown"); + } + catch (JMSException t) + { + // TODO: assert error code and/or expected exception type + } + + resendMessagesIfNecessary(); + + // tests whether receiving and acknowledgment is working after recover + lastMessage = consumeMessages(); + lastMessage.acknowledge(); + } + + /** + * Test that calling acknowledge before failover leaves the session + * clean for use after failover. + */ + public void testAcknowledgeBeforeFailover() throws Exception + { + init(Session.CLIENT_ACKNOWLEDGE, true); + + produceMessages(); + + // consume messages and acknowledge them + Message lastMessage = consumeMessages(); + lastMessage.acknowledge(); + + causeFailure(); + + assertFailoverException(); + + produceMessages(); + + // tests whether receiving and acknowledgment is working after recover + lastMessage = consumeMessages(); + lastMessage.acknowledge(); + } + + /** + * Test that receiving of messages after failover prior to calling + * {@link Message#acknowledge()} still results in acknowledge throwing an exception. + */ + public void testAcknowledgeAfterMessageReceivingAfterFailover() throws Exception + { + init(Session.CLIENT_ACKNOWLEDGE, true); + + produceMessages(); + + // consume messages but do not acknowledge them + consumeMessages(); + causeFailure(); + + assertFailoverException(); + + resendMessagesIfNecessary(); + + // consume again on dirty session + Message lastMessage = consumeMessages(); + try + { + // an implicit recover performed when acknowledge throws an exception due to failover + lastMessage.acknowledge(); + fail("JMSException should be thrown"); + } + catch (JMSException t) + { + // TODO: assert error code and/or expected exception type + } + + // tests whether receiving and acknowledgment is working on a clean session + lastMessage = consumeMessages(); + lastMessage.acknowledge(); + } + + /** + * Tests that call to {@link Message#acknowledge()} after failover throws an exception in asynchronous consumer + * and we can consume messages after acknowledge. + */ + public void testAcknowledgeAfterFailoverForAsynchronousConsumer() throws Exception + { + init(Session.CLIENT_ACKNOWLEDGE, false); + FailoverTestMessageListener ml = new FailoverTestMessageListener(); + _consumer.setMessageListener(ml); + _connection.start(); + + produceMessages(); + + // wait for message receiving + ml.awaitForEnd(); + + assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter()); + + // assert messages + int counter = 0; + Message currentMessage = null; + for (Message message : ml.getReceivedMessages()) + { + assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++); + currentMessage = message; + } + ml.reset(); + + causeFailure(); + assertFailoverException(); + + + try + { + currentMessage.acknowledge(); + fail("JMSException should be thrown!"); + } + catch (JMSException e) + { + // TODO: assert error code and/or expected exception type + } + + resendMessagesIfNecessary(); + + // wait for message receiving + ml.awaitForEnd(); + + assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter()); + + // assert messages + counter = 0; + for (Message message : ml.getReceivedMessages()) + { + assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++); + currentMessage = message; + } + + // acknowledge again. It should be successful + currentMessage.acknowledge(); + } + + /** + * Test whether {@link Session#recover()} works as expected after failover + * in AA mode. + */ + public void testRecoverAfterFailoverInAutoAcknowledgeMode() throws Exception + { + init(Session.AUTO_ACKNOWLEDGE, true); + + produceMessages(); + + // receive first message in order to start a dispatcher thread + Message receivedMessage = _consumer.receive(1000l); + assertReceivedMessage(receivedMessage, TEST_MESSAGE_FORMAT, 0); + + causeFailure(); + + assertFailoverException(); + + _consumerSession.recover(); + + resendMessagesIfNecessary(); + + // tests whether receiving is working after recover + consumeMessages(); + } + + public void testClientAcknowledgedSessionCloseAfterFailover() throws Exception + { + sessionCloseAfterFailoverImpl(Session.CLIENT_ACKNOWLEDGE); + } + + public void testTransactedSessionCloseAfterFailover() throws Exception + { + sessionCloseAfterFailoverImpl(Session.SESSION_TRANSACTED); + } + + public void testAutoAcknowledgedSessionCloseAfterFailover() throws Exception + { + sessionCloseAfterFailoverImpl(Session.AUTO_ACKNOWLEDGE); + } + + public void testPublishAutoAcknowledgedWhileFailover() throws Exception + { + publishWhileFailingOver(Session.AUTO_ACKNOWLEDGE); + } + + public void testPublishClientAcknowledgedWhileFailover() throws Exception + { + Message receivedMessage = publishWhileFailingOver(Session.CLIENT_ACKNOWLEDGE); + receivedMessage.acknowledge(); + } + + public void testPublishTransactedAcknowledgedWhileFailover() throws Exception + { + publishWhileFailingOver(Session.SESSION_TRANSACTED); + _consumerSession.commit(); + } + + public void testPublishAutoAcknowledgedWithFailoverMutex() throws Exception + { + publishWithFailoverMutex(Session.AUTO_ACKNOWLEDGE); + } + + public void testPublishClientAcknowledgedWithFailoverMutex() throws Exception + { + publishWithFailoverMutex(Session.CLIENT_ACKNOWLEDGE); + + } + + public void testPublishTransactedAcknowledgedWithFailoverMutex() throws Exception + { + publishWithFailoverMutex(Session.SESSION_TRANSACTED); + } + + public void testClientAcknowledgedSessionCloseWhileFailover() throws Exception + { + sessionCloseWhileFailoverImpl(Session.CLIENT_ACKNOWLEDGE); + } + + public void testTransactedSessionCloseWhileFailover() throws Exception + { + sessionCloseWhileFailoverImpl(Session.SESSION_TRANSACTED); + } + + public void testAutoAcknowledgedSessionCloseWhileFailover() throws Exception + { + sessionCloseWhileFailoverImpl(Session.AUTO_ACKNOWLEDGE); + } + + public void testClientAcknowledgedQueueBrowserCloseWhileFailover() throws Exception + { + browserCloseWhileFailoverImpl(Session.CLIENT_ACKNOWLEDGE); + } + + public void testTransactedQueueBrowserCloseWhileFailover() throws Exception + { + browserCloseWhileFailoverImpl(Session.SESSION_TRANSACTED); + } + + public void testAutoAcknowledgedQueueBrowserCloseWhileFailover() throws Exception + { + browserCloseWhileFailoverImpl(Session.AUTO_ACKNOWLEDGE); + } + + private Message publishWhileFailingOver(int autoAcknowledge) throws JMSException, InterruptedException + { + setDelayedFailoverPolicy(5); + init(autoAcknowledge, true); + + String text = MessageFormat.format(TEST_MESSAGE_FORMAT, 0); + Message message = _producerSession.createTextMessage(text); + + failBroker(getFailingPort()); + + if(!_failoverStarted.await(5, TimeUnit.SECONDS)) + { + fail("Did not receieve notification failover had started"); + } + + _producer.send(message); + + if (_producerSession.getTransacted()) + { + _producerSession.commit(); + } + + Message receivedMessage = _consumer.receive(1000l); + assertReceivedMessage(receivedMessage, TEST_MESSAGE_FORMAT, 0); + return receivedMessage; + } + + private void publishWithFailoverMutex(int autoAcknowledge) throws JMSException, InterruptedException + { + setDelayedFailoverPolicy(5); + init(autoAcknowledge, true); + + String text = MessageFormat.format(TEST_MESSAGE_FORMAT, 0); + Message message = _producerSession.createTextMessage(text); + + AMQConnection connection = (AMQConnection)_connection; + + // holding failover mutex should prevent the failover from + // proceeding before we try to send the message + synchronized(connection.getFailoverMutex()) + { + failBroker(getFailingPort()); + + // wait to make sure that connection is lost + while(!connection.isFailingOver()) + { + Thread.sleep(25l); + } + + try + { + _producer.send(message); + fail("Sending should fail because connection was lost and failover has not yet completed"); + } + catch(JMSException e) + { + // JMSException is expected + } + } + // wait for failover completion, thus ensuring it actually + //got started, before allowing the test to tear down + awaitForFailoverCompletion(DEFAULT_FAILOVER_TIME); + } + /** + * Tests {@link Session#close()} for session with given acknowledge mode + * to ensure that close works after failover. + * + * @param acknowledgeMode session acknowledge mode + * @throws JMSException + */ + private void sessionCloseAfterFailoverImpl(int acknowledgeMode) throws JMSException + { + init(acknowledgeMode, true); + produceMessages(TEST_MESSAGE_FORMAT, _messageNumber, false); + if (acknowledgeMode == Session.SESSION_TRANSACTED) + { + _producerSession.commit(); + } + + // intentionally receive message but do not commit or acknowledge it in + // case of transacted or CLIENT_ACK session + Message receivedMessage = _consumer.receive(1000l); + assertReceivedMessage(receivedMessage, TEST_MESSAGE_FORMAT, 0); + + causeFailure(); + + assertFailoverException(); + + // for transacted/client_ack session + // no exception should be thrown but transaction should be automatically + // rolled back + _consumerSession.close(); + } + + /** + * A helper method to instantiate produce and consumer sessions, producer + * and consumer. + * + * @param acknowledgeMode + * acknowledge mode + * @param startConnection + * indicates whether connection should be started + * @throws JMSException + */ + private void init(int acknowledgeMode, boolean startConnection) throws JMSException + { + boolean isTransacted = acknowledgeMode == Session.SESSION_TRANSACTED ? true : false; + + _consumerSession = _connection.createSession(isTransacted, acknowledgeMode); + _destination = createDestination(_consumerSession); + _consumer = _consumerSession.createConsumer(_destination); + + if (startConnection) + { + _connection.start(); + } + + _producerSession = _connection.createSession(isTransacted, acknowledgeMode); + _producer = _producerSession.createProducer(_destination); + + } + + protected Destination createDestination(Session session) throws JMSException + { + return session.createQueue(getTestQueueName() + "_" + System.currentTimeMillis()); + } + + /** + * Resends messages if reconnected to a non-clustered broker + * + * @throws JMSException + */ + private void resendMessagesIfNecessary() throws JMSException + { + if (!CLUSTERED) + { + // assert that a new broker does not have messages on a queue + if (_consumer.getMessageListener() == null) + { + Message message = _consumer.receive(100l); + assertNull("Received a message after failover with non-clustered broker!", message); + } + // re-sending messages if reconnected to a non-clustered broker + produceMessages(true); + } + } + + /** + * Produces a default number of messages with default text content into test + * queue + * + * @throws JMSException + */ + private void produceMessages() throws JMSException + { + produceMessages(false); + } + + private void produceMessages(boolean seperateProducer) throws JMSException + { + produceMessages(TEST_MESSAGE_FORMAT, _messageNumber, seperateProducer); + } + + /** + * Consumes a default number of messages and asserts their content. + * + * @return last consumed message + * @throws JMSException + */ + private Message consumeMessages() throws JMSException + { + return consumeMessages(TEST_MESSAGE_FORMAT, _messageNumber); + } + + /** + * Produces given number of text messages with content matching given + * content pattern + * + * @param messagePattern message content pattern + * @param messageNumber number of messages to send + * @param standaloneProducer whether to use the existing producer or a new one. + * @throws JMSException + */ + private void produceMessages(String messagePattern, int messageNumber, boolean standaloneProducer) throws JMSException + { + Session producerSession; + MessageProducer producer; + + if(standaloneProducer) + { + producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED); + producer = producerSession.createProducer(_destination); + } + else + { + producerSession = _producerSession; + producer = _producer; + } + + for (int i = 0; i < messageNumber; i++) + { + String text = MessageFormat.format(messagePattern, i); + Message message = producerSession.createTextMessage(text); + producer.send(message); + } + + if(standaloneProducer) + { + producerSession.commit(); + } + } + + /** + * Consumes given number of text messages and asserts that their content + * matches given pattern + * + * @param messagePattern + * messages content pattern + * @param messageNumber + * message number to received + * @return last consumed message + * @throws JMSException + */ + private Message consumeMessages(String messagePattern, int messageNumber) throws JMSException + { + Message receivedMesssage = null; + for (int i = 0; i < messageNumber; i++) + { + receivedMesssage = _consumer.receive(1000l); + assertReceivedMessage(receivedMesssage, messagePattern, i); + } + return receivedMesssage; + } + + /** + * Asserts received message + * + * @param receivedMessage + * received message + * @param messagePattern + * messages content pattern + * @param messageIndex + * message index + */ + private void assertReceivedMessage(Message receivedMessage, String messagePattern, int messageIndex) + { + assertNotNull("Expected message [" + messageIndex + "] is not received!", receivedMessage); + assertTrue("Failure to receive message [" + messageIndex + "], expected TextMessage but received " + + receivedMessage, receivedMessage instanceof TextMessage); + String expectedText = MessageFormat.format(messagePattern, messageIndex); + String receivedText = null; + try + { + receivedText = ((TextMessage) receivedMessage).getText(); + } + catch (JMSException e) + { + fail("JMSException occured while getting message text:" + e.getMessage()); + } + assertEquals("Failover is broken! Expected [" + expectedText + "] but got [" + receivedText + "]", + expectedText, receivedText); + } + + /** + * Causes failover and waits till connection is re-established. + */ + private void causeFailure() + { + causeFailure(getFailingPort(), DEFAULT_FAILOVER_TIME * 2); + } + + /** + * Causes failover by stopping broker on given port and waits till + * connection is re-established during given time interval. + * + * @param port + * broker port + * @param delay + * time interval to wait for connection re-establishement + */ + private void causeFailure(int port, long delay) + { + failBroker(port); + + awaitForFailoverCompletion(delay); + } + + private void awaitForFailoverCompletion(long delay) + { + _logger.info("Awaiting Failover completion.."); + try + { + if (!_failoverComplete.await(delay, TimeUnit.MILLISECONDS)) + { + fail("Failover did not complete"); + } + } + catch (InterruptedException e) + { + fail("Test was interrupted:" + e.getMessage()); + } + } + + private void assertFailoverException() + { + // TODO: assert exception is received (once implemented) + // along with error code and/or expected exception type + } + + @Override + public void bytesSent(long count) + { + } + + @Override + public void bytesReceived(long count) + { + } + + @Override + public boolean preFailover(boolean redirect) + { + _failoverStarted.countDown(); + return true; + } + + @Override + public boolean preResubscribe() + { + return true; + } + + @Override + public void failoverComplete() + { + _failoverComplete.countDown(); + } + + @Override + public void onException(JMSException e) + { + _exceptionListenerException = e; + } + + /** + * Causes 1 second delay before reconnect in order to test whether JMS + * methods block while failover is in progress + */ + private static class DelayingFailoverPolicy extends FailoverPolicy + { + + private CountDownLatch _suspendLatch; + private long _delay; + + public DelayingFailoverPolicy(AMQConnection connection, long delay) + { + super(connection.getConnectionURL(), connection); + _suspendLatch = new CountDownLatch(1); + _delay = delay; + } + + public void attainedConnection() + { + try + { + _suspendLatch.await(_delay, TimeUnit.SECONDS); + } + catch (InterruptedException e) + { + // continue + } + super.attainedConnection(); + } + + } + + + private class FailoverTestMessageListener implements MessageListener + { + // message counter + private AtomicInteger _counter = new AtomicInteger(); + + private List<Message> _receivedMessage = new ArrayList<Message>(); + + private volatile CountDownLatch _endLatch; + + public FailoverTestMessageListener() throws JMSException + { + _endLatch = new CountDownLatch(1); + } + + @Override + public void onMessage(Message message) + { + _receivedMessage.add(message); + if (_counter.incrementAndGet() % _messageNumber == 0) + { + _endLatch.countDown(); + } + } + + public void reset() + { + _receivedMessage.clear(); + _endLatch = new CountDownLatch(1); + _counter.set(0); + } + + public List<Message> getReceivedMessages() + { + return _receivedMessage; + } + + public Object awaitForEnd() throws InterruptedException + { + return _endLatch.await((long) _messageNumber, TimeUnit.SECONDS); + } + + public int getMessageCounter() + { + return _counter.get(); + } + } + + /** + * Tests {@link Session#close()} for session with given acknowledge mode + * to ensure that it blocks until failover implementation restores connection. + * + * @param acknowledgeMode session acknowledge mode + * @throws JMSException + */ + private void sessionCloseWhileFailoverImpl(int acknowledgeMode) throws JMSException + { + initDelayedFailover(acknowledgeMode); + + // intentionally receive message but not commit or acknowledge it in + // case of transacted or CLIENT_ACK session + Message receivedMessage = _consumer.receive(1000l); + assertReceivedMessage(receivedMessage, TEST_MESSAGE_FORMAT, 0); + + failBroker(getFailingPort()); + + // test whether session#close blocks while failover is in progress + _consumerSession.close(); + + assertFailoverException(); + } + + /** + * A helper method to instantiate {@link QueueBrowser} and publish test messages on a test queue for further browsing. + * + * @param acknowledgeMode session acknowledge mode + * @return queue browser + * @throws JMSException + */ + private QueueBrowser prepareQueueBrowser(int acknowledgeMode) throws JMSException + { + init(acknowledgeMode, false); + _consumer.close(); + QueueBrowser browser = _consumerSession.createBrowser((Queue) _destination); + _connection.start(); + + produceMessages(TEST_MESSAGE_FORMAT, _messageNumber, false); + if (acknowledgeMode == Session.SESSION_TRANSACTED) + { + _producerSession.commit(); + } + return browser; + } + + /** + * Tests {@link QueueBrowser#close()} for session with given acknowledge mode + * to ensure that it blocks until failover implementation restores connection. + * + * @param acknowledgeMode session acknowledge mode + * @throws JMSException + */ + private void browserCloseWhileFailoverImpl(int acknowledgeMode) throws JMSException + { + setDelayedFailoverPolicy(); + + QueueBrowser browser = prepareQueueBrowser(acknowledgeMode); + + @SuppressWarnings("unchecked") + Enumeration<Message> messages = browser.getEnumeration(); + Message receivedMessage = (Message) messages.nextElement(); + assertReceivedMessage(receivedMessage, TEST_MESSAGE_FORMAT, 0); + + failBroker(getFailingPort()); + + browser.close(); + + assertFailoverException(); + } + + private DelayingFailoverPolicy initDelayedFailover(int acknowledgeMode) throws JMSException + { + DelayingFailoverPolicy failoverPolicy = setDelayedFailoverPolicy(); + init(acknowledgeMode, true); + produceMessages(TEST_MESSAGE_FORMAT, _messageNumber, false); + if (acknowledgeMode == Session.SESSION_TRANSACTED) + { + _producerSession.commit(); + } + return failoverPolicy; + } + + private DelayingFailoverPolicy setDelayedFailoverPolicy() + { + return setDelayedFailoverPolicy(2); + } + + private DelayingFailoverPolicy setDelayedFailoverPolicy(long delay) + { + AMQConnection amqConnection = (AMQConnection) _connection; + DelayingFailoverPolicy failoverPolicy = new DelayingFailoverPolicy(amqConnection, delay); + ((AMQConnection) _connection).setFailoverPolicy(failoverPolicy); + return failoverPolicy; + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java b/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java index 004ce5ea8f..bf96dae02e 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java @@ -27,6 +27,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.jms.Connection; import javax.jms.JMSException; @@ -51,6 +52,7 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase private Session _session; MessageConsumer _consumer; MessageProducer _producer; + UUID myUUID = UUID.randomUUID(); public void setUp() throws Exception { @@ -119,7 +121,8 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase m.setFloat("Float", Integer.MAX_VALUE + 5000); m.setInt("Int", Integer.MAX_VALUE - 5000); m.setShort("Short", (short)58); - m.setString("String", "Hello"); + m.setString("String", "Hello"); + m.setObject("uuid", myUUID); _producer.send(m); AMQPEncodedMapMessage msg = (AMQPEncodedMapMessage)_consumer.receive(RECEIVE_TIMEOUT); @@ -140,6 +143,7 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase assertEquals(Integer.MAX_VALUE - 5000,m.getInt("Int")); assertEquals((short)58,m.getShort("Short")); assertEquals("Hello",m.getString("String")); + assertEquals(myUUID,(UUID)m.getObject("uuid")); } @@ -149,7 +153,11 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase List<Integer> myList = getList(); - m.setObject("List", myList); + m.setObject("List", myList); + + List<UUID> uuidList = new ArrayList<UUID>(); + uuidList.add(myUUID); + m.setObject("uuid-list", uuidList); _producer.send(m); AMQPEncodedMapMessage msg = (AMQPEncodedMapMessage)_consumer.receive(RECEIVE_TIMEOUT); @@ -167,6 +175,10 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase assertEquals(i,j.intValue()); i++; } + + List<UUID> list2 = (List<UUID>)msg.getObject("uuid-list"); + assertNotNull("UUID List not received",list2); + assertEquals(myUUID,list2.get(0)); } public void testMessageWithMapEntries() throws JMSException @@ -174,8 +186,12 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase MapMessage m = _session.createMapMessage(); Map<String,String> myMap = getMap(); + m.setObject("Map", myMap); + + Map<String,UUID> uuidMap = new HashMap<String,UUID>(); + uuidMap.put("uuid", myUUID); + m.setObject("uuid-map", uuidMap); - m.setObject("Map", myMap); _producer.send(m); AMQPEncodedMapMessage msg = (AMQPEncodedMapMessage)_consumer.receive(RECEIVE_TIMEOUT); @@ -191,6 +207,10 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase assertEquals("String" + i,map.get("Key" + i)); i++; } + + Map<String,UUID> map2 = (Map<String,UUID>)msg.getObject("uuid-map"); + assertNotNull("Map not received",map2); + assertEquals(myUUID,map2.get("uuid")); } public void testMessageWithNestedListsAndMaps() throws JMSException diff --git a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java index 8cdf12eaa4..d754979ab9 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java @@ -31,62 +31,72 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.transport.Connection; public class SSLTest extends QpidBrokerTestCase -{ - +{ + private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks"; + private static final String KEYSTORE_PASSWORD = "password"; + private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; + private static final String TRUSTSTORE_PASSWORD = "password"; + private static final String CERT_ALIAS_APP1 = "app1"; + private static final String CERT_ALIAS_APP2 = "app2"; + @Override protected void setUp() throws Exception { - System.setProperty("javax.net.debug", "ssl"); + if(isJavaBroker()) + { + setTestClientSystemProperty("profile.use_ssl", "true"); + setConfigurationProperty("connector.ssl.enabled", "true"); + setConfigurationProperty("connector.ssl.sslOnly", "true"); + } + + // set the ssl system properties + setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); + setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + setSystemProperty("javax.net.debug", "ssl"); super.setUp(); } - @Override - protected void tearDown() throws Exception - { - System.setProperty("javax.net.debug", ""); - super.tearDown(); - } - - public void testCreateSSLContextFromConnectionURLParams() + public void testCreateSSLConnectionUsingConnectionURLParams() throws Exception { if (Boolean.getBoolean("profile.use_ssl")) - { + { + // Clear the ssl system properties + setSystemProperty("javax.net.ssl.keyStore", null); + setSystemProperty("javax.net.ssl.keyStorePassword", null); + setSystemProperty("javax.net.ssl.trustStore", null); + setSystemProperty("javax.net.ssl.trustStorePassword", null); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + "?ssl='true'&ssl_verify_hostname='true'" + "&key_store='%s'&key_store_password='%s'" + "&trust_store='%s'&trust_store_password='%s'" + "'"; - String keyStore = System.getProperty("javax.net.ssl.keyStore"); - String keyStorePass = System.getProperty("javax.net.ssl.keyStorePassword"); - String trustStore = System.getProperty("javax.net.ssl.trustStore"); - String trustStorePass = System.getProperty("javax.net.ssl.trustStorePassword"); + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT, + KEYSTORE,KEYSTORE_PASSWORD,TRUSTSTORE,TRUSTSTORE_PASSWORD); - url = String.format(url,System.getProperty("test.port.ssl"), - keyStore,keyStorePass,trustStore,trustStorePass); + AMQConnection con = new AMQConnection(url); + assertNotNull("connection should be successful", con); + Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); + assertNotNull("create session should be successful", ssn); + } + } + + public void testCreateSSLConnectionUsingSystemProperties() throws Exception + { + if (Boolean.getBoolean("profile.use_ssl")) + { + + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s?ssl='true''"; + + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT); - // temporarily set the trust/key store jvm args to something else - // to ensure we only read from the connection URL param. - System.setProperty("javax.net.ssl.trustStore","fessgsdgd"); - System.setProperty("javax.net.ssl.trustStorePassword","fessgsdgd"); - System.setProperty("javax.net.ssl.keyStore","fessgsdgd"); - System.setProperty("javax.net.ssl.keyStorePassword","fessgsdgd"); - try - { - AMQConnection con = new AMQConnection(url); - Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); - } - catch (Exception e) - { - fail("SSL Connection should be successful"); - } - finally - { - System.setProperty("javax.net.ssl.trustStore",trustStore); - System.setProperty("javax.net.ssl.trustStorePassword",trustStorePass); - System.setProperty("javax.net.ssl.keyStore",keyStore); - System.setProperty("javax.net.ssl.keyStorePassword",keyStorePass); - } + AMQConnection con = new AMQConnection(url); + assertNotNull("connection should be successful", con); + Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); + assertNotNull("create session should be successful", ssn); } } @@ -95,8 +105,8 @@ public class SSLTest extends QpidBrokerTestCase if (Boolean.getBoolean("profile.use_ssl")) { String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + - System.getProperty("test.port.ssl") + - "?ssl='true'&ssl_cert_alias='app1''"; + QpidBrokerTestCase.DEFAULT_SSL_PORT + + "?ssl='true'&ssl_cert_alias='" + CERT_ALIAS_APP1 + "''"; AMQTestConnection_0_10 con = new AMQTestConnection_0_10(url); Connection transportCon = con.getConnection(); @@ -105,8 +115,8 @@ public class SSLTest extends QpidBrokerTestCase con.close(); url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + - System.getProperty("test.port.ssl") + - "?ssl='true'&ssl_cert_alias='app2''"; + QpidBrokerTestCase.DEFAULT_SSL_PORT + + "?ssl='true'&ssl_cert_alias='" + CERT_ALIAS_APP2 + "''"; con = new AMQTestConnection_0_10(url); transportCon = con.getConnection(); @@ -116,12 +126,12 @@ public class SSLTest extends QpidBrokerTestCase } } - public void testVerifyHostName() + public void testVerifyHostNameWithIncorrectHostname() { if (Boolean.getBoolean("profile.use_ssl")) { String url = "amqp://guest:guest@test/?brokerlist='tcp://127.0.0.1:" + - System.getProperty("test.port.ssl") + + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; try @@ -140,42 +150,53 @@ public class SSLTest extends QpidBrokerTestCase } } - public void testVerifyLocalHost() + public void testVerifyLocalHost() throws Exception { if (Boolean.getBoolean("profile.use_ssl")) { String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + - System.getProperty("test.port.ssl") + + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; - - try - { - AMQConnection con = new AMQConnection(url); - } - catch (Exception e) - { - fail("Hostname verification should succeed"); - } - } + + AMQConnection con = new AMQConnection(url); + assertNotNull("connection should have been created", con); + } } - public void testVerifyLocalHostLocalDomain() + public void testVerifyLocalHostLocalDomain() throws Exception { if (Boolean.getBoolean("profile.use_ssl")) { String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost.localdomain:" + - System.getProperty("test.port.ssl") + + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; + + AMQConnection con = new AMQConnection(url); + assertNotNull("connection should have been created", con); + } + } + + public void testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly() throws Exception + { + if (Boolean.getBoolean("profile.use_ssl")) + { + // Clear the ssl system properties + setSystemProperty("javax.net.ssl.keyStore", null); + setSystemProperty("javax.net.ssl.keyStorePassword", null); + setSystemProperty("javax.net.ssl.trustStore", null); + setSystemProperty("javax.net.ssl.trustStorePassword", null); - try - { - AMQConnection con = new AMQConnection(url); - } - catch (Exception e) - { - fail("Hostname verification should succeed"); - } - + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + + "?ssl='true'&ssl_verify_hostname='true'" + + "&trust_store='%s'&trust_store_password='%s'" + + "'"; + + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT, TRUSTSTORE,TRUSTSTORE_PASSWORD); + + AMQConnection con = new AMQConnection(url); + assertNotNull("connection should be successful", con); + Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); + assertNotNull("create session should be successful", ssn); } } } diff --git a/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java b/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java new file mode 100644 index 0000000000..d7ee203fdf --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java @@ -0,0 +1,116 @@ +/* + * + * 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.xa; + +import javax.jms.XAConnection; +import javax.jms.XAConnectionFactory; +import javax.jms.XASession; +import javax.transaction.xa.XAResource; + +import org.apache.qpid.client.AMQConnectionFactory; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.util.FileUtils; + +public class XAResourceTest extends QpidBrokerTestCase +{ + + private static final String FACTORY_NAME = "default"; + private static final String ALT_FACTORY_NAME = "connection2"; + + /* + * Test with multiple XAResources originating from the same connection factory. XAResource(s) will be equal, + * as they originate from the same session. + */ + public void testIsSameRMSingleCF() throws Exception + { + XAConnectionFactory factory = getConnectionFactory(FACTORY_NAME); + XAConnection conn = factory.createXAConnection(); + XASession session = conn.createXASession(); + XAResource xaResource1 = session.getXAResource(); + XAResource xaResource2 = session.getXAResource(); + + assertEquals("XAResource objects not equal", xaResource1, xaResource2); + assertTrue("isSameRM not true for identical objects", xaResource1.isSameRM(xaResource2)); + + session.close(); + conn.close(); + } + + /* + * Test with multiple XAResources originating from different connection factory's and different sessions. XAResources will not be + * equal as they do not originate from the same session. As the UUID from the broker will be the same, isSameRM will be true. + * + */ + public void testIsSameRMMultiCF() throws Exception + { + startBroker(FAILING_PORT); + ConnectionURL url = getConnectionFactory(FACTORY_NAME).getConnectionURL(); + XAConnectionFactory factory = new AMQConnectionFactory(url); + XAConnectionFactory factory2 = new AMQConnectionFactory(url); + XAConnectionFactory factory3 = getConnectionFactory(ALT_FACTORY_NAME); + + XAConnection conn = factory.createXAConnection(); + XAConnection conn2 = factory2.createXAConnection(); + XAConnection conn3 = factory3.createXAConnection(); + + XASession session = conn.createXASession(); + XASession session2 = conn2.createXASession(); + XASession session3 = conn3.createXASession(); + + XAResource xaResource1 = session.getXAResource(); + XAResource xaResource2 = session2.getXAResource(); + XAResource xaResource3 = session3.getXAResource(); + + assertFalse("XAResource objects should not be equal", xaResource1.equals(xaResource2)); + assertTrue("isSameRM not true for identical objects", xaResource1.isSameRM(xaResource2)); + assertFalse("isSameRM true for XA Resources created by two different brokers", xaResource1.isSameRM(xaResource3)); + + conn.close(); + conn2.close(); + conn3.close(); + } + + @Override + public void stopBroker(int port) throws Exception + { + if (isBrokerPresent(port)) + { + super.stopBroker(port); + } + } + + @Override + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + // Ensure we shutdown any secondary brokers + stopBroker(FAILING_PORT); + FileUtils.deleteDirectory(System.getProperty("QPID_WORK") + "/" + getFailingPort()); + } + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java index 19657ef396..12a1682212 100644 --- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java @@ -68,61 +68,6 @@ public class ManagementActorLoggingTest extends AbstractTestLogging /** * Description: - * When a JMX Management connection is made then this will be logged out. - * - * Input: - * - * 1. Running Broker - * 2. Connect Management client via JMX - * Output: - * - * <date> MNG-1007 : Open <user> - * - * Validation Steps: - * 1. The MNG ID is correct - * 2. The user is correct - * - * On connection close a MNG-1008 is expected - * - * * <date> MNG-1008 : Close - * - * Validation Steps: - * 1. The MNG ID is correct - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - */ - public void testJMXManagementConsoleConnection() throws IOException - { - List<String> results = waitAndFindMatches("MNG-1007"); - - assertEquals("Unexpected Management Connection count", 1, results.size()); - - String log = getLogMessage(results, 0); - - validateMessageID("MNG-1007", log); - - assertTrue("User not in log message:" + log, log.endsWith(USER)); - // Extract the id from the log string - // MESSAGE [mng:1(rmi://169.24.29.116)] MNG-1007 : Open : User admin - int connectionID = Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + ""); - - results = findMatches("MNG-1008"); - - assertEquals("Unexpected Management Connection close count", 0, results.size()); - - _jmxUtils.close(); - _closed = true; - - results = waitAndFindMatches("MNG-1008"); - - assertEquals("Unexpected Management Connection count", 1, results.size()); - - assertEquals("Close does not have same id as open,", connectionID, - Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + "")); - } - - /** - * Description: * When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message. * Input: * @@ -161,7 +106,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging }); //Remove the connection close from any 0-10 connections - _monitor.reset(); + _monitor.markDiscardPoint(); // Get a managedConnection ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*"); @@ -202,7 +147,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging */ public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException { - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createExchange("test", getName(), "direct", false); @@ -226,7 +171,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException { //Remove any previous exchange declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createExchange("test", getName(), "topic", false); @@ -251,7 +196,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException { //Remove any previous exchange declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createExchange("test", getName(), "fanout", false); @@ -276,7 +221,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException { //Remove any previous exchange declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createExchange("test", getName(), "headers", false); @@ -320,7 +265,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException { //Remove any previous queue declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createQueue("test", getName(), null, false); @@ -363,7 +308,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testQueueDeleteViaManagementConsole() throws IOException, JMException { //Remove any previous queue declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createQueue("test", getName(), null, false); @@ -409,7 +354,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException { //Remove any previous queue declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createQueue("test", getName(), null, false); @@ -436,7 +381,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException { //Remove any previous queue declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createQueue("test", getName(), null, false); @@ -463,7 +408,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException { //Remove any previous queue declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createQueue("test", getName(), null, false); @@ -510,7 +455,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException { //Remove any previous queue declares - _monitor.reset(); + _monitor.markDiscardPoint(); _jmxUtils.createExchange("test", getName(), "direct", false); diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java new file mode 100644 index 0000000000..9839c6e475 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java @@ -0,0 +1,102 @@ +/* + * + * 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.management.jmx; + +import java.util.ArrayList; +import java.util.List; + +import javax.jms.Connection; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; + +/** + * Test enabling generation of message statistics on a per-connection basis. + */ +public class MessageConnectionStatisticsTest extends MessageStatisticsTestCase +{ + public void configureStatistics() throws Exception + { + // no statistics generation configured + } + + /** + * Test statistics on a single connection + */ + public void testEnablingStatisticsPerConnection() throws Exception + { + ManagedBroker vhost = _jmxUtils.getManagedBroker("test"); + + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + List<String> addresses = new ArrayList<String>(); + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived()); + assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled()); + + addresses.add(mc.getRemoteAddress()); + } + assertEquals("Incorrect vhost total", 0, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived()); + + Connection test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test"); + test.start(); + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + if (addresses.contains(mc.getRemoteAddress())) + { + continue; + } + mc.setStatisticsEnabled(true); + assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived()); + } + + sendUsing(test, 5, 200); + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + if (addresses.contains(mc.getRemoteAddress())) + { + assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived()); + assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled()); + } + else + { + assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived()); + assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled()); + } + } + assertEquals("Incorrect vhost total", 0, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived()); + assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled()); + + test.close(); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java new file mode 100644 index 0000000000..383c4c00a8 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java @@ -0,0 +1,162 @@ +/* + * + * 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.management.jmx; + +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; + +/** + * Test enabling generation of message statistics on a per-connection basis. + */ +public class MessageStatisticsConfigurationTest extends MessageStatisticsTestCase +{ + public void configureStatistics() throws Exception + { + setConfigurationProperty("statistics.generation.broker", Boolean.toString(getName().contains("Broker"))); + setConfigurationProperty("statistics.generation.virtualhosts", Boolean.toString(getName().contains("Virtualhost"))); + setConfigurationProperty("statistics.generation.connections", Boolean.toString(getName().contains("Connection"))); + } + + /** + * Just broker statistics. + */ + public void testGenerateBrokerStatistics() throws Exception + { + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived()); + assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled()); + } + + ManagedBroker vhost = _jmxUtils.getManagedBroker("test"); + assertEquals("Incorrect vhost data", 0, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived()); + assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled()); + + assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived()); + assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled()); + } + + /** + * Just virtualhost statistics. + */ + public void testGenerateVirtualhostStatistics() throws Exception + { + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived()); + assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled()); + } + + ManagedBroker vhost = _jmxUtils.getManagedBroker("test"); + assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived()); + assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled()); + + assertEquals("Incorrect server total messages", 0, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server total data", 0, _jmxUtils.getServerInformation().getTotalDataReceived()); + assertFalse("Server statistics should not be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled()); + } + + /** + * Just connection statistics. + */ + public void testGenerateConnectionStatistics() throws Exception + { + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived()); + assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled()); + } + + ManagedBroker vhost = _jmxUtils.getManagedBroker("test"); + assertEquals("Incorrect vhost data", 0, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived()); + assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled()); + + assertEquals("Incorrect server total messages", 0, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server total data", 0, _jmxUtils.getServerInformation().getTotalDataReceived()); + assertFalse("Server statistics should not be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled()); + } + + /** + * Both broker and virtualhost statistics. + */ + public void testGenerateBrokerAndVirtualhostStatistics() throws Exception + { + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived()); + assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled()); + } + + ManagedBroker vhost = _jmxUtils.getManagedBroker("test"); + assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived()); + assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled()); + + assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived()); + assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled()); + } + + /** + * Broker, virtualhost and connection statistics. + */ + public void testGenerateBrokerVirtualhostAndConnectionStatistics() throws Exception + { + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived()); + assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled()); + } + + ManagedBroker vhost = _jmxUtils.getManagedBroker("test"); + assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived()); + assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled()); + + assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived()); + assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled()); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java new file mode 100644 index 0000000000..c374d23473 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java @@ -0,0 +1,110 @@ +/* + * + * 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.management.jmx; + +import java.util.ArrayList; +import java.util.List; + +import javax.jms.Connection; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Session; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; + +/** + * Test statistics for delivery and receipt. + */ +public class MessageStatisticsDeliveryTest extends MessageStatisticsTestCase +{ + public void configureStatistics() throws Exception + { + setConfigurationProperty("statistics.generation.broker", "true"); + setConfigurationProperty("statistics.generation.virtualhosts", "true"); + setConfigurationProperty("statistics.generation.connections", "true"); + } + + public void testDeliveryAndReceiptStatistics() throws Exception + { + ManagedBroker vhost = _jmxUtils.getManagedBroker("test"); + + sendUsing(_test, 5, 200); + Thread.sleep(1000); + + List<String> addresses = new ArrayList<String>(); + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + assertEquals("Incorrect connection delivery total", 0, mc.getTotalMessagesDelivered()); + assertEquals("Incorrect connection delivery data", 0, mc.getTotalDataDelivered()); + assertEquals("Incorrect connection receipt total", 5, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection receipt data", 1000, mc.getTotalDataReceived()); + + addresses.add(mc.getRemoteAddress()); + } + + assertEquals("Incorrect vhost delivery total", 0, vhost.getTotalMessagesDelivered()); + assertEquals("Incorrect vhost delivery data", 0, vhost.getTotalDataDelivered()); + assertEquals("Incorrect vhost receipt total", 5, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost receipt data", 1000, vhost.getTotalDataReceived()); + + Connection test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test"); + test.start(); + receiveUsing(test, 5); + + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + if (addresses.contains(mc.getRemoteAddress())) + { + assertEquals("Incorrect connection delivery total", 0, mc.getTotalMessagesDelivered()); + assertEquals("Incorrect connection delivery data", 0, mc.getTotalDataDelivered()); + assertEquals("Incorrect connection receipt total", 5, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection receipt data", 1000, mc.getTotalDataReceived()); + } + else + { + assertEquals("Incorrect connection delivery total", 5, mc.getTotalMessagesDelivered()); + assertEquals("Incorrect connection delivery data", 1000, mc.getTotalDataDelivered()); + assertEquals("Incorrect connection receipt total", 0, mc.getTotalMessagesReceived()); + assertEquals("Incorrect connection receipt data", 0, mc.getTotalDataReceived()); + } + } + assertEquals("Incorrect vhost delivery total", 5, vhost.getTotalMessagesDelivered()); + assertEquals("Incorrect vhost delivery data", 1000, vhost.getTotalDataDelivered()); + assertEquals("Incorrect vhost receipt total", 5, vhost.getTotalMessagesReceived()); + assertEquals("Incorrect vhost receipt data", 1000, vhost.getTotalDataReceived()); + + test.close(); + } + + protected void receiveUsing(Connection con, int number) throws Exception + { + Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE); + createQueue(session); + MessageConsumer consumer = session.createConsumer(_queue); + for (int i = 0; i < number; i++) + { + Message msg = consumer.receive(1000); + assertNotNull("Message " + i + " was not received", msg); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java new file mode 100644 index 0000000000..180440c0d6 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java @@ -0,0 +1,90 @@ +/* + * + * 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.management.jmx; + +import java.util.List; + +import org.apache.qpid.util.LogMonitor; + +/** + * Test generation of message statistics reporting. + */ +public class MessageStatisticsReportingTest extends MessageStatisticsTestCase +{ + protected LogMonitor _monitor; + + public void configureStatistics() throws Exception + { + setConfigurationProperty("statistics.generation.broker", "true"); + setConfigurationProperty("statistics.generation.virtualhosts", "true"); + + if (getName().equals("testEnabledStatisticsReporting")) + { + setConfigurationProperty("statistics.reporting.period", "10"); + } + + _monitor = new LogMonitor(_outputFile); + } + + /** + * Test enabling reporting. + */ + public void testEnabledStatisticsReporting() throws Exception + { + sendUsing(_test, 10, 100); + sendUsing(_dev, 20, 100); + sendUsing(_local, 15, 100); + + Thread.sleep(10 * 1000); // 15s + + List<String> brokerStatsData = _monitor.findMatches("BRK-1008"); + List<String> brokerStatsMessages = _monitor.findMatches("BRK-1009"); + List<String> vhostStatsData = _monitor.findMatches("VHT-1003"); + List<String> vhostStatsMessages = _monitor.findMatches("VHT-1004"); + + assertEquals("Incorrect number of broker data stats log messages", 2, brokerStatsData.size()); + assertEquals("Incorrect number of broker message stats log messages", 2, brokerStatsMessages.size()); + assertEquals("Incorrect number of virtualhost data stats log messages", 6, vhostStatsData.size()); + assertEquals("Incorrect number of virtualhost message stats log messages", 6, vhostStatsMessages.size()); + } + + /** + * Test not enabling reporting. + */ + public void testNotEnabledStatisticsReporting() throws Exception + { + sendUsing(_test, 10, 100); + sendUsing(_dev, 20, 100); + sendUsing(_local, 15, 100); + + Thread.sleep(10 * 1000); // 15s + + List<String> brokerStatsData = _monitor.findMatches("BRK-1008"); + List<String> brokerStatsMessages = _monitor.findMatches("BRK-1009"); + List<String> vhostStatsData = _monitor.findMatches("VHT-1003"); + List<String> vhostStatsMessages = _monitor.findMatches("VHT-1004"); + + assertEquals("Incorrect number of broker data stats log messages", 0, brokerStatsData.size()); + assertEquals("Incorrect number of broker message stats log messages", 0, brokerStatsMessages.size()); + assertEquals("Incorrect number of virtualhost data stats log messages", 0, vhostStatsData.size()); + assertEquals("Incorrect number of virtualhost message stats log messages", 0, vhostStatsMessages.size()); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java new file mode 100644 index 0000000000..824ae41b97 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java @@ -0,0 +1,218 @@ +/* + * + * 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.management.jmx; + +import javax.jms.Connection; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; + +/** + * Test generation of message statistics. + */ +public class MessageStatisticsTest extends MessageStatisticsTestCase +{ + public void configureStatistics() throws Exception + { + setConfigurationProperty("statistics.generation.broker", "true"); + setConfigurationProperty("statistics.generation.virtualhosts", "true"); + setConfigurationProperty("statistics.generation.connections", "true"); + } + + /** + * Test message totals. + */ + public void testMessageTotals() throws Exception + { + sendUsing(_test, 10, 100); + sendUsing(_dev, 20, 100); + sendUsing(_local, 5, 100); + sendUsing(_local, 5, 100); + sendUsing(_local, 5, 100); + Thread.sleep(2000); + + ManagedBroker test = _jmxUtils.getManagedBroker("test"); + ManagedBroker dev = _jmxUtils.getManagedBroker("development"); + ManagedBroker local = _jmxUtils.getManagedBroker("localhost"); + + if (!isBroker010()) + { + long total = 0; + long data = 0; + for (ManagedConnection mc : _jmxUtils.getAllManagedConnections()) + { + total += mc.getTotalMessagesReceived(); + data += mc.getTotalDataReceived(); + } + assertEquals("Incorrect connection total", 45, total); + assertEquals("Incorrect connection data", 4500, data); + } + assertEquals("Incorrect server total", 45, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server data", 4500, _jmxUtils.getServerInformation().getTotalDataReceived()); + + if (!isBroker010()) + { + long testTotal = 0; + long testData = 0; + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + testTotal += mc.getTotalMessagesReceived(); + testData += mc.getTotalDataReceived(); + } + assertEquals("Incorrect test connection total", 10, testTotal); + assertEquals("Incorrect test connection data", 1000, testData); + } + assertEquals("Incorrect test vhost total", 10, test.getTotalMessagesReceived()); + assertEquals("Incorrect test vhost data", 1000, test.getTotalDataReceived()); + + if (!isBroker010()) + { + long devTotal = 0; + long devData = 0; + for (ManagedConnection mc : _jmxUtils.getManagedConnections("development")) + { + devTotal += mc.getTotalMessagesReceived(); + devData += mc.getTotalDataReceived(); + } + assertEquals("Incorrect test connection total", 20, devTotal); + assertEquals("Incorrect test connection data", 2000, devData); + } + assertEquals("Incorrect development total", 20, dev.getTotalMessagesReceived()); + assertEquals("Incorrect development data", 2000, dev.getTotalDataReceived()); + + if (!isBroker010()) + { + long localTotal = 0; + long localData = 0; + for (ManagedConnection mc : _jmxUtils.getManagedConnections("localhost")) + { + localTotal += mc.getTotalMessagesReceived(); + localData += mc.getTotalDataReceived(); + } + assertEquals("Incorrect test connection total", 15, localTotal); + assertEquals("Incorrect test connection data", 1500, localData); + } + assertEquals("Incorrect localhost total", 15, local.getTotalMessagesReceived()); + assertEquals("Incorrect localhost data", 1500, local.getTotalDataReceived()); + } + + /** + * Test message totals when a connection is closed. + */ + public void testMessageTotalsWithClosedConnections() throws Exception + { + Connection temp = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test"); + temp.start(); + + sendUsing(_test, 10, 100); + sendUsing(temp, 10, 100); + sendUsing(_test, 10, 100); + Thread.sleep(2000); + + temp.close(); + + ManagedBroker test = _jmxUtils.getManagedBroker("test"); + + if (!isBroker010()) + { + long total = 0; + long data = 0; + for (ManagedConnection mc : _jmxUtils.getAllManagedConnections()) + { + total += mc.getTotalMessagesReceived(); + data += mc.getTotalDataReceived(); + } + assertEquals("Incorrect active connection total", 20, total); + assertEquals("Incorrect active connection data", 2000, data); + } + assertEquals("Incorrect server total", 30, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server data", 3000, _jmxUtils.getServerInformation().getTotalDataReceived()); + + if (!isBroker010()) + { + long testTotal = 0; + long testData = 0; + for (ManagedConnection mc : _jmxUtils.getManagedConnections("test")) + { + testTotal += mc.getTotalMessagesReceived(); + testData += mc.getTotalDataReceived(); + } + assertEquals("Incorrect test active connection total", 20, testTotal); + assertEquals("Incorrect test active connection data", 20 * 100, testData); + } + assertEquals("Incorrect test vhost total", 30, test.getTotalMessagesReceived()); + assertEquals("Incorrect test vhost data", 30 * 100, test.getTotalDataReceived()); + } + + /** + * Test message peak rate generation. + */ + public void testMessagePeakRates() throws Exception + { + sendUsing(_test, 2, 10); + Thread.sleep(10000); + sendUsing(_dev, 4, 10); + Thread.sleep(10000); + + ManagedBroker test = _jmxUtils.getManagedBroker("test"); + ManagedBroker dev = _jmxUtils.getManagedBroker("development"); + + assertApprox("Incorrect test vhost peak messages", 0.2d, 1.0d, test.getPeakMessageReceiptRate()); + assertApprox("Incorrect test vhost peak data", 0.2d, 10.0d, test.getPeakDataReceiptRate()); + assertApprox("Incorrect dev vhost peak messages", 0.2d, 2.0d, dev.getPeakMessageReceiptRate()); + assertApprox("Incorrect dev vhost peak data", 0.2d, 20.0d, dev.getPeakDataReceiptRate()); + + assertApprox("Incorrect server peak messages", 0.2d, 2.0d, _jmxUtils.getServerInformation().getPeakMessageReceiptRate()); + assertApprox("Incorrect server peak data", 0.2d, 20.0d, _jmxUtils.getServerInformation().getPeakDataReceiptRate()); + } + + /** + * Test message totals when a vhost has its statistics reset + */ + public void testMessageTotalVhostReset() throws Exception + { + sendUsing(_test, 10, 10); + sendUsing(_dev, 10, 10); + Thread.sleep(2000); + + ManagedBroker test = _jmxUtils.getManagedBroker("test"); + ManagedBroker dev = _jmxUtils.getManagedBroker("development"); + + assertEquals("Incorrect test vhost total messages", 10, test.getTotalMessagesReceived()); + assertEquals("Incorrect test vhost total data", 100, test.getTotalDataReceived()); + assertEquals("Incorrect dev vhost total messages", 10, dev.getTotalMessagesReceived()); + assertEquals("Incorrect dev vhost total data", 100, dev.getTotalDataReceived()); + + assertEquals("Incorrect server total messages", 20, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server total data", 200, _jmxUtils.getServerInformation().getTotalDataReceived()); + + test.resetStatistics(); + + assertEquals("Incorrect test vhost total messages", 0, test.getTotalMessagesReceived()); + assertEquals("Incorrect test vhost total data", 0, test.getTotalDataReceived()); + assertEquals("Incorrect dev vhost total messages", 10, dev.getTotalMessagesReceived()); + assertEquals("Incorrect dev vhost total data", 100, dev.getTotalDataReceived()); + + assertEquals("Incorrect server total messages", 20, _jmxUtils.getServerInformation().getTotalMessagesReceived()); + assertEquals("Incorrect server total data", 200, _jmxUtils.getServerInformation().getTotalDataReceived()); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java new file mode 100644 index 0000000000..a5b3aa283c --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java @@ -0,0 +1,128 @@ +/* + * + * 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.management.jmx; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.test.utils.JMXTestUtils; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +/** + * Test generation of message statistics. + */ +public abstract class MessageStatisticsTestCase extends QpidBrokerTestCase +{ + protected static final String USER = "admin"; + + protected JMXTestUtils _jmxUtils; + protected Connection _test, _dev, _local; + protected String _queueName = "statistics"; + protected Destination _queue; + protected String _brokerUrl; + + @Override + public void setUp() throws Exception + { + _jmxUtils = new JMXTestUtils(this, USER, USER); + _jmxUtils.setUp(); + + configureStatistics(); + + super.setUp(); + + _brokerUrl = getBroker().toString(); + _test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test"); + _dev = new AMQConnection(_brokerUrl, USER, USER, "clientid", "development"); + _local = new AMQConnection(_brokerUrl, USER, USER, "clientid", "localhost"); + + _test.start(); + _dev.start(); + _local.start(); + + _jmxUtils.open(); + } + + protected void createQueue(Session session) throws AMQException, JMSException + { + _queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName); + if (!((AMQSession<?,?>) session).isQueueBound((AMQDestination) _queue)) + { + ((AMQSession<?,?>) session).createQueue(new AMQShortString(_queueName), false, true, false, null); + ((AMQSession<?,?>) session).declareAndBind((AMQDestination) new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName)); + } + } + + + @Override + public void tearDown() throws Exception + { + _jmxUtils.close(); + + _test.close(); + _dev.close(); + _local.close(); + + super.tearDown(); + } + + /** + * Configure statistics generation properties on the broker. + */ + public abstract void configureStatistics() throws Exception; + + protected void sendUsing(Connection con, int number, int size) throws Exception + { + Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE); + createQueue(session); + MessageProducer producer = session.createProducer(_queue); + String content = new String(new byte[size]); + TextMessage msg = session.createTextMessage(content); + for (int i = 0; i < number; i++) + { + producer.send(msg); + } + } + + /** + * Asserts that the actual value is within the expected value plus or + * minus the given error. + */ + public void assertApprox(String message, double error, double expected, double actual) + { + double min = expected * (1.0d - error); + double max = expected * (1.0d + error); + String assertion = String.format("%s: expected %f +/- %d%%, actual %f", + message, expected, (int) (error * 100.0d), actual); + assertTrue(assertion, actual > min && actual < max); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java index f9227c53ba..27b4de0a8e 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java @@ -70,13 +70,13 @@ public class BrokerStartupTest extends AbstractTestLogging { // This logging startup code only occurs when you run a Java broker, // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker() && isExternalBroker() && !isInternalBroker()) { //Remove test Log4j config from the commandline - _broker = _broker.substring(0, _broker.indexOf("-l")); + _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l")); // Add an invalid value - _broker += " -l invalid"; + _brokerCommand += " -l invalid"; // The broker has a built in default log4j configuration set up // so if the the broker cannot load the -l value it will use default diff --git a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java b/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java index d4c550bc08..6d379e14d8 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java @@ -61,21 +61,6 @@ public class ServerConfigurationFileTest extends QpidBrokerTestCase _serverConfig.getConfig().getProperty(property)); } - public void testProtectIOEnabled() throws ConfigurationException - { - validatePropertyDefinedInFile(ServerConfiguration.CONNECTOR_PROTECTIO_ENABLED); - } - - public void testProtectIOReadBufferLimitSize() throws ConfigurationException - { - validatePropertyDefinedInFile(ServerConfiguration.CONNECTOR_PROTECTIO_READ_BUFFER_LIMIT_SIZE); - } - - public void testProtectIOWriteBufferLimitSize() throws ConfigurationException - { - validatePropertyDefinedInFile(ServerConfiguration.CONNECTOR_PROTECTIO_WRITE_BUFFER_LIMIT_SIZE); - } - public void testStatusUpdates() throws ConfigurationException { validatePropertyDefinedInFile(ServerConfiguration.STATUS_UPDATES); diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java index 2d89d319d7..4a92f04b30 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java +++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java @@ -83,15 +83,9 @@ public class MessagingTestConfigProperties /** Holds the name of the default connection factory configuration property. */ public static final String CONNECTION_PROPNAME = "connectionfactory.broker"; - /** Defeins the default connection configuration. */ - public static final String CONNECTION_DEFAULT = "amqp://guest:guest@clientid/?brokerlist='vm://:1'"; - /** Holds the name of the property to get the test broker url from. */ public static final String BROKER_PROPNAME = "qpid.test.broker"; - /** Holds the default broker url for the test. */ - public static final String BROKER_DEFAULT = "vm://:1"; - /** Holds the name of the property to get the test broker virtual path. */ public static final String VIRTUAL_HOST_PROPNAME = "virtualHost"; @@ -274,7 +268,6 @@ public class MessagingTestConfigProperties static { defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT); - defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_DEFAULT); defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT); defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT); defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT); @@ -284,7 +277,6 @@ public class MessagingTestConfigProperties defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT); defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT); defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT); - defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT); defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT); defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT); defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT); diff --git a/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java b/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java index ec222ff03d..470fcefae3 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java @@ -20,58 +20,40 @@ */ package org.apache.qpid.server.failover; -import junit.framework.TestCase; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import org.apache.qpid.AMQConnectionClosedException; import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; -import org.apache.qpid.url.URLSyntaxException; +import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import java.util.concurrent.CountDownLatch; - -public class FailoverMethodTest extends InternalBrokerBaseCase implements ExceptionListener +public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionListener { private CountDownLatch _failoverComplete = new CountDownLatch(1); protected static final Logger _logger = LoggerFactory.getLogger(FailoverMethodTest.class); - @Override - public void createBroker() throws Exception - { - super.createBroker(); - TransportConnection.createVMBroker(ApplicationRegistry.DEFAULT_INSTANCE); - } - @Override - public void stopBroker() - { - TransportConnection.killVMBroker(ApplicationRegistry.DEFAULT_INSTANCE); - super.stopBroker(); - } /** * Test that the round robin method has the correct delays. - * The first connection to vm://:1 will work but the localhost connection should fail but the duration it takes + * The first connection will work but the localhost connection should fail but the duration it takes * to report the failure is what is being tested. * - * @throws URLSyntaxException - * @throws InterruptedException - * @throws JMSException */ - public void testFailoverRoundRobinDelay() throws URLSyntaxException, InterruptedException, JMSException + public void testFailoverRoundRobinDelay() throws Exception { - //note: The VM broker has no connect delay and the default 1 retry + //note: The first broker has no connect delay and the default 1 retry // while the tcp:localhost broker has 3 retries with a 2s connect delay String connectionString = "amqp://guest:guest@/test?brokerlist=" + - "'vm://:" + ApplicationRegistry.DEFAULT_INSTANCE + + "'tcp://:" + getPort() + ";tcp://localhost:5670?connectdelay='2000',retries='3''"; AMQConnectionURL url = new AMQConnectionURL(connectionString); @@ -79,13 +61,15 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except try { long start = System.currentTimeMillis(); - AMQConnection connection = new AMQConnection(url, null); + AMQConnection connection = new AMQConnection(url); connection.setExceptionListener(this); stopBroker(); - _failoverComplete.await(); + _failoverComplete.await(30, TimeUnit.SECONDS); + assertEquals("failoverLatch was not decremented in given timeframe", + 0, _failoverComplete.getCount()); long end = System.currentTimeMillis(); @@ -112,23 +96,24 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except } } - public void testFailoverSingleDelay() throws URLSyntaxException, AMQVMBrokerCreationException, - InterruptedException, JMSException + public void testFailoverSingleDelay() throws Exception { - String connectionString = "amqp://guest:guest@/test?brokerlist='vm://:1?connectdelay='2000',retries='3''"; + String connectionString = "amqp://guest:guest@/test?brokerlist='tcp://localhost:" + getPort() + "?connectdelay='2000',retries='3''"; AMQConnectionURL url = new AMQConnectionURL(connectionString); try { long start = System.currentTimeMillis(); - AMQConnection connection = new AMQConnection(url, null); + AMQConnection connection = new AMQConnection(url); connection.setExceptionListener(this); stopBroker(); - _failoverComplete.await(); + _failoverComplete.await(30, TimeUnit.SECONDS); + assertEquals("failoverLatch was not decremented in given timeframe", + 0, _failoverComplete.getCount()); long end = System.currentTimeMillis(); @@ -144,8 +129,8 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except assertTrue("Failover took less than 6 seconds", duration > 6000); // Ensure we don't have delays before initial connection and reconnection. - // We allow 1 second for initial connection and failover logic on top of 6s of sleep. - assertTrue("Failover took more than 7 seconds:(" + duration + ")", duration < 7000); + // We allow 3 second for initial connection and failover logic on top of 6s of sleep. + assertTrue("Failover took more than 9 seconds:(" + duration + ")", duration < 9000); } catch (AMQException e) { @@ -155,11 +140,15 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except public void onException(JMSException e) { - if (e.getLinkedException() instanceof AMQDisconnectedException) + if (e.getLinkedException() instanceof AMQDisconnectedException || e.getLinkedException() instanceof AMQConnectionClosedException) { _logger.debug("Received AMQDisconnectedException"); _failoverComplete.countDown(); } + else + { + _logger.error("Unexpected underlying exception", e.getLinkedException()); + } } /** @@ -168,28 +157,37 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except * * Test validates that there is a connection delay as required on initial * connection. - * - * @throws URLSyntaxException - * @throws AMQVMBrokerCreationException - * @throws InterruptedException - * @throws JMSException */ - public void testNoFailover() throws URLSyntaxException, AMQVMBrokerCreationException, - InterruptedException, JMSException + public void testNoFailover() throws Exception { + if (!isInternalBroker()) + { + // QPID-3359 + // These tests always used to be inVM tests, then QPID-2815, with removal of ivVM, + // converted the test to use QpidBrokerTestCase. However, since then we notice this + // test fails on slower CI boxes. It turns out the test design is *extremely* + // sensitive the length of time the broker takes to start up. + // + // Making the test a same-VM test to temporarily avoid the issue. In long term, test + // needs redesigned to avoid the issue. + return; + } + int CONNECT_DELAY = 2000; - String connectionString = "amqp://guest:guest@/test?brokerlist='vm://:1?connectdelay='" + CONNECT_DELAY + "'," + + String connectionString = "amqp://guest:guest@/test?brokerlist='tcp://localhost:" + getPort() + "?connectdelay='" + CONNECT_DELAY + "'," + "retries='3'',failover='nofailover'"; + AMQConnectionURL url = new AMQConnectionURL(connectionString); + Thread brokerStart = null; try { //Kill initial broker stopBroker(); //Create a thread to start the broker asynchronously - Thread brokerStart = new Thread(new Runnable() + brokerStart = new Thread(new Runnable() { public void run() { @@ -198,7 +196,7 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except //Wait before starting broker // The wait should allow atleast 1 retries to fail before broker is ready Thread.sleep(750); - createBroker(); + startBroker(); } catch (Exception e) { @@ -212,9 +210,8 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except brokerStart.start(); long start = System.currentTimeMillis(); - //Start the connection so it will use the retries - AMQConnection connection = new AMQConnection(url, null); + AMQConnection connection = new AMQConnection(url); long end = System.currentTimeMillis(); @@ -228,13 +225,16 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except //Ensure we collect the brokerStart thread brokerStart.join(); + brokerStart = null; start = System.currentTimeMillis(); //Kill connection stopBroker(); - _failoverComplete.await(); + _failoverComplete.await(30, TimeUnit.SECONDS); + assertEquals("failoverLatch was not decremented in given timeframe", + 0, _failoverComplete.getCount()); end = System.currentTimeMillis(); @@ -249,6 +249,23 @@ public class FailoverMethodTest extends InternalBrokerBaseCase implements Except { fail(e.getMessage()); } + finally + { + // Guard against the case where the broker took too long to start + // and the initial connection failed to be formed. + if (brokerStart != null) + { + brokerStart.join(); + } + } + } + + public void stopBroker(int port) throws Exception + { + if (isBrokerPresent(port)) + { + super.stopBroker(port); + } } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java b/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java index 4c2758241e..fd33266414 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java @@ -20,13 +20,10 @@ */ package org.apache.qpid.server.failover; -import org.apache.mina.common.WriteTimeoutException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.FailoverBaseCase; -import org.apache.qpid.AMQConnectionClosedException; import javax.jms.Destination; import javax.jms.Message; @@ -34,6 +31,7 @@ import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -195,7 +193,7 @@ public class MessageDisappearWithIOExceptionTest extends FailoverBaseCase implem // Send IO Exception - causing failover _connection.getProtocolHandler(). - exception(new WriteTimeoutException("WriteTimeoutException to cause failover.")); + exception(new IOException("IOException to cause failover.")); // Verify Failover occured through ConnectionListener assertTrue("Failover did not occur", diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java index f56f428f0b..484c2afeb5 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java @@ -349,7 +349,7 @@ public class AbstractTestLogging extends QpidBrokerTestCase public boolean waitForMessage(String message, long wait) throws FileNotFoundException, IOException { - return _monitor.waitForMessage(message, wait, true); + return _monitor.waitForMessage(message, wait); } /** diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java index 05aaf16af1..aef98b8a2a 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java @@ -46,7 +46,7 @@ public class AlertingTest extends AbstractTestLogging { // Update the configuration to make our virtualhost Persistent. makeVirtualHostPersistent(VIRTUALHOST); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.expiredMessageCheckPeriod", "5000"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "5000"); _numMessages = 50; @@ -136,7 +136,7 @@ public class AlertingTest extends AbstractTestLogging stopBroker(); // Rest the monitoring clearing the current output file. - _monitor.reset(); + _monitor.markDiscardPoint(); startBroker(); wasAlertFired(); } @@ -169,14 +169,14 @@ public class AlertingTest extends AbstractTestLogging stopBroker(); - _monitor.reset(); + _monitor.markDiscardPoint(); // Change max message count to 5, start broker and make sure that that's triggered at the right time setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5"); startBroker(); - if (!isExternalBroker()) + if (isInternalBroker()) { assertEquals("Alert Max Msg Count is not correct", 5, ApplicationRegistry.getInstance().getVirtualHostRegistry(). getVirtualHost(VIRTUALHOST).getQueueRegistry().getQueue(new AMQShortString(_destination.getQueueName())). diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java index 97914f84a5..be2da128bc 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java @@ -55,7 +55,7 @@ public class BindingLoggingTest extends AbstractTestLogging { super.setUp(); //Ignore broker startup messages - _monitor.reset(); + _monitor.markDiscardPoint(); _connection = getConnection(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java index 8fd2c085c3..7969ffc059 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java @@ -21,6 +21,8 @@ package org.apache.qpid.server.logging; import junit.framework.AssertionFailedError; + +import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.Main; import org.apache.qpid.transport.ConnectionException; import org.apache.qpid.util.LogMonitor; @@ -151,12 +153,12 @@ public class BrokerLoggingTest extends AbstractTestLogging { // This logging startup code only occurs when you run a Java broker, // that broker must be started via Main so not an InVM broker. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker() && isExternalBroker() && !isInternalBroker()) { String TESTID = "BRK-1007"; //Remove test Log4j config from the commandline - _broker = _broker.substring(0, _broker.indexOf("-l")); + _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l")); startBroker(); @@ -203,7 +205,7 @@ public class BrokerLoggingTest extends AbstractTestLogging 1, findMatches(TESTID).size()); //3 - String defaultLog4j = _configFile.getParent() + "/" + Main.DEFAULT_LOG_CONFIG_FILENAME; + String defaultLog4j = System.getProperty(QPID_HOME) + "/" + BrokerOptions.DEFAULT_LOG_CONFIG_FILE; assertTrue("Log4j file(" + defaultLog4j + ") details not correctly logged:" + getMessageString(log), getMessageString(log).endsWith(defaultLog4j)); @@ -240,12 +242,11 @@ public class BrokerLoggingTest extends AbstractTestLogging */ public void testBrokerStartupCustomLog4j() throws Exception { - // This logging startup code only occurs when you run a Java broker, - // that broker must be started via Main so not an InVM broker. + // This logging startup code only occurs when you run a Java broker if (isJavaBroker() && isExternalBroker()) { // Get custom -l value used during testing for the broker startup - String customLog4j = _broker.substring(_broker.indexOf("-l") + 2); + String customLog4j = _brokerCommand.substring(_brokerCommand.indexOf("-l") + 2).trim(); String TESTID = "BRK-1007"; @@ -518,7 +519,7 @@ public class BrokerLoggingTest extends AbstractTestLogging setConfigurationProperty("connector.ssl.keyStorePath", getConfigurationStringProperty("management.ssl.keyStorePath")); setConfigurationProperty("connector.ssl.keyStorePassword", getConfigurationStringProperty("management.ssl.keyStorePassword")); - Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.sslport")); + Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.ssl.port")); startBroker(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java index 02d0d6f334..1b2ec9c092 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java @@ -77,7 +77,7 @@ public class ChannelLoggingTest extends AbstractTestLogging validateMessageID("CHN-1001", log); assertEquals("Incorrect Channel in actor:"+fromActor(log), isBroker010()? 0 : 1, getChannelID(fromActor(log))); - if (isBroker08()) + if (!isBroker010()) { // Wait to ensure that the CHN-1004 message is logged waitForMessage("CHN-1004"); @@ -89,7 +89,7 @@ public class ChannelLoggingTest extends AbstractTestLogging log = getLogMessage(results, 0); // MESSAGE [con:0(guest@anonymous(3273383)/test)/ch:1] CHN-1004 : Prefetch Size (bytes) {0,number} : Count {1,number} validateMessageID("CHN-1004", log); - assertEquals("Incorrect Channel in actor:"+fromActor(log), isBroker010()? 0 : 1, getChannelID(fromActor(log))); + assertEquals("Incorrect Channel in actor:"+fromActor(log), 1, getChannelID(fromActor(log))); assertTrue("Prefetch Count not correct",getMessageString(fromMessage(log)).endsWith("Count "+PREFETCH)); } diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java index 16c529316a..d45bde2d98 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java @@ -496,7 +496,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest stopBroker(); // Clear our monitor - _monitor.reset(); + _monitor.markDiscardPoint(); startBroker(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java index 32adc49521..602bdb66b5 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java @@ -58,7 +58,7 @@ public class DurableQueueLoggingTest extends AbstractTestLogging { super.setUp(); //Ensure we only have logs from our test - _monitor.reset(); + _monitor.markDiscardPoint(); _connection = getConnection(); _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java index 1e48f34f99..ec96f778f6 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java @@ -20,6 +20,16 @@ */ package org.apache.qpid.server.logging; +import java.io.IOException; +import java.util.List; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQSession_0_10; import org.apache.qpid.framing.AMQFrame; @@ -28,13 +38,6 @@ import org.apache.qpid.framing.ExchangeDeleteBody; import org.apache.qpid.framing.ExchangeDeleteOkBody; import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0; -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Queue; -import javax.jms.Session; -import java.io.IOException; -import java.util.List; - /** * Exchange * @@ -122,7 +125,7 @@ public class ExchangeLoggingTest extends AbstractTestLogging public void testExchangeCreate() throws JMSException, IOException { //Ignore broker startup messages - _monitor.reset(); + _monitor.markDiscardPoint(); _session.createConsumer(_queue); // Ensure we have received the EXH log msg. @@ -176,7 +179,7 @@ public class ExchangeLoggingTest extends AbstractTestLogging public void testExchangeDelete() throws Exception, IOException { //Ignore broker startup messages - _monitor.reset(); + _monitor.markDiscardPoint(); //create the exchange by creating a consumer _session.createConsumer(_queue); @@ -214,4 +217,38 @@ public class ExchangeLoggingTest extends AbstractTestLogging } + public void testDiscardedMessage() throws Exception + { + //Ignore broker startup messages + _monitor.markDiscardPoint(); + + if (!isBroker010()) + { + // Default 0-8..-0-9-1 behaviour is for messages to be rejected (returned to client). + setTestClientSystemProperty("qpid.default_mandatory", "false"); + } + + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Do not create consumer so queue is not created and message will be discarded. + final MessageProducer producer = _session.createProducer(_queue); + + // Sending message + final TextMessage msg = _session.createTextMessage("msg"); + producer.send(msg); + + final String expectedMessageBody = "Discarded Message : Name: " + _name + " Routing Key: " + _queue.getQueueName(); + + // Ensure we have received the EXH log msg. + waitForMessage("EXH-1003"); + + List<String> results = findMatches(EXH_PREFIX); + assertEquals("Result set larger than expected.", 2, results.size()); + + final String log = getLogMessage(results, 1); + validateMessageID("EXH-1003", log); + + final String message = getMessageString(fromMessage(log)); + assertEquals("Log Message not as expected", expectedMessageBody, message); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java index 595c0d5f35..24e6aa4207 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.logging; import junit.framework.AssertionFailedError; +import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.util.LogMonitor; import java.util.List; @@ -76,9 +77,8 @@ public class ManagementLoggingTest extends AbstractTestLogging */ public void testManagementStartupEnabled() throws Exception { - // This test only works on external java brokers due to the fact that - // Management is disabled on InVM brokers. - if (isJavaBroker() && isExternalBroker()) + // This test only works on java brokers + if (isJavaBroker()) { startBrokerAndCreateMonitor(true, false); @@ -130,9 +130,7 @@ public class ManagementLoggingTest extends AbstractTestLogging */ public void testManagementStartupDisabled() throws Exception { - // This test only works on external java brokers due to the fact that - // Management is disabled on InVM brokers. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { startBrokerAndCreateMonitor(false, false); @@ -191,9 +189,7 @@ public class ManagementLoggingTest extends AbstractTestLogging */ public void testManagementStartupRMIEntries() throws Exception { - // This test only works on external java brokers due to the fact that - // Management is disabled on InVM brokers. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { startBrokerAndCreateMonitor(true, false); @@ -211,7 +207,7 @@ public class ManagementLoggingTest extends AbstractTestLogging validateMessageID("MNG-1002", log); //Check the RMI Registry port is as expected - int mPort = getPort() + (DEFAULT_MANAGEMENT_PORT - DEFAULT_PORT); + int mPort = getManagementPort(getPort()); assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log), getMessageString(log).endsWith(String.valueOf(mPort))); @@ -222,7 +218,7 @@ public class ManagementLoggingTest extends AbstractTestLogging // We expect the RMI Registry port (the defined 'management port') to be // 100 lower than the JMX RMIConnector Server Port (the actual JMX server) - int jmxPort = mPort + 100; + int jmxPort = mPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET; assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log), getMessageString(log).endsWith(String.valueOf(jmxPort))); } @@ -250,9 +246,7 @@ public class ManagementLoggingTest extends AbstractTestLogging */ public void testManagementStartupSSLKeystore() throws Exception { - // This test only works on external java brokers due to the fact that - // Management is disabled on InVM brokers. - if (isJavaBroker() && isExternalBroker()) + if (isJavaBroker()) { startBrokerAndCreateMonitor(true, true); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java index b8a42c0ab3..76ebda0ebd 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java @@ -53,7 +53,7 @@ public class QueueLoggingTest extends AbstractTestLogging { super.setUp(); //Remove broker startup logging messages - _monitor.reset(); + _monitor.markDiscardPoint(); _connection = getConnection(); _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java index 6e156f091e..b6efe53580 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java @@ -58,7 +58,7 @@ public class SubscriptionLoggingTest extends AbstractTestLogging { super.setUp(); //Remove broker startup logging messages - _monitor.reset(); + _monitor.markDiscardPoint(); _connection = getConnection(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java index a5aec3edce..398c83a8d8 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java @@ -78,21 +78,10 @@ public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase implements Conn BrokerDetails details = _connectionURL.getBrokerDetails(0); - // Due to the problem with SingleServer delaying on all connection - // attempts. So using a high retry value. - if (_broker.equals(VM)) - { - // Local testing suggests InVM restart takes under a second - details.setProperty(BrokerDetails.OPTIONS_RETRY, "5"); - details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "200"); - } - else - { - // This will attempt to failover for 3 seconds. - // Local testing suggests failover takes 2 seconds - details.setProperty(BrokerDetails.OPTIONS_RETRY, "10"); - details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "500"); - } + // This will attempt to failover for 3 seconds. + // Local testing suggests failover takes 2 seconds + details.setProperty(BrokerDetails.OPTIONS_RETRY, "10"); + details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "500"); super.setUp(); } diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java new file mode 100644 index 0000000000..277e84d66d --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java @@ -0,0 +1,247 @@ +/* + * + * 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.queue; + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.Session; + +import org.apache.log4j.Logger; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class MultipleTransactedBatchProducerTest extends QpidBrokerTestCase +{ + private static final Logger _logger = Logger.getLogger(MultipleTransactedBatchProducerTest.class); + + private static final int MESSAGE_COUNT = 1000; + private static final int BATCH_SIZE = 50; + private static final int NUM_PRODUCERS = 2; + private static final int NUM_CONSUMERS = 3; + private static final Random RANDOM = new Random(); + + private CountDownLatch _receivedLatch; + private String _queueName; + + private volatile String _failMsg; + + public void setUp() throws Exception + { + //debug level logging often makes this test pass artificially, turn the level down to info. + setSystemProperty("amqj.server.logging.level", "INFO"); + _receivedLatch = new CountDownLatch(MESSAGE_COUNT * NUM_PRODUCERS); + setConfigurationProperty("management.enabled", "true"); + super.setUp(); + _queueName = getTestQueueName(); + _failMsg = null; + } + + /** + * When there are multiple producers submitting batches of messages to a given + * queue using transacted sessions, it is highly probable that concurrent + * enqueue() activity will occur and attempt delivery of their message to the + * same subscription. In this scenario it is likely that one of the attempts + * will succeed and the other will result in use of the deliverAsync() method + * to start a queue Runner and ensure delivery of the message. + * + * A defect within the processQueue() method used by the Runner would mean that + * delivery of these messages may not occur, should the Runner stop before all + * messages have been processed. Such a defect was discovered and found to be + * most visible when Selectors are used such that one and only one subscription + * can/will accept any given message, but multiple subscriptions are present, + * and one of the earlier subscriptions receives more messages than the others. + * + * This test is to validate that the processQueue() method is able to correctly + * deliver all of the messages present for asynchronous delivery to subscriptions, + * by utilising multiple batch transacted producers to create the scenario and + * ensure all messages are received by a consumer. + */ + public void testMultipleBatchedProducersWithMultipleConsumersUsingSelectors() throws Exception + { + String selector1 = ("(\"" + _queueName +"\" % " + NUM_CONSUMERS + ") = 0"); + String selector2 = ("(\"" + _queueName +"\" % " + NUM_CONSUMERS + ") = 1"); + String selector3 = ("(\"" + _queueName +"\" % " + NUM_CONSUMERS + ") = 2"); + + //create consumers + Connection conn1 = getConnection(); + conn1.setExceptionListener(new ExceptionHandler("conn1")); + Session sess1 = conn1.createSession(true, Session.SESSION_TRANSACTED); + MessageConsumer cons1 = sess1.createConsumer(sess1.createQueue(_queueName), selector1); + cons1.setMessageListener(new Cons(sess1,"consumer1")); + + Connection conn2 = getConnection(); + conn2.setExceptionListener(new ExceptionHandler("conn2")); + Session sess2 = conn2.createSession(true, Session.SESSION_TRANSACTED); + MessageConsumer cons2 = sess2.createConsumer(sess2.createQueue(_queueName), selector2); + cons2.setMessageListener(new Cons(sess2,"consumer2")); + + Connection conn3 = getConnection(); + conn3.setExceptionListener(new ExceptionHandler("conn3")); + Session sess3 = conn3.createSession(true, Session.SESSION_TRANSACTED); + MessageConsumer cons3 = sess3.createConsumer(sess3.createQueue(_queueName), selector3); + cons3.setMessageListener(new Cons(sess3,"consumer3")); + + conn1.start(); + conn2.start(); + conn3.start(); + + //create producers + Connection connA = getConnection(); + connA.setExceptionListener(new ExceptionHandler("connA")); + Connection connB = getConnection(); + connB.setExceptionListener(new ExceptionHandler("connB")); + Thread producer1 = new Thread(new ProducerThread(connA, _queueName, "producer1")); + Thread producer2 = new Thread(new ProducerThread(connB, _queueName, "producer2")); + + producer1.start(); + Thread.sleep(10); + producer2.start(); + + //await delivery of the messages + int timeout = isBrokerStorePersistent() ? 300 : 75; + boolean result = _receivedLatch.await(timeout, TimeUnit.SECONDS); + + assertNull("Test failed because: " + String.valueOf(_failMsg), _failMsg); + assertTrue("Some of the messages were not all recieved in the given timeframe, remaining count was: "+_receivedLatch.getCount(), + result); + + } + + @Override + public Message createNextMessage(Session session, int msgCount) throws JMSException + { + Message message = super.createNextMessage(session,msgCount); + + //bias at least 50% of the messages to the first consumers selector because + //the issue presents itself primarily when an earlier subscription completes + //delivery after the later subscriptions + int val; + if (msgCount % 2 == 0) + { + val = 0; + } + else + { + val = RANDOM.nextInt(Integer.MAX_VALUE); + } + + message.setIntProperty(_queueName, val); + + return message; + } + + private class Cons implements MessageListener + { + private Session _sess; + private String _desc; + + public Cons(Session sess, String desc) + { + _sess = sess; + _desc = desc; + } + + public void onMessage(Message message) + { + _receivedLatch.countDown(); + int msgCount = 0; + int msgID = 0; + try + { + msgCount = message.getIntProperty(INDEX); + msgID = message.getIntProperty(_queueName); + } + catch (JMSException e) + { + _logger.error(_desc + " received exception: " + e.getMessage(), e); + failAsyncTest(e.getMessage()); + } + + _logger.info("Consumer received message:"+ msgCount + " with ID: " + msgID); + + try + { + _sess.commit(); + } + catch (JMSException e) + { + _logger.error(_desc + " received exception: " + e.getMessage(), e); + failAsyncTest(e.getMessage()); + } + } + } + + private class ProducerThread implements Runnable + { + private Connection _conn; + private String _dest; + private String _desc; + + public ProducerThread(Connection conn, String dest, String desc) + { + _conn = conn; + _dest = dest; + _desc = desc; + } + + public void run() + { + try + { + Session session = _conn.createSession(true, Session.SESSION_TRANSACTED); + sendMessage(session, session.createQueue(_dest), MESSAGE_COUNT, BATCH_SIZE); + } + catch (Exception e) + { + _logger.error(_desc + " received exception: " + e.getMessage(), e); + failAsyncTest(e.getMessage()); + } + } + } + + private class ExceptionHandler implements javax.jms.ExceptionListener + { + private String _desc; + + public ExceptionHandler(String description) + { + _desc = description; + } + + public void onException(JMSException e) + { + _logger.error(_desc + " received exception: " + e.getMessage(), e); + failAsyncTest(e.getMessage()); + } + } + + private void failAsyncTest(String msg) + { + _logger.error("Failing test because: " + msg); + _failMsg = msg; + } +}
\ No newline at end of file diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java index 6203e8a194..2ce1251eab 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.queue; import junit.framework.TestCase; import junit.framework.Assert; import org.apache.log4j.Logger; -import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQQueue; diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java index f78b327209..a724e6c66e 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java @@ -64,7 +64,7 @@ public class ProducerFlowControlTest extends AbstractTestLogging _jmxUtilConnected=false; super.setUp(); - _monitor.reset(); + _monitor.markDiscardPoint(); producerConnection = getConnection(); producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java index 74f50e8659..aeeecb2dff 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java @@ -110,18 +110,13 @@ public class QueueDepthWithSelectorTest extends QpidBrokerTestCase try { Connection connection = getConnection(); - Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + AMQSession session = (AMQSession)connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - Thread.sleep(2000); - long queueDepth = ((AMQSession) session).getQueueDepth((AMQDestination) _queue); + long queueDepth = session.getQueueDepth((AMQDestination) _queue); assertEquals("Session reports Queue depth not as expected", expectedDepth, queueDepth); connection.close(); } - catch (InterruptedException e) - { - fail(e.getMessage()); - } catch (AMQException e) { fail(e.getMessage()); @@ -158,6 +153,10 @@ public class QueueDepthWithSelectorTest extends QpidBrokerTestCase { assertTrue("Message " + msgId + " not received.", msgIdRecevied[msgId]); } + + //do a synchronous op to ensure the acks are processed + //on the broker before proceeding + ((AMQSession)_clientSession).sync(); } /** diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java index f845ff1214..32b0185f88 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java @@ -52,7 +52,6 @@ import org.apache.qpid.url.URLSyntaxException; * * TODO move the pre broker-startup setup method invocation code to {@link QpidBrokerTestCase} * - * @see SimpleACLTest * @see ExternalACLTest * @see ExternalACLFileTest * @see ExternalACLJMXTest @@ -65,10 +64,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements protected CountDownLatch _exceptionReceived; /** Override this to return the name of the configuration XML file. */ - public String getConfig() - { - return "config-systests-acl.xml"; - } + public abstract String getConfig(); /** Override this to setup external ACL files for virtual hosts. */ public List<String> getHostList() @@ -87,14 +83,8 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements @Override public void setUp() throws Exception { - if (QpidHome == null) - { - fail("QPID_HOME not set"); - } - // Initialise ACLs. - _configFile = new File(QpidHome, "etc" + File.separator + getConfig()); - + _configFile = new File("build" + File.separator + "etc" + File.separator + getConfig()); // Initialise ACL files for (String virtualHost : getHostList()) { @@ -160,7 +150,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements */ public void setUpACLFile(String virtualHost) throws IOException, ConfigurationException { - String path = QpidHome + File.separator + "etc"; + String path = "build" + File.separator + "etc"; String className = StringUtils.substringBeforeLast(getClass().getSimpleName().toLowerCase(), "test"); String testName = StringUtils.substringAfter(getName(), "test").toLowerCase(); @@ -200,7 +190,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements } PrintWriter out = new PrintWriter(new FileWriter(aclFile)); - out.println(String.format("# %s", _testName)); + out.println(String.format("# %s", getTestName())); for (String line : rules) { out.println(line); diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java index 4603cc1862..254e1fe6ac 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java @@ -18,11 +18,620 @@ */ package org.apache.qpid.server.security.acl; +import java.io.IOException; import java.util.Arrays; import java.util.List; -public class ExternalACLTest extends SimpleACLTest +import javax.jms.Connection; +import javax.jms.DeliveryMode; +import javax.jms.IllegalStateException; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.jms.Topic; +import javax.jms.TopicSubscriber; +import javax.naming.NamingException; + +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.url.URLSyntaxException; + +/** + * Tests the V2 ACLs. The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using + * JMS to contact the broker. + */ +public class ExternalACLTest extends AbstractACLTestCase { + public void testAccessAuthorizedSuccess() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + + //Do something to show connection is active. + sess.rollback(); + + conn.close(); + } + catch (Exception e) + { + fail("Connection was not created due to:" + e); + } + } + + public void testAccessVhostAuthorisedGuestSuccess() throws IOException, Exception + { + //The 'guest' user has no access to the 'test' vhost, as tested below in testAccessNoRights(), and so + //is unable to perform actions such as connecting (and by extension, creating a queue, and consuming + //from a queue etc). In order to test the vhost-wide 'access' ACL right, the 'guest' user has been given + //this right in the 'test2' vhost. + + try + { + //get a connection to the 'test2' vhost using the guest user and perform various actions. + Connection conn = getConnection("test2", "guest", "guest"); + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + conn.start(); + + //create Queues and consumers for each + Queue namedQueue = sess.createQueue("vhostAccessCreatedQueue" + getTestQueueName()); + Queue tempQueue = sess.createTemporaryQueue(); + MessageConsumer consumer = sess.createConsumer(namedQueue); + MessageConsumer tempConsumer = sess.createConsumer(tempQueue); + + //send a message to each queue (also causing an exchange declare) + MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null); + ((org.apache.qpid.jms.MessageProducer) sender).send(namedQueue, sess.createTextMessage("test"), + DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); + ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"), + DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); + + //consume the messages from the queues + consumer.receive(2000); + tempConsumer.receive(2000); + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testAccessNoRightsFailure() throws Exception + { + try + { + Connection conn = getConnection("test", "guest", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + sess.rollback(); + + fail("Connection was created."); + } + catch (JMSException e) + { + // JMSException -> linkedException -> cause = AMQException (403 or 320) + Exception linkedException = e.getLinkedException(); + assertNotNull("There was no linked exception", linkedException); + Throwable cause = linkedException.getCause(); + assertNotNull("Cause was null", cause); + assertTrue("Wrong linked exception type", cause instanceof AMQException); + AMQConstant errorCode = isBroker010() ? AMQConstant.CONNECTION_FORCED : AMQConstant.ACCESS_REFUSED; + assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode()); + } + } + + public void testClientDeleteQueueSuccess() throws Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + + // create kipper + Topic kipper = sess.createTopic("kipper"); + TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); + + subscriber.close(); + sess.unsubscribe("kipper"); + + //Do something to show connection is active. + sess.rollback(); + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testServerDeleteQueueFailure() throws Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + conn.start(); + + // create kipper + Topic kipper = sess.createTopic("kipper"); + TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); + + subscriber.close(); + sess.unsubscribe("kipper"); + + //Do something to show connection is active. + sess.rollback(); + conn.close(); + } + catch (JMSException e) + { + // JMSException -> linedException = AMQException.403 + check403Exception(e.getLinkedException()); + } + } + + public void testClientConsumeFromTempQueueSuccess() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createTemporaryQueue()); + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testClientConsumeFromNamedQueueFailure() throws NamingException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createQueue("IllegalQueue")); + + fail("Test failed as consumer was created."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testClientCreateTemporaryQueueSuccess() throws JMSException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + //Create Temporary Queue - can't use the createTempQueue as QueueName is null. + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("doesnt_matter_as_autodelete_means_tmp"), + true, false, false); + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testClientCreateNamedQueueFailure() throws NamingException, JMSException, AMQException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + //Create a Named Queue + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); + + fail("Test failed as Queue creation succeded."); + //conn will be automatically closed + } + catch (AMQException e) + { + check403Exception(e); + } + } + + public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); + + conn.start(); + + MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue")); + + sender.send(sess.createTextMessage("test")); + + //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. + sess.commit(); + + conn.close(); + } + catch (Exception e) + { + fail("Test publish failed:" + e); + } + } + + public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null); + + Queue queue = sess.createQueue("example.RequestQueue"); + + // Send a message that we will wait to be sent, this should give the broker time to process the msg + // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not + // queue existence. + ((org.apache.qpid.jms.MessageProducer) sender).send(queue, sess.createTextMessage("test"), + DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); + + conn.close(); + } + catch (Exception e) + { + fail("Test publish failed:" + e); + } + } + + public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null); + + Queue queue = session.createQueue("Invalid"); + + // Send a message that we will wait to be sent, this should give the broker time to close the connection + // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not + // queue existence. + ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"), + DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); + + // Test the connection with a valid consumer + // This may fail as the session may be closed before the queue or the consumer created. + Queue temp = session.createTemporaryQueue(); + + session.createConsumer(temp).close(); + + //Connection should now be closed and will throw the exception caused by the above send + conn.close(); + + fail("Close is not expected to succeed."); + } + catch (IllegalStateException e) + { + _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createQueue("example.RequestQueue")); + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception + { + try + { + Connection conn = getConnection("test", "client", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createQueue("Invalid")); + + fail("Test failed as consumer was created."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + sess.createConsumer(sess.createTemporaryQueue()); + + fail("Test failed as consumer was created."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + //Create Temporary Queue + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("example.RequestQueue"), false, false, false); + + conn.close(); + } + catch (Exception e) + { + fail("Test failed due to:" + e.getMessage()); + } + } + + public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + + Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + //Create a Named Queue + ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); + + fail("Test failed as creation succeded."); + } + catch (Exception e) + { + check403Exception(e); + } + } + + public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + session.createTemporaryQueue(); + + fail("Test failed as creation succeded."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception + { + try + { + Connection connection = getConnection("test", "server", "guest"); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + connection.start(); + + ((AMQSession<?, ?>) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"), + true, false, false); + + fail("Test failed as creation succeded."); + } + catch (Exception e) + { + check403Exception(e); + } + } + + /** + * This test uses both the cilent and sender to validate that the Server is able to publish to a temporary queue. + * The reason the client must be involved is that the Server is unable to create its own Temporary Queues. + * + * @throws AMQException + * @throws URLSyntaxException + * @throws JMSException + */ + public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception + { + //Set up the Server + Connection serverConnection = getConnection("test", "server", "guest"); + + Session serverSession = serverConnection.createSession(true, Session.SESSION_TRANSACTED); + + Queue requestQueue = serverSession.createQueue("example.RequestQueue"); + + MessageConsumer server = serverSession.createConsumer(requestQueue); + + serverConnection.start(); + + //Set up the consumer + Connection clientConnection = getConnection("test", "client", "guest"); + + //Send a test mesage + Session clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + Queue responseQueue = clientSession.createTemporaryQueue(); + + MessageConsumer clientResponse = clientSession.createConsumer(responseQueue); + + clientConnection.start(); + + Message request = clientSession.createTextMessage("Request"); + + assertNotNull("Response Queue is null", responseQueue); + + request.setJMSReplyTo(responseQueue); + + clientSession.createProducer(requestQueue).send(request); + + try + { + Message msg = null; + + msg = server.receive(2000); + + while (msg != null && !((TextMessage) msg).getText().equals("Request")) + { + msg = server.receive(2000); + } + + assertNotNull("Message not received", msg); + + assertNotNull("Reply-To is Null", msg.getJMSReplyTo()); + + MessageProducer sender = serverSession.createProducer(msg.getJMSReplyTo()); + + sender.send(serverSession.createTextMessage("Response")); + + //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. + serverSession.commit(); + + //Ensure Response is received. + Message clientResponseMsg = clientResponse.receive(2000); + assertNotNull("Client did not receive response message,", clientResponseMsg); + assertEquals("Incorrect message received", "Response", ((TextMessage) clientResponseMsg).getText()); + + } + catch (Exception e) + { + fail("Test publish failed:" + e); + } + finally + { + try + { + serverConnection.close(); + } + finally + { + clientConnection.close(); + } + } + } + + public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception + { + try + { + Connection conn = getConnection("test", "server", "guest"); + + ((AMQConnection) conn).setConnectionListener(this); + + Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + + conn.start(); + + MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null); + + Queue queue = session.createQueue("Invalid"); + + // Send a message that we will wait to be sent, this should give the broker time to close the connection + // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not + // queue existence. + ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"), + DeliveryMode.NON_PERSISTENT, 0, 0L, false, false); + + // Test the connection with a valid consumer + // This may not work as the session may be closed before the queue or consumer creation can occur. + // The correct JMSexception with linked error will only occur when the close method is recevied whilst in + // the failover safe block + session.createConsumer(session.createQueue("example.RequestQueue")).close(); + + //Connection should now be closed and will throw the exception caused by the above send + conn.close(); + + fail("Close is not expected to succeed."); + } + catch (IllegalStateException e) + { + _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); + } + catch (JMSException e) + { + check403Exception(e.getLinkedException()); + } + } + + @Override public String getConfig() { diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java deleted file mode 100644 index a50817e659..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java +++ /dev/null @@ -1,644 +0,0 @@ -/* - * 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.security.acl; - -import java.io.IOException; - -import javax.jms.Connection; -import javax.jms.DeliveryMode; -import javax.jms.IllegalStateException; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; -import javax.jms.Topic; -import javax.jms.TopicSubscriber; -import javax.naming.NamingException; - -import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.url.URLSyntaxException; - -/** - * Basic access control list tests. - * - * These tests require an access control security plugin to be configured in the broker, and carry out various broker - * operations that will succeed or fail depending on the user and virtual host. See the {@code config-systests-acl-setup.xml} - * configuration file for the SimpleXML version of the ACLs used by the Java broker only, or the various {@code .txt} - * files in the system tests directory for the external version 3 ACL files used by both the Java and C++ brokers. - * <p> - * This class can be extended and the {@link #getConfig()} method overridden to run the same tests with a different type - * of access control mechanism. Extension classes should differ only in the configuration file used, but extra tests can be - * added that are specific to a particular configuration. - * <p> - * The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using - * JMS to contact the broker. - * - * @see ExternalACLTest - */ -public class SimpleACLTest extends AbstractACLTestCase -{ - public void testAccessAuthorizedSuccess() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - - //Do something to show connection is active. - sess.rollback(); - - conn.close(); - } - catch (Exception e) - { - fail("Connection was not created due to:" + e); - } - } - - public void testAccessVhostAuthorisedGuestSuccess() throws IOException, Exception - { - //The 'guest' user has no access to the 'test' vhost, as tested below in testAccessNoRights(), and so - //is unable to perform actions such as connecting (and by extension, creating a queue, and consuming - //from a queue etc). In order to test the vhost-wide 'access' ACL right, the 'guest' user has been given - //this right in the 'test2' vhost. - - try - { - //get a connection to the 'test2' vhost using the guest user and perform various actions. - Connection conn = getConnection("test2", "guest", "guest"); - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - conn.start(); - - //create Queues and consumers for each - Queue namedQueue = sess.createQueue("vhostAccessCreatedQueue" + getTestQueueName()); - Queue tempQueue = sess.createTemporaryQueue(); - MessageConsumer consumer = sess.createConsumer(namedQueue); - MessageConsumer tempConsumer = sess.createConsumer(tempQueue); - - //send a message to each queue (also causing an exchange declare) - MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null); - ((org.apache.qpid.jms.MessageProducer) sender).send(namedQueue, sess.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - - //consume the messages from the queues - consumer.receive(2000); - tempConsumer.receive(2000); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testAccessNoRightsFailure() throws Exception - { - try - { - Connection conn = getConnection("test", "guest", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - sess.rollback(); - - fail("Connection was created."); - } - catch (JMSException e) - { - // JMSException -> linkedException -> cause = AMQException (403 or 320) - Exception linkedException = e.getLinkedException(); - assertNotNull("There was no linked exception", linkedException); - Throwable cause = linkedException.getCause(); - assertNotNull("Cause was null", cause); - assertTrue("Wrong linked exception type", cause instanceof AMQException); - AMQConstant errorCode = isBroker010() ? AMQConstant.CONTEXT_IN_USE : AMQConstant.ACCESS_REFUSED; - assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode()); - } - } - - public void testClientDeleteQueueSuccess() throws Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - - // create kipper - Topic kipper = sess.createTopic("kipper"); - TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); - - subscriber.close(); - sess.unsubscribe("kipper"); - - //Do something to show connection is active. - sess.rollback(); - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testServerDeleteQueueFailure() throws Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - conn.start(); - - // create kipper - Topic kipper = sess.createTopic("kipper"); - TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper"); - - subscriber.close(); - sess.unsubscribe("kipper"); - - //Do something to show connection is active. - sess.rollback(); - conn.close(); - } - catch (JMSException e) - { - // JMSException -> linedException = AMQException.403 - check403Exception(e.getLinkedException()); - } - } - - public void testClientConsumeFromTempQueueSuccess() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createTemporaryQueue()); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testClientConsumeFromNamedQueueFailure() throws NamingException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createQueue("IllegalQueue")); - - fail("Test failed as consumer was created."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testClientCreateTemporaryQueueSuccess() throws JMSException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - //Create Temporary Queue - can't use the createTempQueue as QueueName is null. - ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("doesnt_matter_as_autodelete_means_tmp"), - true, false, false); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testClientCreateNamedQueueFailure() throws NamingException, JMSException, AMQException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - //Create a Named Queue - ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); - - fail("Test failed as Queue creation succeded."); - //conn will be automatically closed - } - catch (AMQException e) - { - check403Exception(e); - } - } - - public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(true, Session.SESSION_TRANSACTED); - - conn.start(); - - MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue")); - - sender.send(sess.createTextMessage("test")); - - //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. - sess.commit(); - - conn.close(); - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } - } - - public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null); - - Queue queue = sess.createQueue("example.RequestQueue"); - - // Send a message that we will wait to be sent, this should give the broker time to process the msg - // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not - // queue existence. - ((org.apache.qpid.jms.MessageProducer) sender).send(queue, sess.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - - conn.close(); - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } - } - - public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null); - - Queue queue = session.createQueue("Invalid"); - - // Send a message that we will wait to be sent, this should give the broker time to close the connection - // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not - // queue existence. - ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - - // Test the connection with a valid consumer - // This may fail as the session may be closed before the queue or the consumer created. - Queue temp = session.createTemporaryQueue(); - - session.createConsumer(temp).close(); - - //Connection should now be closed and will throw the exception caused by the above send - conn.close(); - - fail("Close is not expected to succeed."); - } - catch (IllegalStateException e) - { - _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createQueue("example.RequestQueue")); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception - { - try - { - Connection conn = getConnection("test", "client", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createQueue("Invalid")); - - fail("Test failed as consumer was created."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - sess.createConsumer(sess.createTemporaryQueue()); - - fail("Test failed as consumer was created."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - //Create Temporary Queue - ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("example.RequestQueue"), false, false, false); - - conn.close(); - } - catch (Exception e) - { - fail("Test failed due to:" + e.getMessage()); - } - } - - public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - - Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - //Create a Named Queue - ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false); - - fail("Test failed as creation succeded."); - } - catch (Exception e) - { - check403Exception(e); - } - } - - public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - session.createTemporaryQueue(); - - fail("Test failed as creation succeded."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } - - public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception - { - try - { - Connection connection = getConnection("test", "server", "guest"); - - Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - connection.start(); - - ((AMQSession<?, ?>) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"), - true, false, false); - - fail("Test failed as creation succeded."); - } - catch (Exception e) - { - check403Exception(e); - } - } - - /** - * This test uses both the cilent and sender to validate that the Server is able to publish to a temporary queue. - * The reason the client must be involved is that the Server is unable to create its own Temporary Queues. - * - * @throws AMQException - * @throws URLSyntaxException - * @throws JMSException - */ - public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception - { - //Set up the Server - Connection serverConnection = getConnection("test", "server", "guest"); - - Session serverSession = serverConnection.createSession(true, Session.SESSION_TRANSACTED); - - Queue requestQueue = serverSession.createQueue("example.RequestQueue"); - - MessageConsumer server = serverSession.createConsumer(requestQueue); - - serverConnection.start(); - - //Set up the consumer - Connection clientConnection = getConnection("test", "client", "guest"); - - //Send a test mesage - Session clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - Queue responseQueue = clientSession.createTemporaryQueue(); - - MessageConsumer clientResponse = clientSession.createConsumer(responseQueue); - - clientConnection.start(); - - Message request = clientSession.createTextMessage("Request"); - - assertNotNull("Response Queue is null", responseQueue); - - request.setJMSReplyTo(responseQueue); - - clientSession.createProducer(requestQueue).send(request); - - try - { - Message msg = null; - - msg = server.receive(2000); - - while (msg != null && !((TextMessage) msg).getText().equals("Request")) - { - msg = server.receive(2000); - } - - assertNotNull("Message not received", msg); - - assertNotNull("Reply-To is Null", msg.getJMSReplyTo()); - - MessageProducer sender = serverSession.createProducer(msg.getJMSReplyTo()); - - sender.send(serverSession.createTextMessage("Response")); - - //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker. - serverSession.commit(); - - //Ensure Response is received. - Message clientResponseMsg = clientResponse.receive(2000); - assertNotNull("Client did not receive response message,", clientResponseMsg); - assertEquals("Incorrect message received", "Response", ((TextMessage) clientResponseMsg).getText()); - - } - catch (Exception e) - { - fail("Test publish failed:" + e); - } - finally - { - try - { - serverConnection.close(); - } - finally - { - clientConnection.close(); - } - } - } - - public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception - { - try - { - Connection conn = getConnection("test", "server", "guest"); - - ((AMQConnection) conn).setConnectionListener(this); - - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - conn.start(); - - MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null); - - Queue queue = session.createQueue("Invalid"); - - // Send a message that we will wait to be sent, this should give the broker time to close the connection - // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not - // queue existence. - ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"), - DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true); - - // Test the connection with a valid consumer - // This may not work as the session may be closed before the queue or consumer creation can occur. - // The correct JMSexception with linked error will only occur when the close method is recevied whilst in - // the failover safe block - session.createConsumer(session.createQueue("example.RequestQueue")).close(); - - //Connection should now be closed and will throw the exception caused by the above send - conn.close(); - - fail("Close is not expected to succeed."); - } - catch (IllegalStateException e) - { - _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error."); - } - catch (JMSException e) - { - check403Exception(e.getLinkedException()); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java index f40e95885d..044a0af335 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java @@ -35,16 +35,8 @@ public class FirewallConfigTest extends QpidBrokerTestCase @Override protected void setUp() throws Exception { - // do setup - final String QPID_HOME = System.getProperty("QPID_HOME"); - - if (QPID_HOME == null) - { - fail("QPID_HOME not set"); - } - // Setup initial config file. - _configFile = new File(QPID_HOME, "etc/config-systests-firewall.xml"); + _configFile = new File("build/etc/config-systests-firewall.xml"); // Setup temporary config file _tmpConfig = File.createTempFile("config-systests-firewall", ".xml"); @@ -85,14 +77,8 @@ public class FirewallConfigTest extends QpidBrokerTestCase public void testVhostAllowBrokerDeny() throws Exception { - if (_broker.equals(VM)) - { - //No point running this test with an InVM broker as the - //firewall plugin only functions for TCP connections. - return; - } - _configFile = new File(System.getProperty("QPID_HOME"), "etc/config-systests-firewall-2.xml"); + _configFile = new File("build/etc/config-systests-firewall-2.xml"); super.setUp(); @@ -125,14 +111,7 @@ public class FirewallConfigTest extends QpidBrokerTestCase public void testVhostDenyBrokerAllow() throws Exception { - if (_broker.equals(VM)) - { - //No point running this test with an InVM broker as the - //firewall plugin only functions for TCP connections. - return; - } - - _configFile = new File(System.getProperty("QPID_HOME"), "etc/config-systests-firewall-3.xml"); + _configFile = new File("build/etc/config-systests-firewall-3.xml"); super.setUp(); @@ -277,11 +256,6 @@ public class FirewallConfigTest extends QpidBrokerTestCase private void testFirewall(boolean initial, boolean inVhost, Runnable restartOrReload) throws Exception { - if (_broker.equals(VM)) - { - // No point running this test in a vm broker - return; - } writeFirewallFile(initial, inVhost); setConfigurationProperty("management.enabled", String.valueOf(true)); diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java index 13a9dd73b8..107c730a7e 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java @@ -94,7 +94,7 @@ public class CancelTest extends QpidBrokerTestCase browser.close(); MessageConsumer consumer = _clientSession.createConsumer(_queue); - assertNotNull( consumer.receive() ); + assertNotNull( consumer.receive(2000l) ); consumer.close(); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java index 97d825177c..d6caf05d33 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java @@ -59,7 +59,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase _queue = _clientSession.createQueue(getTestQueueName()); _clientSession.createConsumer(_queue).close(); - + //Ensure there are no messages on the queue to start with. checkQueueDepth(0); } @@ -490,7 +490,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase } } - assertTrue("We should get atleast " + messages + " msgs.", msgCount >= messages); + assertTrue("We should get atleast " + messages + " msgs (found " + msgCount +").", msgCount >= messages); if (_logger.isDebugEnabled()) { diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java index 51589c705f..8c3c247e2b 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java @@ -25,25 +25,37 @@ import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; +import java.util.Properties; + import javax.jms.Connection; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.QueueReceiver; +import javax.jms.QueueSession; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.Topic; +import javax.jms.TopicSession; +import javax.jms.TopicSubscriber; import javax.naming.Context; +import javax.naming.InitialContext; import org.apache.qpid.client.AMQAnyDestination; +import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQSession_0_10; +import org.apache.qpid.client.message.QpidMessageProperties; import org.apache.qpid.client.messaging.address.Node.ExchangeNode; import org.apache.qpid.client.messaging.address.Node.QueueNode; import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; import org.apache.qpid.messaging.Address; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.transport.ExecutionErrorCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -187,9 +199,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs())); } - - // todo add tests for delete options - + public void testCreateQueue() throws Exception { Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); @@ -202,7 +212,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "durable: true ," + "x-declare: " + "{" + - "auto-delete: true," + + "exclusive: true," + "arguments: {" + "'qpid.max_size': 1000," + "'qpid.max_count': 100" + @@ -218,6 +228,9 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "}"; AMQDestination dest = new AMQAnyDestination(addr); MessageConsumer cons = jmsSession.createConsumer(dest); + cons.close(); + + // Even if the consumer is closed the queue and the bindings should be intact. assertTrue("Queue not created as expected",( (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); @@ -246,12 +259,44 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase (AMQSession_0_10)jmsSession).isQueueBound("amq.match", dest.getAddressName(),null, args)); + MessageProducer prod = jmsSession.createProducer(dest); + prod.send(jmsSession.createTextMessage("test")); + + MessageConsumer cons2 = jmsSession.createConsumer(jmsSession.createQueue("ADDR:my-queue")); + Message m = cons2.receive(1000); + assertNotNull("Should receive message sent to my-queue",m); + assertEquals("The subject set in the message is incorrect","hello",m.getStringProperty(QpidMessageProperties.QPID_SUBJECT)); } public void testCreateExchange() throws Exception { + createExchangeImpl(false, false); + } + + /** + * Verify creating an exchange via an Address, with supported + * exchange-declare arguments. + */ + public void testCreateExchangeWithArgs() throws Exception + { + createExchangeImpl(true, false); + } + + /** + * Verify that when creating an exchange via an Address, if a + * nonsense argument is specified the broker throws an execution + * exception back on the session with NOT_IMPLEMENTED status. + */ + public void testCreateExchangeWithNonsenseArgs() throws Exception + { + createExchangeImpl(true, true); + } + + private void createExchangeImpl(final boolean withExchangeArgs, + final boolean useNonsenseArguments) throws Exception + { Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); - + String addr = "ADDR:my-exchange/hello; " + "{ " + "create: always, " + @@ -261,17 +306,36 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "x-declare: " + "{ " + "type:direct, " + - "auto-delete: true, " + - "arguments: {" + - "'qpid.msg_sequence': 1, " + - "'qpid.ive': 1" + - "}" + + "auto-delete: true" + + createExchangeArgsString(withExchangeArgs, useNonsenseArguments) + "}" + "}" + "}"; AMQDestination dest = new AMQAnyDestination(addr); - MessageConsumer cons = jmsSession.createConsumer(dest); + + MessageConsumer cons; + try + { + cons = jmsSession.createConsumer(dest); + if(useNonsenseArguments) + { + fail("Expected execution exception during exchange declare did not occur"); + } + } + catch(JMSException e) + { + if(useNonsenseArguments && e.getCause().getMessage().contains(ExecutionErrorCode.NOT_IMPLEMENTED.toString())) + { + //expected because we used an argument which the broker doesn't have functionality + //for. We can't do the rest of the test as a result of the exception, just stop. + return; + } + else + { + fail("Unexpected exception whilst creating consumer: " + e); + } + } assertTrue("Exchange not created as expected",( (AMQSession_0_10)jmsSession).isExchangeExist(dest, (ExchangeNode)dest.getTargetNode() , true)); @@ -286,16 +350,66 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase cons = jmsSession.createConsumer(dest); } + private String createExchangeArgsString(final boolean withExchangeArgs, + final boolean useNonsenseArguments) + { + String argsString; + + if(withExchangeArgs && useNonsenseArguments) + { + argsString = ", arguments: {" + + "'abcd.1234.wxyz': 1, " + + "}"; + } + else if(withExchangeArgs) + { + argsString = ", arguments: {" + + "'qpid.msg_sequence': 1, " + + "'qpid.ive': 1" + + "}"; + } + else + { + argsString = ""; + } + + return argsString; + } + + public void checkQueueForBindings(Session jmsSession, AMQDestination dest,String headersBinding) throws Exception + { + assertTrue("Queue not created as expected",( + (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + + assertTrue("Queue not bound as expected",( + (AMQSession_0_10)jmsSession).isQueueBound("", + dest.getAddressName(),dest.getAddressName(), null)); + + assertTrue("Queue not bound as expected",( + (AMQSession_0_10)jmsSession).isQueueBound("amq.direct", + dest.getAddressName(),"test", null)); + + assertTrue("Queue not bound as expected",( + (AMQSession_0_10)jmsSession).isQueueBound("amq.topic", + dest.getAddressName(),"a.#", null)); + + Address a = Address.parse(headersBinding); + assertTrue("Queue not bound as expected",( + (AMQSession_0_10)jmsSession).isQueueBound("amq.match", + dest.getAddressName(),null, a.getOptions())); + } + + /** + * Test goal: Verifies that a producer and consumer creation triggers the correct + * behavior for x-bindings specified in node props. + */ public void testBindQueueWithArgs() throws Exception { - Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); + Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); String headersBinding = "{exchange: 'amq.match', arguments: {x-match: any, dep: sales, loc: CA}}"; - String addr = "ADDR:my-queue/hello; " + - "{ " + - "create: always, " + - "node: " + + String addr = "node: " + "{" + "durable: true ," + "x-declare: " + @@ -310,28 +424,14 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "}" + "}"; - AMQDestination dest = new AMQAnyDestination(addr); - MessageConsumer cons = jmsSession.createConsumer(dest); - - assertTrue("Queue not created as expected",( - (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); - - assertTrue("Queue not bound as expected",( - (AMQSession_0_10)jmsSession).isQueueBound("", - dest.getAddressName(),dest.getAddressName(), null)); - assertTrue("Queue not bound as expected",( - (AMQSession_0_10)jmsSession).isQueueBound("amq.direct", - dest.getAddressName(),"test", null)); - - assertTrue("Queue not bound as expected",( - (AMQSession_0_10)jmsSession).isQueueBound("amq.topic", - dest.getAddressName(),"a.#", null)); + AMQDestination dest1 = new AMQAnyDestination("ADDR:my-queue/hello; {create: receiver, " +addr); + MessageConsumer cons = jmsSession.createConsumer(dest1); + checkQueueForBindings(jmsSession,dest1,headersBinding); - Address a = Address.parse(headersBinding); - assertTrue("Queue not bound as expected",( - (AMQSession_0_10)jmsSession).isQueueBound("amq.match", - dest.getAddressName(),null, a.getOptions())); + AMQDestination dest2 = new AMQAnyDestination("ADDR:my-queue2/hello; {create: sender, " +addr); + MessageProducer prod = jmsSession.createProducer(dest2); + checkQueueForBindings(jmsSession,dest2,headersBinding); } /** @@ -467,39 +567,6 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } /** - * Test goal: Verifies that and address based destination can be used successfully - * as a reply to. - */ - public void testAddressBasedReplyTo() throws Exception - { - Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); - - String addr = "ADDR:amq.direct/x512; {create: receiver, " + - "link : {name : 'MY.RESP.QUEUE', " + - "x-declare : { auto-delete: true, exclusive: true, " + - "arguments : {'qpid.max_size': 1000, 'qpid.policy_type': ring }} } }"; - - Destination replyTo = new AMQAnyDestination(addr); - Destination dest =new AMQAnyDestination("ADDR:amq.direct/Hello"); - - MessageConsumer cons = jmsSession.createConsumer(dest); - MessageProducer prod = jmsSession.createProducer(dest); - Message m = jmsSession.createTextMessage("Hello"); - m.setJMSReplyTo(replyTo); - prod.send(m); - - Message msg = cons.receive(1000); - assertNotNull("consumer should have received the message",msg); - - MessageConsumer replyToCons = jmsSession.createConsumer(replyTo); - MessageProducer replyToProd = jmsSession.createProducer(msg.getJMSReplyTo()); - replyToProd.send(jmsSession.createTextMessage("reply")); - - Message replyToMsg = replyToCons.receive(1000); - assertNotNull("The reply to consumer should have got the message",replyToMsg); - } - - /** * Test goal: Verifies that session.createQueue method * works as expected both with the new and old addressing scheme. */ @@ -520,7 +587,22 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase cons.close(); // Using the ADDR method + // default case queue = ssn.createQueue("ADDR:my-queue2"); + try + { + prod = ssn.createProducer(queue); + fail("The client should throw an exception, since there is no queue present in the broker"); + } + catch(Exception e) + { + String s = "The name 'my-queue2' supplied in the address " + + "doesn't resolve to an exchange or a queue"; + assertEquals(s,e.getCause().getCause().getMessage()); + } + + // explicit create case + queue = ssn.createQueue("ADDR:my-queue2; {create: sender}"); prod = ssn.createProducer(queue); cons = ssn.createConsumer(queue); assertTrue("my-queue2 was not created as expected",( @@ -547,11 +629,25 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase } /** - * Test goal: Verifies that session.creatTopic method - * works as expected both with the new and old addressing scheme. + * Test goal: Verifies that session.creatTopic method works as expected + * both with the new and old addressing scheme. */ public void testSessionCreateTopic() throws Exception { + sessionCreateTopicImpl(false); + } + + /** + * Test goal: Verifies that session.creatTopic method works as expected + * both with the new and old addressing scheme when adding exchange arguments. + */ + public void testSessionCreateTopicWithExchangeArgs() throws Exception + { + sessionCreateTopicImpl(true); + } + + private void sessionCreateTopicImpl(boolean withExchangeArgs) throws Exception + { Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); // Using the BURL method @@ -571,7 +667,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase prod.send(ssn.createTextMessage("test")); assertNotNull("consumer should receive a message",cons.receive(1000)); cons.close(); - + String addr = "ADDR:vehicles/bus; " + "{ " + "create: always, " + @@ -581,11 +677,8 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "x-declare: " + "{ " + "type:direct, " + - "auto-delete: true, " + - "arguments: {" + - "'qpid.msg_sequence': 1, " + - "'qpid.ive': 1" + - "}" + + "auto-delete: true" + + createExchangeArgsString(withExchangeArgs, false) + "}" + "}, " + "link: {name : my-topic, " + @@ -697,7 +790,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase public void testSubscriptionForSameDestination() throws Exception { Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); - Destination dest = ssn.createTopic("ADDR:amq.topic/foo"); + Destination dest = ssn.createTopic("ADDR:amq.topic/foo; {link:{durable:true}}"); MessageConsumer consumer1 = ssn.createConsumer(dest); MessageConsumer consumer2 = ssn.createConsumer(dest); MessageProducer prod = ssn.createProducer(dest); @@ -796,4 +889,297 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase { } } + + public void testQueueReceiversAndTopicSubscriber() throws Exception + { + Queue queue = new AMQAnyDestination("ADDR:my-queue; {create: always}"); + Topic topic = new AMQAnyDestination("ADDR:amq.topic/test"); + + QueueSession qSession = ((AMQConnection)_connection).createQueueSession(false, Session.AUTO_ACKNOWLEDGE); + QueueReceiver receiver = qSession.createReceiver(queue); + + TopicSession tSession = ((AMQConnection)_connection).createTopicSession(false, Session.AUTO_ACKNOWLEDGE); + TopicSubscriber sub = tSession.createSubscriber(topic); + + Session ssn = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageProducer prod1 = ssn.createProducer(ssn.createQueue("ADDR:my-queue")); + prod1.send(ssn.createTextMessage("test1")); + + MessageProducer prod2 = ssn.createProducer(ssn.createTopic("ADDR:amq.topic/test")); + prod2.send(ssn.createTextMessage("test2")); + + Message msg1 = receiver.receive(); + assertNotNull(msg1); + assertEquals("test1",((TextMessage)msg1).getText()); + + Message msg2 = sub.receive(); + assertNotNull(msg2); + assertEquals("test2",((TextMessage)msg2).getText()); + } + + public void testDurableSubscriber() throws Exception + { + Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); + + Properties props = new Properties(); + props.setProperty("java.naming.factory.initial", "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"); + props.setProperty("destination.address1", "ADDR:amq.topic"); + props.setProperty("destination.address2", "ADDR:amq.direct/test"); + String addrStr = "ADDR:amq.topic/test; {link:{name: my-topic," + + "x-bindings:[{key:'NYSE.#'},{key:'NASDAQ.#'},{key:'CNTL.#'}]}}"; + props.setProperty("destination.address3", addrStr); + props.setProperty("topic.address4", "hello.world"); + addrStr = "ADDR:my_queue; {create:always,link: {x-subscribes:{exclusive: true, arguments: {a:b,x:y}}}}"; + props.setProperty("destination.address5", addrStr); + + Context ctx = new InitialContext(props); + + for (int i=1; i < 5; i++) + { + Topic topic = (Topic) ctx.lookup("address"+i); + createDurableSubscriber(ctx,ssn,"address"+i,topic); + } + + Topic topic = ssn.createTopic("ADDR:news.us"); + createDurableSubscriber(ctx,ssn,"my-dest",topic); + + Topic namedQueue = (Topic) ctx.lookup("address5"); + try + { + createDurableSubscriber(ctx,ssn,"my-queue",namedQueue); + fail("Exception should be thrown. Durable subscribers cannot be created for Queues"); + } + catch(JMSException e) + { + assertEquals("Durable subscribers can only be created for Topics", + e.getMessage()); + } + } + + private void createDurableSubscriber(Context ctx,Session ssn,String destName,Topic topic) throws Exception + { + MessageConsumer cons = ssn.createDurableSubscriber(topic, destName); + MessageProducer prod = ssn.createProducer(topic); + + Message m = ssn.createTextMessage(destName); + prod.send(m); + Message msg = cons.receive(1000); + assertNotNull(msg); + assertEquals(destName,((TextMessage)msg).getText()); + ssn.unsubscribe(destName); + } + + public void testDeleteOptions() throws Exception + { + Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); + MessageConsumer cons; + + // default (create never, assert never) ------------------- + // create never -------------------------------------------- + String addr1 = "ADDR:testQueue1;{create: always, delete: always}"; + AMQDestination dest = new AMQAnyDestination(addr1); + try + { + cons = jmsSession.createConsumer(dest); + cons.close(); + } + catch(JMSException e) + { + fail("Exception should not be thrown. Exception thrown is : " + e); + } + + assertFalse("Queue not deleted as expected",( + (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + + + String addr2 = "ADDR:testQueue2;{create: always, delete: receiver}"; + dest = new AMQAnyDestination(addr2); + try + { + cons = jmsSession.createConsumer(dest); + cons.close(); + } + catch(JMSException e) + { + fail("Exception should not be thrown. Exception thrown is : " + e); + } + + assertFalse("Queue not deleted as expected",( + (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + + + String addr3 = "ADDR:testQueue3;{create: always, delete: sender}"; + dest = new AMQAnyDestination(addr3); + try + { + cons = jmsSession.createConsumer(dest); + MessageProducer prod = jmsSession.createProducer(dest); + prod.close(); + } + catch(JMSException e) + { + fail("Exception should not be thrown. Exception thrown is : " + e); + } + + assertFalse("Queue not deleted as expected",( + (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true)); + + + } + + /** + * Test Goals : 1. Test if the client sets the correct accept mode for unreliable + * and at-least-once. + * 2. Test default reliability modes for Queues and Topics. + * 3. Test if an exception is thrown if exactly-once is used. + * 4. Test if an exception is thrown if at-least-once is used with topics. + * + * Test Strategy: For goal #1 & #2 + * For unreliable and at-least-once the test tries to receives messages + * in client_ack mode but does not ack the messages. + * It will then close the session, recreate a new session + * and will then try to verify the queue depth. + * For unreliable the messages should have been taken off the queue. + * For at-least-once the messages should be put back onto the queue. + * + */ + + public void testReliabilityOptions() throws Exception + { + String addr1 = "ADDR:testQueue1;{create: always, delete : receiver, link : {reliability : unreliable}}"; + acceptModeTest(addr1,0); + + String addr2 = "ADDR:testQueue2;{create: always, delete : receiver, link : {reliability : at-least-once}}"; + acceptModeTest(addr2,2); + + // Default accept-mode for topics + acceptModeTest("ADDR:amq.topic/test",0); + + // Default accept-mode for queues + acceptModeTest("ADDR:testQueue1;{create: always}",2); + + String addr3 = "ADDR:testQueue2;{create: always, delete : receiver, link : {reliability : exactly-once}}"; + try + { + AMQAnyDestination dest = new AMQAnyDestination(addr3); + fail("An exception should be thrown indicating it's an unsupported type"); + } + catch(Exception e) + { + assertTrue(e.getCause().getMessage().contains("The reliability mode 'exactly-once' is not yet supported")); + } + + String addr4 = "ADDR:amq.topic/test;{link : {reliability : at-least-once}}"; + try + { + AMQAnyDestination dest = new AMQAnyDestination(addr4); + Session ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE); + MessageConsumer cons = ssn.createConsumer(dest); + fail("An exception should be thrown indicating it's an unsupported combination"); + } + catch(Exception e) + { + assertTrue(e.getCause().getMessage().contains("AT-LEAST-ONCE is not yet supported for Topics")); + } + } + + private void acceptModeTest(String address, int expectedQueueDepth) throws Exception + { + Session ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE); + MessageConsumer cons; + MessageProducer prod; + + AMQDestination dest = new AMQAnyDestination(address); + cons = ssn.createConsumer(dest); + prod = ssn.createProducer(dest); + + for (int i=0; i < expectedQueueDepth; i++) + { + prod.send(ssn.createTextMessage("Msg" + i)); + } + + for (int i=0; i < expectedQueueDepth; i++) + { + Message msg = cons.receive(1000); + assertNotNull(msg); + assertEquals("Msg" + i,((TextMessage)msg).getText()); + } + + ssn.close(); + ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE); + long queueDepth = ((AMQSession) ssn).getQueueDepth(dest); + assertEquals(expectedQueueDepth,queueDepth); + cons.close(); + prod.close(); + } + + public void testDestinationOnSend() throws Exception + { + Session ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE); + MessageConsumer cons = ssn.createConsumer(ssn.createTopic("ADDR:amq.topic/test")); + MessageProducer prod = ssn.createProducer(null); + + Queue queue = ssn.createQueue("ADDR:amq.topic/test"); + prod.send(queue,ssn.createTextMessage("A")); + + Message msg = cons.receive(1000); + assertNotNull(msg); + assertEquals("A",((TextMessage)msg).getText()); + prod.close(); + cons.close(); + } + + public void testReplyToWithNamelessExchange() throws Exception + { + System.setProperty("qpid.declare_exchanges","false"); + replyToTest("ADDR:my-queue;{create: always}"); + System.setProperty("qpid.declare_exchanges","true"); + } + + public void testReplyToWithCustomExchange() throws Exception + { + replyToTest("ADDR:hello;{create:always,node:{type:topic}}"); + } + + private void replyToTest(String replyTo) throws Exception + { + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination replyToDest = AMQDestination.createDestination(replyTo); + MessageConsumer replyToCons = session.createConsumer(replyToDest); + + Destination dest = session.createQueue("ADDR:amq.direct/test"); + + MessageConsumer cons = session.createConsumer(dest); + MessageProducer prod = session.createProducer(dest); + Message m = session.createTextMessage("test"); + m.setJMSReplyTo(replyToDest); + prod.send(m); + + Message msg = cons.receive(); + MessageProducer prodR = session.createProducer(msg.getJMSReplyTo()); + prodR.send(session.createTextMessage("x")); + + Message m1 = replyToCons.receive(); + assertNotNull("The reply to consumer should have received the messsage",m1); + } + + public void testAltExchangeInAddressString() throws Exception + { + String addr1 = "ADDR:my-exchange/test; {create: always, node:{type: topic,x-declare:{alternate-exchange:'amq.fanout'}}}"; + Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + String altQueueAddr = "ADDR:my-alt-queue;{create: always, delete: receiver,node:{x-bindings:[{exchange:'amq.fanout'}] }}"; + MessageConsumer cons = session.createConsumer(session.createQueue(altQueueAddr)); + + MessageProducer prod = session.createProducer(session.createTopic(addr1)); + prod.send(session.createMessage()); + prod.close(); + assertNotNull("The consumer on the queue bound to the alt-exchange should receive the message",cons.receive(1000)); + + String addr2 = "ADDR:test-queue;{create:sender, delete: sender,node:{type:queue,x-declare:{alternate-exchange:'amq.fanout'}}}"; + prod = session.createProducer(session.createTopic(addr2)); + prod.send(session.createMessage()); + prod.close(); + assertNotNull("The consumer on the queue bound to the alt-exchange should receive the message",cons.receive(1000)); + cons.close(); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java index fcbab273e5..3068deecf8 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java @@ -299,7 +299,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener details.setProperty(BrokerDetails.OPTIONS_RETRY, String.valueOf(RETRIES)); details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, String.valueOf(DELAY)); - connection = new AMQConnection(connectionURL, null); + connection = new AMQConnection(connectionURL); ((AMQConnection) connection).setConnectionListener(this); diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java index 49a608190d..b1c8b5682f 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java @@ -23,6 +23,7 @@ package org.apache.qpid.test.client.message; import java.util.concurrent.CountDownLatch; import javax.jms.DeliveryMode; +import javax.jms.Destination; import javax.jms.InvalidSelectorException; import javax.jms.JMSException; import javax.jms.Message; @@ -30,6 +31,7 @@ import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Session; +import javax.jms.TextMessage; import junit.framework.Assert; @@ -50,7 +52,6 @@ public class SelectorTest extends QpidBrokerTestCase implements MessageListener private AMQConnection _connection; private AMQDestination _destination; private int count; - public String _connectionString = "vm://:1"; private static final String INVALID_SELECTOR = "Cost LIKE 5"; CountDownLatch _responseLatch = new CountDownLatch(1); @@ -280,31 +281,36 @@ public class SelectorTest extends QpidBrokerTestCase implements MessageListener Assert.assertNotNull("Msg5 should not be null", msg5); } - public static void main(String[] argv) throws Exception + public void testSelectorWithJMSDeliveryMode() throws Exception { - SelectorTest test = new SelectorTest(); - test._connectionString = (argv.length == 0) ? "localhost:3000" : argv[0]; + Session session = _connection.createSession(false, Session.SESSION_TRANSACTED); - try - { - while (true) - { - if (test._connectionString.contains("vm://:1")) - { - test.setUp(); - } - test.testUsingOnMessage(); - - if (test._connectionString.contains("vm://:1")) - { - test.tearDown(); - } - } - } - catch (Exception e) - { - System.err.println(e.getMessage()); - e.printStackTrace(); - } + Destination dest1 = session.createTopic("test1"); + Destination dest2 = session.createTopic("test2"); + + MessageProducer prod1 = session.createProducer(dest1); + MessageProducer prod2 = session.createProducer(dest2); + MessageConsumer consumer1 = session.createConsumer(dest1,"JMSDeliveryMode = 'PERSISTENT'"); + MessageConsumer consumer2 = session.createConsumer(dest2,"JMSDeliveryMode = 'NON_PERSISTENT'"); + + Message msg1 = session.createTextMessage("Persistent"); + prod1.send(msg1); + prod2.send(msg1); + + prod1.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + prod2.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + + Message msg2 = session.createTextMessage("Non_Persistent"); + prod1.send(msg2); + prod2.send(msg2); + + TextMessage m1 = (TextMessage)consumer1.receive(1000); + assertEquals("Consumer1 should receive the persistent message","Persistent",m1.getText()); + assertNull("Consumer1 should not receiver another message",consumer1.receive(1000)); + + TextMessage m2 = (TextMessage)consumer2.receive(1000); + assertEquals("Consumer2 should receive the non persistent message","Non_Persistent",m2.getText()); + assertNull("Consumer2 should not receiver another message",consumer2.receive(1000)); } + } diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java index 1a23eee8ab..6189c37306 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java @@ -63,7 +63,7 @@ public class SyncWaitTimeoutDelayTest extends SyncWaitDelayTest catch (JMSException e) { assertTrue("Wrong exception type received.", e.getLinkedException() instanceof AMQTimeoutException); - assertTrue("Wrong message received on exception.", e.getMessage().startsWith("Failed to commit")); + assertTrue("Wrong message received on exception.", e.getMessage().startsWith("Exception during commit")); // As we are using Nano time ensure to multiply up the millis. assertTrue("Timeout was more than 30s default", (System.nanoTime() - start) < (1000000L * 1000 * 30)); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java deleted file mode 100644 index c11f75e742..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * 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.test.framework.qpid; - -import junit.framework.Test; -import junit.framework.TestResult; - -import org.apache.qpid.test.framework.FrameworkBaseCase; -import org.apache.qpid.test.framework.LocalAMQPCircuitFactory; - -import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator; - -/** - * AMQPFeatureDecorator applies decorations to {@link FrameworkBaseCase} tests, so that they may use Qpid/AMQP specific - * features, not available through JMS. For example, the immediate and mandatory flags. This decorator replaces the - * standard test circuit factory on the base class with one that allows these features to be used. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Substitute the circuit factory with an AMQP/Qpid specific one. - * </table> - * - * @todo This wrapper substitutes in a LocalAMQPCircuitFactory, which is fine for local tests. For distributed tests - * the Fanout or Interop factories are substituted in by their decorators instead. These actually use - * distributed circuit static create methods to build the circuits, which should actually be changed to a factory, - * so that static methods do not need to be used. The distributed circuit creater delegates the circuit - * construction to remote test nodes. This decorator should not be used with distributed tests, or should be made - * aware of them, in which case it might ensure that an AMQP feature (implied already by other properties) flag - * is passed out to the remote test nodes, and provide a mechansim for them to decorate their circuit creation - * with AMQP features too. Add factory substituion/decoration mechansim for test clients, here or in a seperate - * class. - */ -public class AMQPFeatureDecorator extends WrappedSuiteTestDecorator -{ - /** The test suite to run. */ - private Test test; - - /** - * Creates a wrapped test test decorator from another one. - * - * @param test The test test. - */ - public AMQPFeatureDecorator(WrappedSuiteTestDecorator test) - { - super(test); - this.test = test; - } - - /** - * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated. - * - * @param testResult The the results object to monitor the test results with. - */ - public void run(TestResult testResult) - { - for (Test test : getAllUnderlyingTests()) - { - if (test instanceof FrameworkBaseCase) - { - FrameworkBaseCase frameworkTest = (FrameworkBaseCase) test; - frameworkTest.setCircuitFactory(new LocalAMQPCircuitFactory()); - } - } - - // Run the test. - test.run(testResult); - } - - /** - * Prints the name of the test for debugging purposes. - * - * @return The name of the test. - */ - public String toString() - { - return "AMQPFeatureDecorator: [test = \"" + test + "\"]"; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java deleted file mode 100644 index 2708253d86..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * 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.test.framework.qpid; - -import junit.framework.Test; -import junit.framework.TestResult; - -import org.apache.qpid.test.framework.BrokerLifecycleAware; -import org.apache.qpid.test.framework.CauseFailureUserPrompt; - -import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator; - -/** - * CauseFailureDecorator applies decorations to {@link BrokerLifecycleAware} tests, so that they may use different failure - * mechanisms. It is capable of detecting when a test case uses in-vm brokers, and setting up an automatic failure - * for those tests, so that the current live broker can be shut-down by test cases. For external brokers, automatic - * failure could be implemented, for example by having a kill script. At the moment this sets up the failure to prompt - * a user interactively to cause a failure, using {@link CauseFailureUserPrompt}. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Setup automatic failures for in-vm brokers. <td> {@link CauseFailureInVM} - * <tr><td> Setup user generated failures for external brokers. <td> {@link CauseFailureUserPrompt}. - * <tr><td> - * </table> - * - * @todo Slight problem in that CauseFailureInVM is Qpid specific, whereas CauseFailureUserPrompt is not. Would like the - * failure decorator to be non-qpid specific so that it can test failure of any JMS implementation too. Either pass - * in class name of failure mechanism, set it up in the in-vm decorator instead of here but with prompt user as the - * default for when the in-vm decorator is not used? - */ -public class CauseFailureDecorator extends WrappedSuiteTestDecorator -{ - /** The test suite to run. */ - private Test test; - - /** - * Creates a wrapped test test decorator from another one. - * - * @param test The test test. - */ - public CauseFailureDecorator(WrappedSuiteTestDecorator test) - { - super(test); - this.test = test; - } - - /** - * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated. - * - * @param testResult The the results object to monitor the test results with. - */ - public void run(TestResult testResult) - { - for (Test test : getAllUnderlyingTests()) - { - if (test instanceof BrokerLifecycleAware) - { - BrokerLifecycleAware failureTest = (BrokerLifecycleAware) test; - failureTest.setFailureMechanism(new CauseFailureUserPrompt()); - } - } - - // Run the test. - test.run(testResult); - } - - /** - * Prints the name of the test for debugging purposes. - * - * @return The name of the test. - */ - public String toString() - { - return "CauseFailureDecorator: [test = \"" + test + "\"]"; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java deleted file mode 100644 index 3e03ad0872..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * 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.test.framework.qpid; - -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.test.framework.CauseFailure; -import org.apache.qpid.test.framework.BrokerLifecycleAware; - -/** - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Cause messaging broker failure on the active in-vm broker. - * <td> {@link TransportConnection}, {@link ApplicationRegistry} - * </table> - */ -public class CauseFailureInVM implements CauseFailure -{ - /** Holds the in-vm broker instrumented test case to create failures for. */ - private BrokerLifecycleAware inVMTest; - - /** - * Creates an automated failure mechanism for testing against in-vm brokers. The test to create the mechanism - * for is specified, and as this failure is for in-vm brokers, the test must be {@link org.apache.qpid.test.framework.BrokerLifecycleAware}. The test - * must also report that it is currently being run against an in-vm broker, and it is a runtime error if it is not, - * as the creator of this failure mechanism should already have checked that it is. - * - * @param inVMTest The test case to create an automated failure mechanism for. - */ - public CauseFailureInVM(BrokerLifecycleAware inVMTest) - { - // Check that the test is really using in-vm brokers. - if (!inVMTest.usingInVmBroker()) - { - throw new RuntimeException( - "Cannot create in-vm broker failure mechanism for a test that is not using in-vm brokers."); - } - - this.inVMTest = inVMTest; - } - - /** - * Causes the active message broker to fail. - */ - public void causeFailure() - { - int liveBroker = inVMTest.getLiveBroker(); - - TransportConnection.killVMBroker(liveBroker); - ApplicationRegistry.remove(liveBroker); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java deleted file mode 100644 index b92a72a654..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * 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.test.framework.qpid; - -import junit.framework.Test; -import junit.framework.TestResult; - -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.test.framework.BrokerLifecycleAware; -import org.apache.qpid.test.framework.FrameworkBaseCase; - -import org.apache.qpid.junit.extensions.SetupTaskAware; -import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator; - -/** - * InVMBrokerDecorator is a test decorator, that is activated when running tests against an in-vm broker only. Its - * purpose is to automatically create, and close and delete an in-vm broker, during the set-up and tear-down of - * each test case. This decorator may only be used in conjunction with tests that extend {@link FrameworkBaseCase}. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Create/Destroy an in-vm broker on every test run. - * </table> - * - * @todo May need to add a more fine grained injection point for the in-vm broker management, as this acts at the - * suite level, rather than the individual test level. - * - * @todo Management of in-vm brokers for failure testing. Failure test setups may need to set their connection url to - * use multiple broker (vm://:1;vm://:2), with fail-over between them. There is round-robin fail-over, but also - * retry? A test case using an in-vm broker needs to record which one it is using, so that it can be - * killed/restarted. - */ -public class InVMBrokerDecorator extends WrappedSuiteTestDecorator -{ - /** The test suite to run. */ - private Test test; - - /** - * Creates a wrapped test suite decorator from another one. - * - * @param test The test suite. - */ - public InVMBrokerDecorator(WrappedSuiteTestDecorator test) - { - super(test); - this.test = test; - } - - /** - * Runs the tests with in-vm broker creation and clean-up added to the tests task stack. - * - * @param testResult The the results object to monitor the test results with. - */ - public void run(TestResult testResult) - { - for (Test test : getAllUnderlyingTests()) - { - // Check that the test to have an in-vm broker setup/teardown task added to it, is actually a framework - // test that can handle setup tasks. - if ((test instanceof SetupTaskAware)) - { - SetupTaskAware frameworkTest = (SetupTaskAware) test; - - frameworkTest.chainSetupTask(new Runnable() - { - public void run() - { - // Ensure that the in-vm broker is created. - try - { - ApplicationRegistry.getInstance(1); - TransportConnection.createVMBroker(1); - } - catch (AMQVMBrokerCreationException e) - { - throw new RuntimeException("In-VM broker creation failed: " + e.getMessage(), e); - } - } - }); - - frameworkTest.chainTearDownTask(new Runnable() - { - public void run() - { - // Ensure that the in-vm broker is cleaned up so that the next test starts afresh. - TransportConnection.killVMBroker(1); - ApplicationRegistry.remove(1); - } - }); - - // Check if the test is aware whether or not it can control the broker life cycle, and if so provide - // additional instrumentation for it to control the in-vm broker through. - if (test instanceof BrokerLifecycleAware) - { - BrokerLifecycleAware inVMTest = (BrokerLifecycleAware) test; - inVMTest.setInVmBrokers(); - inVMTest.setLiveBroker(1); - inVMTest.setFailureMechanism(new CauseFailureInVM(inVMTest)); - } - } - } - - // Run the test. - test.run(testResult); - } - - /** - * Prints the name of the test for debugging purposes. - * - * @return The name of the test. - */ - public String toString() - { - return "InVMBrokerDecorator: [test = " + test + "]"; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java b/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java deleted file mode 100644 index d4bab657d7..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * 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.test.testcases; - -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.FrameworkBaseCase; -import static org.apache.qpid.test.framework.MessagingTestConfigProperties.ACK_MODE_PROPNAME; -import static org.apache.qpid.test.framework.MessagingTestConfigProperties.PUBSUB_PROPNAME; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl; -import org.apache.qpid.test.framework.sequencers.CircuitFactory; - -import javax.jms.*; - -import java.util.LinkedList; -import java.util.List; -import java.util.Random; - -/** - * TTLTest checks that time-to-live is applied to messages. The test sends messages with a variety of TTL stamps on them - * then after a pause attempts to receive those messages. Only messages with a large enough TTL to have survived the pause - * should be receiveable. This test case also applies an additional assertion against the broker, that the message store - * is empty at the end of the test. - * - * <p/>This test is designed to run over local circuits only, as it must control a timed pause between sending and receiving - * messages to that TTL can be applied to purge some of the messages. - * - * <p/><table id="crc"><caption>CRC Card</caption> - * <tr><th> Responsibilities <th> Collaborations - * <tr><td> - * </table> - * - * @todo Use an interface or other method to mark this test as local only. - * - * @todo Implement the message store assertion for in-vm broker. Could also be done for external broker, for example - * by using diagnostic exchange. - * - * @todo Implement and add a queue depth assertion too. This might already be in another test to copy from. - * - * @todo Create variations on test theme, for different ack mode and tx and message sizes etc. - * - * @todo Add an allowable margin of error to the test, as ttl may not be precise. - */ -public class TTLTest extends FrameworkBaseCase -{ - /** - * Creates a new test case with the specified name. - * - * @param name The test case name. - */ - public TTLTest(String name) - { - super(name); - } - - /** - * Checks that all messages sent with a TTL shorter than a pause between sending them and attempting to receive them - * will fail to arrive. Once all messages have been purged by TTL or received, check that they no longer exist on - * the broker. - * - * @throws javax.jms.JMSException Allowed to fall through and fail test. - */ - public void testTTLP2P() throws Exception - { - String errorMessages = ""; - Random r = new Random(); - - // Used to accumulate correctly received messages in. - List<Message> receivedMessages = new LinkedList<Message>(); - - // Set up the test properties to match the test case requirements. - getTestProps().setProperty(ACK_MODE_PROPNAME, Session.AUTO_ACKNOWLEDGE); - getTestProps().setProperty(PUBSUB_PROPNAME, false); - - // Create the test circuit from the test configuration parameters. - CircuitFactory circuitFactory = getCircuitFactory(); - Circuit testCircuit = circuitFactory.createCircuit(getConnection(), getTestProps()); - - // This test case assumes it is using a local circuit. - LocalCircuitImpl localCircuit = (LocalCircuitImpl) testCircuit; - - Session producerSession = localCircuit.getLocalPublisherCircuitEnd().getSession(); - MessageProducer producer = localCircuit.getLocalPublisherCircuitEnd().getProducer(); - MessageConsumer consumer = localCircuit.getLocalReceiverCircuitEnd().getConsumer(); - - // Send some tests messages, with random TTLs, some shorter and some longer than the pause time. - for (int i = 0; i < 100; i++) - { - Message testMessage = TestUtils.createTestMessageOfSize(producerSession, 10); - - // Set the TTL on the message and record its value in the message headers. - long ttl = 500 + r.nextInt(1500); - producer.setTimeToLive(ttl); - testMessage.setLongProperty("testTTL", ttl); - - producer.send(testMessage); - // producerSession.commit(); - } - - // Inject a pause to allow some messages to be purged by TTL. - TestUtils.pause(1000); - - // Attempt to receive back all of the messages, confirming by the message time stamps and TTLs that only - // those received should have avoided being purged by the TTL. - boolean timedOut = false; - - - Message testMessage = null; - - do - { - testMessage = consumer.receive(1000); - - long ttl = testMessage.getLongProperty("testTTL"); - long timeStamp = testMessage.getJMSTimestamp(); - long now = System.currentTimeMillis(); - - if ((timeStamp + ttl) < now) - { - errorMessages += - "Received message [sent: " + timeStamp + ", ttl: " + ttl + ", received: " + now - + "] which should have been purged by its TTL.\n"; - } - /*else - { - receivedMessages.add(testMessage); - }*/ - } while (!timedOut && testMessage != null); - - // Check that the queue and message store on the broker are empty. - // assertTrue("Message store is not empty.", messageStoreEmpty.apply()); - // assertTrue("Queue is not empty.", queueEmpty.apply()); - - assertTrue(errorMessages, "".equals(errorMessages)); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java index 4b45a96c20..23efb656d2 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java @@ -23,7 +23,7 @@ package org.apache.qpid.test.unit.ack; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.test.utils.FailoverBaseCase; +import org.apache.qpid.test.utils.QpidBrokerTestCase; import javax.jms.Connection; import javax.jms.JMSException; @@ -32,7 +32,7 @@ import javax.jms.MessageConsumer; import javax.jms.Queue; import javax.jms.Session; -public class Acknowledge2ConsumersTest extends FailoverBaseCase +public class Acknowledge2ConsumersTest extends QpidBrokerTestCase { protected static int NUM_MESSAGES = 100; protected Connection _con; diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/ClientAcknowledgeTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/ClientAcknowledgeTest.java new file mode 100644 index 0000000000..06be5cf456 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/ClientAcknowledgeTest.java @@ -0,0 +1,82 @@ +/* + * 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.test.unit.ack; + +import javax.jms.Connection; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class ClientAcknowledgeTest extends QpidBrokerTestCase +{ + private static final long ONE_DAY_MS = 1000l * 60 * 60 * 24; + private Connection _connection; + private Queue _queue; + private Session _consumerSession; + private MessageConsumer _consumer; + private MessageProducer _producer; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _queue = getTestQueue(); + _connection = getConnection(); + } + + /** + * Test that message.acknowledge actually acknowledges, regardless of + * the flusher thread period, by restarting the broker after calling + * acknowledge, and then verifying after restart that the message acked + * is no longer present. This test requires a persistent store. + */ + public void testClientAckWithLargeFlusherPeriod() throws Exception + { + setTestClientSystemProperty("qpid.session.max_ack_delay", Long.toString(ONE_DAY_MS)); + _consumerSession = _connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + _consumer = _consumerSession.createConsumer(_queue); + _connection.start(); + + _producer = _consumerSession.createProducer(_queue); + _producer.send(createNextMessage(_consumerSession, 1)); + _producer.send(createNextMessage(_consumerSession, 2)); + + Message message = _consumer.receive(1000l); + assertNotNull("Message has not been received", message); + assertEquals("Unexpected message is received", 1, message.getIntProperty(INDEX)); + message.acknowledge(); + + //restart broker to allow verification of the acks + //without explicitly closing connection (which acks) + restartBroker(); + + // try to receive the message again, which should fail (as it was ackd) + _connection = getConnection(); + _connection.start(); + _consumerSession = _connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + _consumer = _consumerSession.createConsumer(_queue); + message = _consumer.receive(1000l); + assertNotNull("Message has not been received", message); + assertEquals("Unexpected message is received", 2, message.getIntProperty(INDEX)); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java index 6c83136511..13c78c1e14 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.test.unit.ack; -import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch; +import java.util.concurrent.CountDownLatch; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.jms.ConnectionListener; import org.apache.qpid.test.utils.QpidBrokerTestCase; diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java index 5e7ba5482d..66ca1d8345 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java @@ -46,7 +46,7 @@ public class RecoverTest extends FailoverBaseCase { static final Logger _logger = LoggerFactory.getLogger(RecoverTest.class); - private Exception _error; + private volatile Exception _error; private AtomicInteger count; protected AMQConnection _connection; @@ -249,14 +249,13 @@ public class RecoverTest extends FailoverBaseCase { if (!message.getJMSRedelivered()) { - setError( - new Exception("Message not marked as redelivered on what should be second delivery attempt")); + setError(new Exception("Message not marked as redelivered on what should be second delivery attempt")); } } else { - System.err.println(message); - fail("Message delivered too many times!: " + count); + _logger.error(message.toString()); + setError(new Exception("Message delivered too many times!: " + count)); } } catch (JMSException e) diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java index 59ce64eb4f..0731d56204 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java @@ -21,7 +21,6 @@ package org.apache.qpid.test.unit.basic; import junit.framework.Assert; -import org.apache.mina.common.ByteBuffer; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; @@ -45,6 +44,7 @@ import javax.jms.MessageNotWriteableException; import javax.jms.MessageProducer; import javax.jms.Session; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java index abf8da799c..3af215d1d5 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.test.unit.basic; -import org.apache.mina.common.ByteBuffer; - import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; @@ -41,6 +39,8 @@ import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.MessageProducer; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.CountDownLatch; @@ -105,7 +105,7 @@ public class FieldTableMessageTest extends QpidBrokerTestCase implements Message { int count = _count; _waitForCompletion = new CountDownLatch(_count); - send(count); + send(count); _waitForCompletion.await(20, TimeUnit.SECONDS); check(); _logger.info("Completed without failure"); @@ -125,12 +125,15 @@ public class FieldTableMessageTest extends QpidBrokerTestCase implements Message } - void check() throws JMSException, AMQFrameDecodingException + void check() throws JMSException, AMQFrameDecodingException, IOException { for (Object m : received) { - ByteBuffer buffer = ((JMSBytesMessage) m).getData(); - FieldTable actual = FieldTableFactory.newFieldTable(buffer, buffer.remaining()); + final BytesMessage bytesMessage = (BytesMessage) m; + final long bodyLength = bytesMessage.getBodyLength(); + byte[] data = new byte[(int) bodyLength]; + bytesMessage.readBytes(data); + FieldTable actual = FieldTableFactory.newFieldTable(new DataInputStream(new ByteArrayInputStream(data)), bodyLength); for (String key : _expected.keys()) { assertEquals("Values for " + key + " did not match", _expected.getObject(key), actual.getObject(key)); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java index 3a5f676ca6..87eae32cf8 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java @@ -23,7 +23,6 @@ import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.test.utils.QpidBrokerTestCase; diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java index c6b8069300..3c7962d873 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java @@ -21,14 +21,13 @@ package org.apache.qpid.test.unit.basic.close; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.url.AMQBindingURL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; +import javax.jms.Queue; import javax.jms.Session; public class CloseTest extends QpidBrokerTestCase @@ -41,7 +40,7 @@ public class CloseTest extends QpidBrokerTestCase Session session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); - AMQQueue queue = new AMQQueue(new AMQBindingURL("test-queue")); + Queue queue = session.createQueue("test-queue"); MessageConsumer consumer = session.createConsumer(queue); MessageProducer producer_not_used_but_created_for_testing = session.createProducer(queue); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java index 292bcd6039..53a7533869 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java @@ -20,28 +20,15 @@ */ package org.apache.qpid.test.unit.client; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.QueueSession; import javax.jms.Session; -import javax.jms.TextMessage; import javax.jms.TopicSession; import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQConnectionDelegate_0_10; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQTopic; @@ -53,9 +40,9 @@ import org.slf4j.LoggerFactory; public class AMQConnectionTest extends QpidBrokerTestCase { - private static AMQConnection _connection; - private static AMQTopic _topic; - private static AMQQueue _queue; + protected static AMQConnection _connection; + protected static AMQTopic _topic; + protected static AMQQueue _queue; private static QueueSession _queueSession; private static TopicSession _topicSession; protected static final Logger _logger = LoggerFactory.getLogger(AMQConnectionTest.class); @@ -63,15 +50,14 @@ public class AMQConnectionTest extends QpidBrokerTestCase protected void setUp() throws Exception { super.setUp(); - _connection = (AMQConnection) getConnection("guest", "guest"); + createConnection(); _topic = new AMQTopic(_connection.getDefaultTopicExchangeName(), new AMQShortString("mytopic")); _queue = new AMQQueue(_connection.getDefaultQueueExchangeName(), new AMQShortString("myqueue")); } - - protected void tearDown() throws Exception + + protected void createConnection() throws Exception { - _connection.close(); - super.tearDown(); + _connection = (AMQConnection) getConnection("guest", "guest"); } /** @@ -210,60 +196,50 @@ public class AMQConnectionTest extends QpidBrokerTestCase public void testPrefetchSystemProperty() throws Exception { - String oldPrefetch = System.getProperty(ClientProperties.MAX_PREFETCH_PROP_NAME); - try - { - _connection.close(); - System.setProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(2).toString()); - _connection = (AMQConnection) getConnection(); - _connection.start(); - // Create two consumers on different sessions - Session consSessA = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE); - MessageConsumer consumerA = consSessA.createConsumer(_queue); + _connection.close(); + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(2).toString()); + + createConnection(); + _connection.start(); + // Create two consumers on different sessions + Session consSessA = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE); + MessageConsumer consumerA = consSessA.createConsumer(_queue); - Session producerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - MessageProducer producer = producerSession.createProducer(_queue); + Session producerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageProducer producer = producerSession.createProducer(_queue); - // Send 3 messages - for (int i = 0; i < 3; i++) - { - producer.send(producerSession.createTextMessage("test")); - } - - MessageConsumer consumerB = null; - if (isBroker08()) - { - Session consSessB = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE); - consumerB = consSessB.createConsumer(_queue); - } - else - { - consumerB = consSessA.createConsumer(_queue); - } - - Message msg; - // Check that consumer A has 2 messages - for (int i = 0; i < 2; i++) - { - msg = consumerA.receive(1500); - assertNotNull("Consumer A should receive 2 messages",msg); - } - - msg = consumerA.receive(1500); - assertNull("Consumer A should not have received a 3rd message",msg); - - // Check that consumer B has the last message - msg = consumerB.receive(1500); - assertNotNull("Consumer B should have received the message",msg); + // Send 3 messages + for (int i = 0; i < 3; i++) + { + producer.send(producerSession.createTextMessage("test")); } - finally + + MessageConsumer consumerB = null; + // 0-8, 0-9, 0-9-1 prefetch is per session, not consumer. + if (!isBroker010()) { - if (oldPrefetch == null) - { - oldPrefetch = ClientProperties.MAX_PREFETCH_DEFAULT; - } - System.setProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, oldPrefetch); + Session consSessB = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE); + consumerB = consSessB.createConsumer(_queue); + } + else + { + consumerB = consSessA.createConsumer(_queue); + } + + Message msg; + // Check that consumer A has 2 messages + for (int i = 0; i < 2; i++) + { + msg = consumerA.receive(1500); + assertNotNull("Consumer A should receive 2 messages",msg); } + + msg = consumerA.receive(1500); + assertNull("Consumer A should not have received a 3rd message",msg); + + // Check that consumer B has the last message + msg = consumerB.receive(1500); + assertNotNull("Consumer B should have received the message",msg); } public void testGetChannelID() throws Exception @@ -286,120 +262,5 @@ public class AMQConnectionTest extends QpidBrokerTestCase } } } - - /** - * Test Strategy : Kill -STOP the broker and see - * if the client terminates the connection with a - * read timeout. - * The broker process is cleaned up in the test itself - * and avoids using process.waitFor() as it hangs. - */ - public void testHeartBeat() throws Exception - { - boolean windows = - ((String) System.getProperties().get("os.name")).matches("(?i).*windows.*"); - - if (!isCppBroker() || windows) - { - return; - } - - Process process = null; - int port = getPort(0); - String pid = null; - try - { - // close the connection and shutdown the broker started by QpidTest - _connection.close(); - stopBroker(port); - - System.setProperty("qpid.heartbeat", "1"); - - // in case this broker gets stuck, atleast the rest of the tests will not fail. - port = port + 200; - String startCmd = getBrokerCommand(port); - - // start a broker using a script - ProcessBuilder pb = new ProcessBuilder(System.getProperty("broker.start")); - pb.redirectErrorStream(true); - - Map<String, String> env = pb.environment(); - env.put("BROKER_CMD",startCmd); - env.put("BROKER_READY",System.getProperty(BROKER_READY)); - - Process startScript = pb.start(); - startScript.waitFor(); - startScript.destroy(); - - Connection con = - new AMQConnection("amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:" + port + "'"); - final AtomicBoolean lock = new AtomicBoolean(false); - - String cmd = "/usr/bin/pgrep -f " + port; - process = Runtime.getRuntime().exec("/bin/bash"); - LineNumberReader reader = new LineNumberReader(new InputStreamReader(process.getInputStream())); - PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(process.getOutputStream())), true); - out.println(cmd); - pid = reader.readLine(); - try - { - Integer.parseInt(pid); - } - catch (NumberFormatException e) - { - // Error! try to read further to gather the error msg. - String line; - _logger.debug(pid); - while ((line = reader.readLine()) != null ) - { - _logger.debug(line); - } - throw new Exception( "Unable to get the brokers pid " + pid); - } - _logger.debug("pid : " + pid); - - con.setExceptionListener(new ExceptionListener(){ - - public void onException(JMSException e) - { - synchronized(lock) { - lock.set(true); - lock.notifyAll(); - } - } - }); - out.println("kill -STOP " + pid); - - synchronized(lock){ - lock.wait(2500); - } - out.close(); - reader.close(); - assertTrue("Client did not terminate the connection, check log for details",lock.get()); - } - catch(Exception e) - { - throw e; - } - finally - { - System.setProperty("qpid.heartbeat", ""); - - if (process != null) - { - process.destroy(); - } - - Process killScript = Runtime.getRuntime().exec(System.getProperty("broker.kill") + " " + pid); - killScript.waitFor(); - killScript.destroy(); - cleanBroker(); - } - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(AMQConnectionTest.class); - } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSSLConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSSLConnectionTest.java new file mode 100644 index 0000000000..5f3daa407a --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSSLConnectionTest.java @@ -0,0 +1,57 @@ +/* + * + * 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.test.unit.client; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQConnectionURL; + +public class AMQSSLConnectionTest extends AMQConnectionTest +{ + private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks"; + private static final String KEYSTORE_PASSWORD = "password"; + private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; + private static final String TRUSTSTORE_PASSWORD = "password"; + + @Override + protected void setUp() throws Exception + { + setTestClientSystemProperty("profile.use_ssl", "true"); + setConfigurationProperty("connector.ssl.enabled", "true"); + setConfigurationProperty("connector.ssl.sslOnly", "true"); + super.setUp(); + } + + protected void createConnection() throws Exception + { + + final String sslPrototypeUrl = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + + "?ssl='true'&ssl_verify_hostname='false'" + + "&key_store='%s'&key_store_password='%s'" + + "&trust_store='%s'&trust_store_password='%s'" + + "'"; + + final String url = String.format(sslPrototypeUrl,System.getProperty("test.port.ssl"), + KEYSTORE,KEYSTORE_PASSWORD,TRUSTSTORE,TRUSTSTORE_PASSWORD); + + _connection = (AMQConnection) getConnection(new AMQConnectionURL(url)); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java index 33575b58aa..8577fb5b6a 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.test.unit.client; +import org.apache.qpid.AMQException; +import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.test.utils.QpidBrokerTestCase; import javax.jms.Connection; @@ -32,11 +34,9 @@ import javax.jms.Session; * * Test to validate that setting the respective qpid.declare_queues, * qpid.declare_exchanges system properties functions as expected. - * */ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase { - public void testQueueDeclare() throws Exception { setSystemProperty("qpid.declare_queues", "false"); @@ -53,11 +53,8 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase fail("JMSException should be thrown as the queue does not exist"); } catch (JMSException e) - { - assertTrue("Exception should be that the queue does not exist :" + - e.getMessage(), - e.getMessage().contains("does not exist")); - + { + checkExceptionErrorCode(e, AMQConstant.NOT_FOUND); } } @@ -79,10 +76,15 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase } catch (JMSException e) { - assertTrue("Exception should be that the exchange does not exist :" + - e.getMessage(), - e.getMessage().contains("Exchange " + EXCHANGE_TYPE + " does not exist")); + checkExceptionErrorCode(e, AMQConstant.NOT_FOUND); } } + private void checkExceptionErrorCode(JMSException original, AMQConstant code) + { + Exception linked = original.getLinkedException(); + assertNotNull("Linked exception should have been set", linked); + assertTrue("Linked exception should be an AMQException", linked instanceof AMQException); + assertEquals("Error code should be " + code.getCode(), code, ((AMQException) linked).getErrorCode()); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java index 79e2ff8148..aae8b1feb9 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java @@ -24,7 +24,6 @@ import junit.textui.TestRunner; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.slf4j.Logger; diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java index f0794c9dab..2e8a2d049d 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java @@ -25,11 +25,9 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.failover.FailoverException; import org.apache.qpid.client.protocol.AMQProtocolHandler; -import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.framing.*; import org.apache.qpid.jms.ConnectionListener; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.url.URLSyntaxException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,70 +47,67 @@ public class ChannelCloseTest extends QpidBrokerTestCase implements ExceptionLis private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseTest.class); Connection _connection; - private String _brokerlist = "vm://:1"; private Session _session; private static final long SYNC_TIMEOUT = 500; private int TEST = 0; - /* - close channel, use chanel with same id ensure error. + /** + * Close channel, use chanel with same id ensure error. + * + * This test is only valid for non 0-10 connection . */ public void testReusingChannelAfterFullClosure() throws Exception { - // this is testing an inVM Connetion conneciton - if (isJavaBroker() && !isExternalBroker()) + _connection=newConnection(); + + // Create Producer + try { - _connection=newConnection(); + _connection.start(); + + createChannelAndTest(1); - // Create Producer + // Cause it to close try { - _connection.start(); - - createChannelAndTest(1); - - // Cause it to close - try - { - _logger.info("Testing invalid exchange"); - declareExchange(1, "", "name_that_will_lookup_to_null", false); - fail("Exchange name is empty so this should fail "); - } - catch (AMQException e) - { - assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode()); - } + _logger.info("Testing invalid exchange"); + declareExchange(1, "", "name_that_will_lookup_to_null", false); + fail("Exchange name is empty so this should fail "); + } + catch (AMQException e) + { + assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode()); + } - // Check that - try + // Check that + try + { + _logger.info("Testing valid exchange should fail"); + declareExchange(1, "topic", "amq.topic", false); + fail("This should not succeed as the channel should be closed "); + } + catch (AMQException e) + { + if (_logger.isInfoEnabled()) { - _logger.info("Testing valid exchange should fail"); - declareExchange(1, "topic", "amq.topic", false); - fail("This should not succeed as the channel should be closed "); + _logger.info("Exception occured was:" + e.getErrorCode()); } - catch (AMQException e) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Exception occured was:" + e.getErrorCode()); - } - assertEquals("Connection should be closed", AMQConstant.CHANNEL_ERROR, e.getErrorCode()); + assertEquals("Connection should be closed", AMQConstant.CHANNEL_ERROR, e.getErrorCode()); - _connection=newConnection(); - } + _connection=newConnection(); + } - checkSendingMessage(); + checkSendingMessage(); - _session.close(); - _connection.close(); + _session.close(); + _connection.close(); - } - catch (JMSException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } + } + catch (JMSException e) + { + e.printStackTrace(); + fail(e.getMessage()); } } @@ -306,27 +301,19 @@ public class ChannelCloseTest extends QpidBrokerTestCase implements ExceptionLis private Connection newConnection() { - AMQConnection connection = null; + Connection connection = null; try { - connection = new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" + _brokerlist + "'"); + connection = getConnection(); - connection.setConnectionListener(this); + ((AMQConnection) connection).setConnectionListener(this); _session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); connection.start(); } - catch (JMSException e) - { - fail("Creating new connection when:" + e.getMessage()); - } - catch (AMQException e) - { - fail("Creating new connection when:" + e.getMessage()); - } - catch (URLSyntaxException e) + catch (Exception e) { fail("Creating new connection when:" + e.getMessage()); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java index dc2f59c384..91e681131f 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java @@ -55,7 +55,7 @@ public class CloseAfterConnectionFailureTest extends QpidBrokerTestCase implemen try { //Start the connection so it will use the retries - connection = new AMQConnection(url, null); + connection = new AMQConnection(url); connection.setExceptionListener(this); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java index 6d1b6de238..7f166d07fe 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.Map; import javax.jms.Connection; +import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Queue; @@ -98,6 +99,31 @@ public class ConnectionCloseTest extends QpidBrokerTestCase delta.size() < deltaThreshold); } + /** + * This test is added due to QPID-3453 to test connection closing when AMQ + * session is not closed but underlying transport session is in detached + * state and transport connection is closed + */ + public void testConnectionCloseOnOnForcibleBrokerStop() throws Exception + { + Connection connection = getConnection(); + connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + stopBroker(); + + // we need to close connection explicitly in order to verify that + // closing of connection having transport session in DETACHED state and + // transport connection in CLOSED state does not throw an exception + try + { + connection.close(); + } + catch (JMSException e) + { + // session closing should not fail + fail("Cannot close connection:" + e.getMessage()); + } + } + private void dumpStacks(Map<Thread,StackTraceElement[]> map) { for (Map.Entry<Thread,StackTraceElement[]> entry : map.entrySet()) diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java new file mode 100644 index 0000000000..545081fb43 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java @@ -0,0 +1,41 @@ +package org.apache.qpid.test.unit.client.connection; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQConnectionFactory; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class ConnectionFactoryTest extends QpidBrokerTestCase +{ + + /** + * The username & password specified should not override the default + * specified in the URL. + */ + public void testCreateConnectionWithUsernamePassword() throws Exception + { + + String brokerUrl = getBroker().toString(); + String URL = "amqp://guest:guest@clientID/test?brokerlist='" + brokerUrl + "'"; + AMQConnectionFactory factory = new AMQConnectionFactory(URL); + + AMQConnection con = (AMQConnection)factory.createConnection(); + assertEquals("Usernames used is different from the one in URL","guest",con.getConnectionURL().getUsername()); + assertEquals("Password used is different from the one in URL","guest",con.getConnectionURL().getPassword()); + + try + { + AMQConnection con2 = (AMQConnection)factory.createConnection("user","pass"); + assertEquals("Usernames used is different from the one in URL","user",con2.getConnectionURL().getUsername()); + assertEquals("Password used is different from the one in URL","pass",con2.getConnectionURL().getPassword()); + } + catch(Exception e) + { + // ignore + } + + AMQConnection con3 = (AMQConnection)factory.createConnection(); + assertEquals("Usernames used is different from the one in URL","guest",con3.getConnectionURL().getUsername()); + assertEquals("Password used is different from the one in URL","guest",con3.getConnectionURL().getPassword()); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java index 04fc611cd1..f18f365f20 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java @@ -20,32 +20,31 @@ */ package org.apache.qpid.test.unit.client.connection; +import javax.jms.Connection; +import javax.jms.QueueSession; +import javax.jms.TopicSession; + import org.apache.qpid.AMQConnectionFailureException; import org.apache.qpid.AMQException; import org.apache.qpid.AMQUnresolvedAddressException; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.client.AMQAuthenticationException; import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.jms.Session; -import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.jms.BrokerDetails; - -import javax.jms.Connection; -import javax.jms.QueueSession; -import javax.jms.TopicSession; -import javax.naming.NamingException; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.jms.Session; +import org.apache.qpid.test.utils.QpidBrokerTestCase; public class ConnectionTest extends QpidBrokerTestCase { - String _broker_NotRunning = "vm://:2"; + String _broker_NotRunning = "tcp://localhost:" + findFreePort(); + String _broker_BadDNS = "tcp://hg3sgaaw4lgihjs"; public void testSimpleConnection() throws Exception @@ -83,21 +82,21 @@ public class ConnectionTest extends QpidBrokerTestCase + "&temporaryTopicExchange='tmp.topic'"); System.err.println(url.toString()); - conn = new AMQConnection(url, null); + conn = new AMQConnection(url); AMQSession sess = (AMQSession) conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - - sess.declareExchange(new AMQShortString("test.direct"), + + sess.declareExchange(new AMQShortString("test.direct"), ExchangeDefaults.DIRECT_EXCHANGE_CLASS, false); - sess.declareExchange(new AMQShortString("tmp.direct"), + sess.declareExchange(new AMQShortString("tmp.direct"), ExchangeDefaults.DIRECT_EXCHANGE_CLASS, false); - sess.declareExchange(new AMQShortString("tmp.topic"), + sess.declareExchange(new AMQShortString("tmp.topic"), ExchangeDefaults.TOPIC_EXCHANGE_CLASS, false); - sess.declareExchange(new AMQShortString("test.topic"), + sess.declareExchange(new AMQShortString("test.topic"), ExchangeDefaults.TOPIC_EXCHANGE_CLASS, false); QueueSession queueSession = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); @@ -113,7 +112,7 @@ public class ConnectionTest extends QpidBrokerTestCase queueSession.close(); TopicSession topicSession = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); - + AMQTopic topic = (AMQTopic) topicSession.createTopic("silly.topic"); assertEquals(topic.getExchangeName().toString(), "test.topic"); @@ -271,7 +270,7 @@ public class ConnectionTest extends QpidBrokerTestCase } connection.close(); } - + public void testUnsupportedSASLMechanism() throws Exception { BrokerDetails broker = getBroker(); @@ -287,10 +286,64 @@ public class ConnectionTest extends QpidBrokerTestCase } catch (Exception e) { - assertTrue("Incorrect exception thrown", - e.getMessage().contains("The following SASL mechanisms " + - "[MY_MECH]" + - " specified by the client are not supported by the broker")); + assertTrue("Unexpected exception message : " + e.getMessage(), + e.getMessage().contains("Client and broker have no SASL mechanisms in common.")); + assertTrue("Unexpected exception message : " + e.getMessage(), + e.getMessage().contains("Client restricted itself to : MY_MECH")); + + } + } + + /** + * Tests that when the same user connects twice with same clientid, the second connection + * fails if the clientid verification feature is enabled (which uses a dummy 0-10 Session + * with the clientid as its name to detect the previous usage of the clientid by the user) + */ + public void testClientIDVerificationForSameUser() throws Exception + { + setTestSystemProperty(ClientProperties.QPID_VERIFY_CLIENT_ID, "true"); + + BrokerDetails broker = getBroker(); + try + { + Connection con = new AMQConnection(broker.toString(), "guest", "guest", + "client_id", "test"); + + Connection con2 = new AMQConnection(broker.toString(), "guest", "guest", + "client_id", "test"); + + fail("The client should throw a ConnectionException stating the" + + " client ID is not unique"); + } + catch (Exception e) + { + assertTrue("Incorrect exception thrown: " + e.getMessage(), + e.getMessage().contains("ClientID must be unique")); + } + } + + /** + * Tests that when different users connects with same clientid, the second connection + * succeeds even though the clientid verification feature is enabled (which uses a dummy + * 0-10 Session with the clientid as its name; these are only verified unique on a + * per-principal basis) + */ + public void testClientIDVerificationForDifferentUsers() throws Exception + { + setTestSystemProperty(ClientProperties.QPID_VERIFY_CLIENT_ID, "true"); + + BrokerDetails broker = getBroker(); + try + { + Connection con = new AMQConnection(broker.toString(), "guest", "guest", + "client_id", "test"); + + Connection con2 = new AMQConnection(broker.toString(), "admin", "admin", + "client_id", "test"); + } + catch (Exception e) + { + fail("Unexpected exception thrown, client id was not unique but usernames were different! " + e.getMessage()); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java index cec9d292cf..0057422c8f 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java @@ -47,13 +47,15 @@ public class ExceptionListenerTest extends QpidBrokerTestCase { public void onException(JMSException e) { + _logger.debug("&&&&&&&&&&&&&&&&&&&&&&&&&&&& Caught exception &&&&&&&&&&&&&&&&&&&&&&&&&&&& ", e); fired.countDown(); } }); - + _logger.debug("%%%%%%%%%%%%%%%% Stopping Broker %%%%%%%%%%%%%%%%%%%%%"); stopBroker(); + _logger.debug("%%%%%%%%%%%%%%%% Stopped Broker %%%%%%%%%%%%%%%%%%%%%"); - if (!fired.await(3, TimeUnit.SECONDS)) + if (!fired.await(5, TimeUnit.SECONDS)) { fail("exception listener was not fired"); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java index fd28b86762..8ad8fa77d7 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java @@ -20,14 +20,10 @@ */ package org.apache.qpid.test.unit.client.message; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import javax.jms.JMSException; import javax.jms.Message; @@ -35,10 +31,13 @@ import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.ObjectMessage; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ObjectMessageTest extends QpidBrokerTestCase implements MessageListener { @@ -67,7 +66,7 @@ public class ObjectMessageTest extends QpidBrokerTestCase implements MessageList connection.start(); // create a publisher - producer = session.createProducer(destination, false, false, true); + producer = session.createProducer(destination, false, false); A a1 = new A(1, "A"); A a2 = new A(2, "a"); B b = new B(1, "B"); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java index 278b9e9c04..836684c965 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java @@ -25,27 +25,26 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; -import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.transport.TestNetworkDriver; +import org.apache.qpid.transport.TestNetworkConnection; public class AMQProtocolSessionTest extends QpidBrokerTestCase { - private static class AMQProtSession extends AMQProtocolSession + private static class TestProtocolSession extends AMQProtocolSession { - public AMQProtSession(AMQProtocolHandler protocolHandler, AMQConnection connection) + public TestProtocolSession(AMQProtocolHandler protocolHandler, AMQConnection connection) { super(protocolHandler,connection); } - public TestNetworkDriver getNetworkDriver() + public TestNetworkConnection getNetworkConnection() { - return (TestNetworkDriver) _protocolHandler.getNetworkDriver(); + return (TestNetworkConnection) _protocolHandler.getNetworkConnection(); } public AMQShortString genQueueName() @@ -54,7 +53,7 @@ public class AMQProtocolSessionTest extends QpidBrokerTestCase } } - private AMQProtSession _testSession; + private TestProtocolSession _testSession; protected void setUp() throws Exception { @@ -62,10 +61,10 @@ public class AMQProtocolSessionTest extends QpidBrokerTestCase AMQConnection con = (AMQConnection) getConnection("guest", "guest"); AMQProtocolHandler protocolHandler = new AMQProtocolHandler(con); - protocolHandler.setNetworkDriver(new TestNetworkDriver()); - + protocolHandler.setNetworkConnection(new TestNetworkConnection()); + //don't care about the values set here apart from the dummy IoSession - _testSession = new AMQProtSession(protocolHandler , con); + _testSession = new TestProtocolSession(protocolHandler , con); } public void testTemporaryQueueWildcard() throws UnknownHostException @@ -93,14 +92,9 @@ public class AMQProtocolSessionTest extends QpidBrokerTestCase checkTempQueueName(new InetSocketAddress(InetAddress.getByName("1080:0:0:0:8:800:200C:417A"), 1234), "tmp_1080_0_0_0_8_800_200c_417a_1234_1"); } - public void testTemporaryQueuePipe() throws UnknownHostException - { - checkTempQueueName(new VmPipeAddress(1), "tmp_vm_1_1"); - } - private void checkTempQueueName(SocketAddress address, String queueName) { - _testSession.getNetworkDriver().setLocalAddress(address); + _testSession.getNetworkConnection().setLocalAddress(address); assertEquals("Wrong queue name", queueName, _testSession.genQueueName().asString()); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java index 8c806fa2da..c98e403671 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java @@ -22,237 +22,145 @@ package org.apache.qpid.test.unit.client.temporaryqueue; import javax.jms.Connection; -import javax.jms.ExceptionListener; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TemporaryQueue; import javax.jms.TextMessage; -import junit.framework.Assert; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.jms.ConnectionListener; -import java.util.ArrayList; -import java.util.List; -import java.util.LinkedList; - -public class TemporaryQueueTest extends QpidBrokerTestCase implements ExceptionListener +/** + * Tests the behaviour of {@link TemporaryQueue}. + */ +public class TemporaryQueueTest extends QpidBrokerTestCase { - private List<Exception> _exceptions = new ArrayList<Exception>(); - - protected void setUp() throws Exception - { - super.setUp(); - } - - protected void tearDown() throws Exception + /** + * Tests the basic produce/consume behaviour of a temporary queue. + */ + public void testMessageDeliveryUsingTemporaryQueue() throws Exception { - super.tearDown(); - } - - protected Connection createConnection() throws Exception - { - return getConnection("guest", "guest"); - } - - public void testTemporaryQueue() throws Exception - { - Connection conn = createConnection(); - Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); - TemporaryQueue queue = session.createTemporaryQueue(); + final Connection conn = getConnection(); + final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryQueue queue = session.createTemporaryQueue(); assertNotNull(queue); - MessageProducer producer = session.createProducer(queue); - MessageConsumer consumer = session.createConsumer(queue); + final MessageProducer producer = session.createProducer(queue); + final MessageConsumer consumer = session.createConsumer(queue); conn.start(); producer.send(session.createTextMessage("hello")); TextMessage tm = (TextMessage) consumer.receive(2000); - assertNotNull(tm); + assertNotNull("Message not received", tm); assertEquals("hello", tm.getText()); + } - try - { - queue.delete(); - fail("Expected JMSException : should not be able to delete while there are active consumers"); - } - catch (JMSException je) - { - ; //pass - } - - consumer.close(); + /** + * Tests that a temporary queue cannot be used by another {@link Session}. + */ + public void testUseFromAnotherSessionProhibited() throws Exception + { + final Connection conn = getConnection(); + final Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryQueue queue = session1.createTemporaryQueue(); + assertNotNull(queue); try { - queue.delete(); + session2.createConsumer(queue); + fail("Expected a JMSException when subscribing to a temporary queue created on a different session"); } catch (JMSException je) { - fail("Unexpected Exception: " + je.getMessage()); + //pass + assertEquals("Cannot consume from a temporary destination created on another session", je.getMessage()); } - - conn.close(); - } - - public void tUniqueness() throws Exception - { - int numProcs = Runtime.getRuntime().availableProcessors(); - final int threadsProc = 5; - - runUniqueness(1, 10); - runUniqueness(numProcs * threadsProc, 10); - runUniqueness(numProcs * threadsProc, 100); - runUniqueness(numProcs * threadsProc, 500); } - void runUniqueness(int makers, int queues) throws Exception + /** + * Tests that the client is able to explicitly delete a temporary queue using + * {@link TemporaryQueue#delete()} and is prevented from deleting one that + * still has consumers. + * + * Note: Under < 0-10 {@link TemporaryQueue#delete()} only marks the queue as deleted + * on the client. 0-10 causes the queue to be deleted from the Broker. + */ + public void testExplictTemporaryQueueDeletion() throws Exception { - Connection connection = createConnection(); - - Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); - - List<TempQueueMaker> tqList = new LinkedList<TempQueueMaker>(); - - //Create Makers - for (int m = 0; m < makers; m++) - { - tqList.add(new TempQueueMaker(session, queues)); - } - - - List<Thread> threadList = new LinkedList<Thread>(); - - //Create Makers - for (TempQueueMaker maker : tqList) - { - threadList.add(new Thread(maker)); - } - - //Start threads - for (Thread thread : threadList) - { - thread.start(); - } - - // Join Threads - for (Thread thread : threadList) - { - try - { - thread.join(); - } - catch (InterruptedException e) - { - fail("Couldn't correctly join threads"); - } - } - + final Connection conn = getConnection(); + final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final AMQSession<?, ?> amqSession = (AMQSession<?, ?>)session; // Required to observe the queue binding on the Broker + final TemporaryQueue queue = session.createTemporaryQueue(); + assertNotNull(queue); + final MessageConsumer consumer = session.createConsumer(queue); + conn.start(); - List<AMQQueue> list = new LinkedList<AMQQueue>(); + assertTrue("Queue should be bound", amqSession.isQueueBound((AMQDestination)queue)); - // Test values - for (TempQueueMaker maker : tqList) + try { - check(maker, list); + queue.delete(); + fail("Expected JMSException : should not be able to delete while there are active consumers"); } - - Assert.assertEquals("Not enough queues made.", makers * queues, list.size()); - - connection.close(); - } - - private void check(TempQueueMaker tq, List<AMQQueue> list) - { - for (AMQQueue q : tq.getList()) + catch (JMSException je) { - if (list.contains(q)) - { - fail(q + " already exists."); - } - else - { - list.add(q); - } + //pass + assertEquals("Temporary Queue has consumers so cannot be deleted", je.getMessage()); } - } - - - class TempQueueMaker implements Runnable - { - List<AMQQueue> _queues; - Session _session; - private int _count; + consumer.close(); + // Now deletion should succeed. + queue.delete(); - TempQueueMaker(Session session, int queues) throws JMSException + try { - _queues = new LinkedList<AMQQueue>(); - - _count = queues; - - _session = session; + session.createConsumer(queue); + fail("Exception not thrown"); } - - public void run() + catch (JMSException je) { - int i = 0; - try - { - for (; i < _count; i++) - { - _queues.add((AMQQueue) _session.createTemporaryQueue()); - } - } - catch (JMSException jmse) - { - //stop - } + //pass + assertEquals("Cannot consume from a deleted destination", je.getMessage()); } - List<AMQQueue> getList() + if (isBroker010()) { - return _queues; + assertFalse("Queue should no longer be bound", amqSession.isQueueBound((AMQDestination)queue)); } } - public void testQPID1217() throws Exception - { - Connection conA = getConnection(); - conA.setExceptionListener(this); - Session sessA = conA.createSession(false, Session.AUTO_ACKNOWLEDGE); - TemporaryQueue temp = sessA.createTemporaryQueue(); - - MessageProducer prod = sessA.createProducer(temp); - prod.send(sessA.createTextMessage("hi")); - - Thread.sleep(500); - assertTrue("Exception received", _exceptions.isEmpty()); - - Connection conB = getConnection(); - Session sessB = conB.createSession(false, Session.AUTO_ACKNOWLEDGE); - - JMSException ex = null; - try - { - MessageConsumer consB = sessB.createConsumer(temp); - } - catch (JMSException e) - { - ex = e; - } - assertNotNull(ex); - } - - public static junit.framework.Test suite() + /** + * Tests that a temporary queue remains available for reuse even after its initial + * consumer has disconnected. + * + * This test would fail under < 0-10 as their temporary queues are deleted automatically + * (broker side) after the last consumer disconnects (so message2 would be lost). For this + * reason this test is excluded from those profiles. + */ + public void testTemporaryQueueReused() throws Exception { - return new junit.framework.TestSuite(TemporaryQueueTest.class); - } + final Connection conn = getConnection(); + final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryQueue queue = session.createTemporaryQueue(); + assertNotNull(queue); - public void onException(JMSException arg0) - { - _exceptions.add(arg0); + final MessageProducer producer1 = session.createProducer(queue); + final MessageConsumer consumer1 = session.createConsumer(queue); + conn.start(); + producer1.send(session.createTextMessage("message1")); + producer1.send(session.createTextMessage("message2")); + TextMessage tm = (TextMessage) consumer1.receive(2000); + assertNotNull("Message not received by first consumer", tm); + assertEquals("message1", tm.getText()); + consumer1.close(); + + final MessageConsumer consumer2 = session.createConsumer(queue); + conn.start(); + tm = (TextMessage) consumer2.receive(2000); + assertNotNull("Message not received by second consumer", tm); + assertEquals("message2", tm.getText()); + consumer2.close(); } - } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java index de092fc893..f5e0ed75d2 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java @@ -50,7 +50,6 @@ public class MessageRequeueTest extends QpidBrokerTestCase protected final String queue = "direct://amq.direct//message-requeue-test-queue"; protected String payload = "Message:"; - //protected final String BROKER = "vm://:1"; protected final String BROKER = "tcp://127.0.0.1:5672"; private boolean testReception = true; @@ -155,8 +154,8 @@ public class MessageRequeueTest extends QpidBrokerTestCase _logger.info("consumed: " + messagesReceived); assertEquals("number of consumed messages does not match initial data", (int) numTestMessages, messagesReceived); - // wit 0_10 we can have a delivery tag of 0 - if (conn.isBroker08()) + // with 0_10 we can have a delivery tag of 0 + if (!conn.isBroker010()) { for (long b : messageLog) { @@ -224,7 +223,7 @@ public class MessageRequeueTest extends QpidBrokerTestCase StringBuilder list = new StringBuilder(); list.append("Failed to receive:"); int failed = 0; - if (conn.isBroker08()) + if (!conn.isBroker010()) { for (long b : receieved) { diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java index 989ac98747..80422cf3e9 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java @@ -52,7 +52,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase */ public void testDurSubRestoredAfterNonPersistentMessageSent() throws Exception { - if (isBrokerStorePersistent() || !isBroker08()) + if (isBrokerStorePersistent()) { TopicConnectionFactory factory = getConnectionFactory(); Topic topic = (Topic) getInitialContext().lookup(_topicName); @@ -116,7 +116,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase */ public void testDurSubRestoresMessageSelector() throws Exception { - if (isBrokerStorePersistent() || !isBroker08()) + if (isBrokerStorePersistent()) { TopicConnectionFactory factory = getConnectionFactory(); Topic topic = (Topic) getInitialContext().lookup(_topicName); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java index 830421a01f..97452ad1c8 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java @@ -25,12 +25,14 @@ import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.message.NonQpidObjectMessage; +import org.apache.qpid.client.message.QpidMessageProperties; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.jms.Connection; import javax.jms.Destination; import javax.jms.Message; import javax.jms.MessageConsumer; @@ -39,7 +41,11 @@ import javax.jms.MessageProducer; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.jms.Session; +import javax.jms.Topic; + import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; /** * @author Apache Software Foundation @@ -163,4 +169,39 @@ public class JMSPropertiesTest extends QpidBrokerTestCase con.close(); } + /** + * Test Goal : Test if custom message properties can be set and retrieved properly with out an error. + * Also test if unsupported properties are filtered out. See QPID-2930. + */ + public void testQpidExtensionProperties() throws Exception + { + Connection con = getConnection("guest", "guest"); + Session ssn = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE); + con.start(); + + Topic topic = ssn.createTopic("test"); + MessageConsumer consumer = ssn.createConsumer(topic); + MessageProducer prod = ssn.createProducer(topic); + Message m = ssn.createMessage(); + m.setObjectProperty("foo-bar", "foobar".getBytes()); + m.setObjectProperty(QpidMessageProperties.AMQP_0_10_APP_ID, "my-app-id"); + prod.send(m); + + Message msg = consumer.receive(1000); + assertNotNull(msg); + + Enumeration<String> enu = msg.getPropertyNames(); + Map<String,String> map = new HashMap<String,String>(); + while (enu.hasMoreElements()) + { + String name = enu.nextElement(); + String value = msg.getStringProperty(name); + map.put(name, value); + } + + assertFalse("Property 'foo-bar' should have been filtered out",map.containsKey("foo-bar")); + assertEquals("Property "+ QpidMessageProperties.AMQP_0_10_APP_ID + " should be present","my-app-id",msg.getStringProperty(QpidMessageProperties.AMQP_0_10_APP_ID)); + assertEquals("Property "+ QpidMessageProperties.AMQP_0_10_ROUTING_KEY + " should be present","test",msg.getStringProperty(QpidMessageProperties.AMQP_0_10_ROUTING_KEY)); + + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java index 0f799073b4..39691a5c7c 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java @@ -20,6 +20,10 @@ */ package org.apache.qpid.test.unit.message; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQHeadersExchange; import org.apache.qpid.client.AMQQueue; @@ -50,21 +54,8 @@ import javax.jms.StreamMessage; */ public class StreamMessageTest extends QpidBrokerTestCase { - private static final Logger _logger = LoggerFactory.getLogger(StreamMessageTest.class); - public String _connectionString = "vm://:1"; - - protected void setUp() throws Exception - { - super.setUp(); - } - - protected void tearDown() throws Exception - { - super.tearDown(); - } - public void testStreamMessageEOF() throws Exception { Connection con = (AMQConnection) getConnection("guest", "guest"); @@ -114,6 +105,7 @@ public class StreamMessageTest extends QpidBrokerTestCase try { msg2.readByte(); + fail("Expected exception not thrown"); } catch (Exception e) { @@ -125,6 +117,9 @@ public class StreamMessageTest extends QpidBrokerTestCase public void testModifyReceivedMessageExpandsBuffer() throws Exception { + final CountDownLatch awaitMessages = new CountDownLatch(1); + final AtomicReference<Throwable> listenerCaughtException = new AtomicReference<Throwable>(); + AMQConnection con = (AMQConnection) getConnection("guest", "guest"); AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE); AMQQueue queue = new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("testQ")); @@ -134,28 +129,38 @@ public class StreamMessageTest extends QpidBrokerTestCase public void onMessage(Message message) { - StreamMessage sm = (StreamMessage) message; + final StreamMessage sm = (StreamMessage) message; try { sm.clearBody(); + // it is legal to extend a stream message's content sm.writeString("dfgjshfslfjshflsjfdlsjfhdsljkfhdsljkfhsd"); } - catch (JMSException e) + catch (Throwable t) + { + listenerCaughtException.set(t); + } + finally { - _logger.error("Error when writing large string to received msg: " + e, e); - fail("Error when writing large string to received msg" + e); + awaitMessages.countDown(); } } }); Connection con2 = (AMQConnection) getConnection("guest", "guest"); AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE); - MessageProducer mandatoryProducer = producerSession.createProducer(queue); + MessageProducer producer = producerSession.createProducer(queue); con.start(); StreamMessage sm = producerSession.createStreamMessage(); sm.writeInt(42); - mandatoryProducer.send(sm); - Thread.sleep(2000); + producer.send(sm); + + // Allow up to five seconds for the message to arrive with the consumer + final boolean completed = awaitMessages.await(5, TimeUnit.SECONDS); + assertTrue("Message did not arrive with consumer within a reasonable time", completed); + final Throwable listenerException = listenerCaughtException.get(); + assertNull("No exception should be caught by listener : " + listenerException, listenerException); + con.close(); con2.close(); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java index fe929b4965..978ebfa93f 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java @@ -20,17 +20,20 @@ */ package org.apache.qpid.test.unit.message; -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.Session; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.Properties; +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; import javax.naming.InitialContext; -import javax.jms.*; -import java.util.Properties; -import java.io.*; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; /** @@ -41,8 +44,6 @@ import java.io.*; */ public class UTF8Test extends QpidBrokerTestCase { - private static final Logger _logger = LoggerFactory.getLogger(UTF8Test.class); - public void testPlainEn() throws Exception { invoke("UTF8En"); @@ -65,38 +66,24 @@ public class UTF8Test extends QpidBrokerTestCase private void runTest(String exchangeName, String queueName, String routingKey, String data) throws Exception { - _logger.info("Running test for exchange: " + exchangeName - + " queue Name: " + queueName - + " routing key: " + routingKey); - declareQueue(exchangeName, routingKey, queueName); + Connection con = getConnection(); + Session sess = con.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); + final Destination dest = getDestination(exchangeName, routingKey, queueName); + + final MessageConsumer msgCons = sess.createConsumer(dest); + con.start(); - javax.jms.Connection con = getConnection(); - javax.jms.Session sess = con.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); - Destination dest = getDestination(exchangeName, routingKey, queueName); // Send data MessageProducer msgProd = sess.createProducer(dest); TextMessage message = sess.createTextMessage(data); msgProd.send(message); + // consume data - MessageConsumer msgCons = sess.createConsumer(dest); - con.start(); TextMessage m = (TextMessage) msgCons.receive(RECEIVE_TIMEOUT); assertNotNull(m); assertEquals(m.getText(), data); } - private void declareQueue(String exch, String routkey, String qname) throws Exception - { - Connection conn = new Connection(); - conn.connect("localhost", QpidBrokerTestCase.DEFAULT_PORT, "test", "guest", "guest",false); - Session sess = conn.createSession(0); - sess.exchangeDeclare(exch, "direct", null, null); - sess.queueDeclare(qname, null, null); - sess.exchangeBind(qname, exch, routkey, null); - sess.sync(); - conn.close(); - } - private Destination getDestination(String exch, String routkey, String qname) throws Exception { Properties props = new Properties(); diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTransactedPublishTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTransactedPublishTest.java deleted file mode 100644 index 3ec7937812..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTransactedPublishTest.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * - * 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.test.unit.publish; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.test.utils.FailoverBaseCase; - -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TransactionRolledBackException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -/** - * QPID-1816 : Whilst testing Acknoledgement after failover this completes testing - * of the client after failover. When we have a dirty session we should receive - * an error if we attempt to publish. This test ensures that both in the synchronous - * and asynchronous message delivery paths we receive the expected exceptions at - * the expected time. - */ -public class DirtyTransactedPublishTest extends FailoverBaseCase implements ConnectionListener -{ - protected CountDownLatch _failoverCompleted = new CountDownLatch(1); - - protected int NUM_MESSAGES; - protected Connection _connection; - protected Queue _queue; - protected Session _consumerSession; - protected MessageConsumer _consumer; - protected MessageProducer _producer; - - private static final String MSG = "MSG"; - private static final String SEND_FROM_ON_MESSAGE_TEXT = "sendFromOnMessage"; - protected CountDownLatch _receviedAll; - protected AtomicReference<Exception> _causeOfFailure = new AtomicReference<Exception>(null); - - @Override - protected void setUp() throws Exception - { - super.setUp(); - NUM_MESSAGES = 10; - - _queue = getTestQueue(); - - //Create Producer put some messages on the queue - _connection = getConnection(); - } - - /** - * Initialise the test variables - * @param transacted is this a transacted test - * @param mode if not trasacted then what ack mode to use - * @throws Exception if there is a setup issue. - */ - protected void init(boolean transacted, int mode) throws Exception - { - _consumerSession = _connection.createSession(transacted, mode); - _consumer = _consumerSession.createConsumer(_queue); - _producer = _consumerSession.createProducer(_queue); - - // These should all end up being prefetched by session - sendMessage(_consumerSession, _queue, 1); - - assertEquals("Wrong number of messages on queue", 1, - ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); - } - - /** - * If a transacted session has failed over whilst it has uncommitted sent - * data then we need to throw a TransactedRolledbackException on commit() - * - * The alternative would be to maintain a replay buffer so that the message - * could be resent. This is not currently implemented - * - * @throws Exception if something goes wrong. - */ - public void testDirtySendingSynchronousTransacted() throws Exception - { - Session producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED); - - // Ensure we get failover notifications - ((AMQConnection) _connection).setConnectionListener(this); - - MessageProducer producer = producerSession.createProducer(_queue); - - // Create and send message 0 - Message msg = producerSession.createMessage(); - msg.setIntProperty(INDEX, 0); - producer.send(msg); - - // DON'T commit message .. fail connection - - failBroker(getFailingPort()); - - // Ensure destination exists for sending - producerSession.createConsumer(_queue).close(); - - // Send the next message - msg.setIntProperty(INDEX, 1); - try - { - producer.send(msg); - fail("Should fail with Qpid as we provide early warning of the dirty session via a JMSException."); - } - catch (JMSException jmse) - { - assertEquals("Early warning of dirty session not correct", - "Failover has occurred and session is dirty so unable to send.", jmse.getMessage()); - } - - // Ignore that the session is dirty and attempt to commit to validate the - // exception is thrown. AND that the above failure notification did NOT - // clean up the session. - - try - { - producerSession.commit(); - fail("Session is dirty we should get an TransactionRolledBackException"); - } - catch (TransactionRolledBackException trbe) - { - // Normal path. - } - - // Resending of messages should now work ok as the commit was forcilbly rolledback - msg.setIntProperty(INDEX, 0); - producer.send(msg); - msg.setIntProperty(INDEX, 1); - producer.send(msg); - - producerSession.commit(); - - assertEquals("Wrong number of messages on queue", 2, - ((AMQSession) producerSession).getQueueDepth((AMQDestination) _queue)); - } - - /** - * If a transacted session has failed over whilst it has uncommitted sent - * data then we need to throw a TransactedRolledbackException on commit() - * - * The alternative would be to maintain a replay buffer so that the message - * could be resent. This is not currently implemented - * - * @throws Exception if something goes wrong. - */ - public void testDirtySendingOnMessageTransacted() throws Exception - { - NUM_MESSAGES = 1; - _receviedAll = new CountDownLatch(NUM_MESSAGES); - ((AMQConnection) _connection).setConnectionListener(this); - - init(true, Session.SESSION_TRANSACTED); - - _consumer.setMessageListener(new MessageListener() - { - - public void onMessage(Message message) - { - try - { - // Create and send message 0 - Message msg = _consumerSession.createMessage(); - msg.setIntProperty(INDEX, 0); - _producer.send(msg); - - // DON'T commit message .. fail connection - - failBroker(getFailingPort()); - - // rep - repopulateBroker(); - - // Destination will exist as this failBroker will populate - // the queue with 1 message - - // Send the next message - msg.setIntProperty(INDEX, 1); - try - { - _producer.send(msg); - fail("Should fail with Qpid as we provide early warning of the dirty session via a JMSException."); - } - catch (JMSException jmse) - { - assertEquals("Early warning of dirty session not correct", - "Failover has occurred and session is dirty so unable to send.", jmse.getMessage()); - } - - // Ignore that the session is dirty and attempt to commit to validate the - // exception is thrown. AND that the above failure notification did NOT - // clean up the session. - - try - { - _consumerSession.commit(); - fail("Session is dirty we should get an TransactionRolledBackException"); - } - catch (TransactionRolledBackException trbe) - { - // Normal path. - } - - // Resend messages - msg.setIntProperty(INDEX, 0); - msg.setStringProperty(MSG, SEND_FROM_ON_MESSAGE_TEXT); - _producer.send(msg); - msg.setIntProperty(INDEX, 1); - msg.setStringProperty(MSG, SEND_FROM_ON_MESSAGE_TEXT); - _producer.send(msg); - - _consumerSession.commit(); - - // Stop this consumer .. can't do _consumer.stop == DEADLOCK - // this doesn't seem to stop dispatcher running - _connection.stop(); - - // Signal that the onMessage send part of test is complete - // main thread can validate that messages are correct - _receviedAll.countDown(); - - } - catch (Exception e) - { - fail(e); - } - - } - - }); - - _connection.start(); - - if (!_receviedAll.await(10000L, TimeUnit.MILLISECONDS)) - { - // Check to see if we ended due to an exception in the onMessage handler - Exception cause = _causeOfFailure.get(); - if (cause != null) - { - cause.printStackTrace(); - fail(cause.getMessage()); - } - else - { - fail("All messages not received:" + _receviedAll.getCount() + "/" + NUM_MESSAGES); - } - } - - // Check to see if we ended due to an exception in the onMessage handler - Exception cause = _causeOfFailure.get(); - if (cause != null) - { - cause.printStackTrace(); - fail(cause.getMessage()); - } - - _consumer.close(); - _consumerSession.close(); - - _consumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - _connection.start(); - - // Validate that we could send the messages as expected. - assertEquals("Wrong number of messages on queue", 3, - ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue)); - - MessageConsumer consumer = _consumerSession.createConsumer(_queue); - - //Validate the message sent to setup the failed over broker. - Message message = consumer.receive(1000); - assertNotNull("Message " + 0 + " not received.", message); - assertEquals("Incorrect message received", 0, message.getIntProperty(INDEX)); - - // Validate the two messages sent from within the onMessage - for (int index = 0; index <= 1; index++) - { - message = consumer.receive(1000); - assertNotNull("Message " + index + " not received.", message); - assertEquals("Incorrect message received", index, message.getIntProperty(INDEX)); - assertEquals("Incorrect message text for message:" + index, SEND_FROM_ON_MESSAGE_TEXT, message.getStringProperty(MSG)); - } - - assertNull("Extra message received.", consumer.receiveNoWait()); - - _consumerSession.close(); - - assertEquals("Wrong number of messages on queue", 0, - ((AMQSession) getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE)).getQueueDepth((AMQDestination) _queue)); - } - - private void repopulateBroker() throws Exception - { - // Repopulate this new broker so we can test what happends after failover - - //Get the connection to the first (main port) broker. - Connection connection = getConnection(); - // Use a transaction to send messages so we can be sure they arrive. - Session session = connection.createSession(true, Session.SESSION_TRANSACTED); - // ensure destination is created. - session.createConsumer(_queue).close(); - - sendMessage(session, _queue, NUM_MESSAGES); - - assertEquals("Wrong number of messages on queue", NUM_MESSAGES, - ((AMQSession) session).getQueueDepth((AMQDestination) _queue)); - - connection.close(); - } - - // AMQConnectionListener Interface.. used so we can validate that we - // actually failed over. - - public void bytesSent(long count) - { - } - - public void bytesReceived(long count) - { - } - - public boolean preFailover(boolean redirect) - { - //Allow failover - return true; - } - - public boolean preResubscribe() - { - //Allow failover - return true; - } - - public void failoverComplete() - { - _failoverCompleted.countDown(); - } - - /** - * Override so we can block until failover has completd - * - * @param port int the port of the broker to fail. - */ - @Override - public void failBroker(int port) - { - super.failBroker(port); - - try - { - if (!_failoverCompleted.await(DEFAULT_FAILOVER_TIME, TimeUnit.MILLISECONDS)) - { - fail("Failover did not occur in specified time:" + DEFAULT_FAILOVER_TIME); - } - } - catch (InterruptedException e) - { - fail("Failover was interuppted"); - } - } - - /** - * Pass the given exception back to the waiting thread to fail the test run. - * - * @param e The exception that is causing the test to fail. - */ - protected void fail(Exception e) - { - _causeOfFailure.set(e); - // End the test. - while (_receviedAll.getCount() != 0) - { - _receviedAll.countDown(); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java index d799b141c0..9ea116ae53 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java @@ -262,7 +262,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase producer.send(session1.createTextMessage("B")); _logger.info("Receive message on consumer 1 :expecting B"); - msg = consumer1.receive(500); + msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull("Consumer 1 should get message 'B'.", msg); assertEquals("Incorrect Message received on consumer1.", "B", ((TextMessage) msg).getText()); _logger.info("Receive message on consumer 1 :expecting null"); @@ -287,13 +287,13 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase else { _logger.info("Receive message on consumer 3 :expecting B"); - msg = consumer3.receive(500); + msg = consumer3.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull("Consumer 3 should get message 'B'.", msg); assertEquals("Incorrect Message received on consumer3.", "B", ((TextMessage) msg).getText()); } _logger.info("Receive message on consumer 1 :expecting C"); - msg = consumer1.receive(500); + msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull("Consumer 1 should get message 'C'.", msg); assertEquals("Incorrect Message received on consumer1.", "C", ((TextMessage) msg).getText()); _logger.info("Receive message on consumer 1 :expecting null"); @@ -301,7 +301,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase assertNull("There should be no more messages for consumption on consumer1.", msg); _logger.info("Receive message on consumer 3 :expecting C"); - msg = consumer3.receive(500); + msg = consumer3.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull("Consumer 3 should get message 'C'.", msg); assertEquals("Incorrect Message received on consumer3.", "C", ((TextMessage) msg).getText()); _logger.info("Receive message on consumer 3 :expecting null"); @@ -358,7 +358,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase // Send message and check that both consumers get it and only it. producer.send(session0.createTextMessage("A")); - msg = consumer1.receive(500); + msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull("Message should be available", msg); assertEquals("Message Text doesn't match", "A", ((TextMessage) msg).getText()); msg = consumer1.receive(500); @@ -729,7 +729,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase conn.start(); - Message rMsg = subB.receive(1000); + Message rMsg = subB.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull(rMsg); assertEquals("Content was wrong", "testResubscribeWithChangedSelectorAndRestart2", @@ -797,7 +797,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase conn.start(); - Message rMsg = subTwo.receive(1000); + Message rMsg = subTwo.receive(POSITIVE_RECEIVE_TIMEOUT); assertNotNull(rMsg); assertEquals("Content was wrong", "testResubscribeWithChangedSelectorAndRestart1", diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TemporaryTopicTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TemporaryTopicTest.java new file mode 100644 index 0000000000..c89b13a0f9 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TemporaryTopicTest.java @@ -0,0 +1,182 @@ +/* + * + * 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.test.unit.topic; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TemporaryTopic; +import javax.jms.TextMessage; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + + +/** + * Tests the behaviour of {@link TemporaryTopic}. + */ +public class TemporaryTopicTest extends QpidBrokerTestCase +{ + /** + * Tests the basic publish/subscribe behaviour of a temporary topic. Single + * message is sent to two subscribers. + */ + public void testMessageDeliveryUsingTemporaryTopic() throws Exception + { + final Connection conn = getConnection(); + final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryTopic topic = session.createTemporaryTopic(); + assertNotNull(topic); + final MessageProducer producer = session.createProducer(topic); + final MessageConsumer consumer1 = session.createConsumer(topic); + final MessageConsumer consumer2 = session.createConsumer(topic); + conn.start(); + producer.send(session.createTextMessage("hello")); + + final TextMessage tm1 = (TextMessage) consumer1.receive(2000); + final TextMessage tm2 = (TextMessage) consumer2.receive(2000); + + assertNotNull("Message not received by subscriber1", tm1); + assertEquals("hello", tm1.getText()); + assertNotNull("Message not received by subscriber2", tm2); + assertEquals("hello", tm2.getText()); + } + + /** + * Tests that the client is able to explicitly delete a temporary topic using + * {@link TemporaryTopic#delete()} and is prevented from deleting one that + * still has consumers. + * + * Note: Under < 0-10 {@link TemporaryTopic#delete()} only marks the queue as deleted + * on the client. 0-10 causes the topic to be deleted from the Broker. + */ + public void testExplictTemporaryTopicDeletion() throws Exception + { + final Connection conn = getConnection(); + + final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryTopic topic = session.createTemporaryTopic(); + assertNotNull(topic); + final MessageConsumer consumer = session.createConsumer(topic); + conn.start(); + try + { + topic.delete(); + fail("Expected JMSException : should not be able to delete while there are active consumers"); + } + catch (JMSException je) + { + //pass + assertEquals("Temporary Topic has consumers so cannot be deleted", je.getMessage()); + } + + consumer.close(); + + // Now deletion should succeed. + topic.delete(); + + try + { + session.createConsumer(topic); + fail("Exception not thrown"); + } + catch (JMSException je) + { + //pass + assertEquals("Cannot consume from a deleted destination", je.getMessage()); + } + } + + /** + * Tests that a temporary topic cannot be used by another {@link Session}. + */ + public void testUseFromAnotherSessionProhibited() throws Exception + { + final Connection conn = getConnection(); + final Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryTopic topic = session1.createTemporaryTopic(); + + try + { + session2.createConsumer(topic); + fail("Expected a JMSException when subscribing to a temporary topic created on a different session"); + } + catch (JMSException je) + { + // pass + assertEquals("Cannot consume from a temporary destination created on another session", je.getMessage()); + } + } + + /** + * Tests that the client is prohibited from creating a durable subscriber for a temporary + * queue. + */ + public void testDurableSubscriptionProhibited() throws Exception + { + final Connection conn = getConnection(); + + final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryTopic topic = session.createTemporaryTopic(); + assertNotNull(topic); + try + { + session.createDurableSubscriber(topic, null); + fail("Expected JMSException : should not be able to create durable subscription from temp topic"); + } + catch (JMSException je) + { + //pass + assertEquals("Cannot create a durable subscription with a temporary topic: " + topic.toString(), je.getMessage()); + } + } + + /** + * Tests that a temporary topic remains available for reuse even after its initial + * subscribers have disconnected. + */ + public void testTemporaryTopicReused() throws Exception + { + final Connection conn = getConnection(); + final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + final TemporaryTopic topic = session.createTemporaryTopic(); + assertNotNull(topic); + + final MessageProducer producer = session.createProducer(topic); + final MessageConsumer consumer1 = session.createConsumer(topic); + conn.start(); + producer.send(session.createTextMessage("message1")); + TextMessage tm = (TextMessage) consumer1.receive(2000); + assertNotNull("Message not received by first consumer", tm); + assertEquals("message1", tm.getText()); + consumer1.close(); + + final MessageConsumer consumer2 = session.createConsumer(topic); + conn.start(); + producer.send(session.createTextMessage("message2")); + tm = (TextMessage) consumer2.receive(2000); + assertNotNull("Message not received by second consumer", tm); + assertEquals("message2", tm.getText()); + consumer2.close(); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java index eee232e113..826545a23d 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java @@ -20,38 +20,28 @@ */ package org.apache.qpid.test.unit.topic; +import javax.jms.Connection; import javax.jms.InvalidDestinationException; -import javax.jms.JMSException; +import javax.jms.Message; import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; import javax.jms.Session; -import javax.jms.TemporaryTopic; import javax.jms.TextMessage; +import javax.jms.Topic; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import javax.jms.TopicSubscriber; import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQTopic; -import org.apache.qpid.client.AMQTopicSessionAdaptor; import org.apache.qpid.test.utils.QpidBrokerTestCase; /** @author Apache Software Foundation */ public class TopicSessionTest extends QpidBrokerTestCase { - - protected void setUp() throws Exception - { - super.setUp(); - } - - protected void tearDown() throws Exception - { - super.tearDown(); - } - - public void testTopicSubscriptionUnsubscription() throws Exception { @@ -228,83 +218,6 @@ public class TopicSessionTest extends QpidBrokerTestCase con.close(); } - public void testSendingSameMessage() throws Exception - { - AMQConnection conn = (AMQConnection) getConnection("guest", "guest"); - TopicSession session = conn.createTopicSession(true, Session.AUTO_ACKNOWLEDGE); - TemporaryTopic topic = session.createTemporaryTopic(); - assertNotNull(topic); - TopicPublisher producer = session.createPublisher(topic); - MessageConsumer consumer = session.createConsumer(topic); - conn.start(); - TextMessage sentMessage = session.createTextMessage("Test Message"); - producer.send(sentMessage); - session.commit(); - TextMessage receivedMessage = (TextMessage) consumer.receive(2000); - assertNotNull(receivedMessage); - assertEquals(sentMessage.getText(), receivedMessage.getText()); - producer.send(sentMessage); - session.commit(); - receivedMessage = (TextMessage) consumer.receive(2000); - assertNotNull(receivedMessage); - assertEquals(sentMessage.getText(), receivedMessage.getText()); - session.commit(); - conn.close(); - - } - - public void testTemporaryTopic() throws Exception - { - AMQConnection conn = (AMQConnection) getConnection("guest", "guest"); - TopicSession session = conn.createTopicSession(true, Session.AUTO_ACKNOWLEDGE); - TemporaryTopic topic = session.createTemporaryTopic(); - assertNotNull(topic); - TopicPublisher producer = session.createPublisher(topic); - MessageConsumer consumer = session.createConsumer(topic); - conn.start(); - producer.send(session.createTextMessage("hello")); - session.commit(); - TextMessage tm = (TextMessage) consumer.receive(2000); - assertNotNull(tm); - assertEquals("hello", tm.getText()); - session.commit(); - try - { - topic.delete(); - fail("Expected JMSException : should not be able to delete while there are active consumers"); - } - catch (JMSException je) - { - ; //pass - } - - consumer.close(); - - try - { - topic.delete(); - } - catch (JMSException je) - { - fail("Unexpected Exception: " + je.getMessage()); - } - - TopicSession session2 = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); - try - { - session2.createConsumer(topic); - fail("Expected a JMSException when subscribing to a temporary topic created on adifferent session"); - } - catch (JMSException je) - { - ; // pass - } - - - conn.close(); - } - - public void testNoLocal() throws Exception { @@ -398,56 +311,39 @@ public class TopicSessionTest extends QpidBrokerTestCase } /** - * This tests QPID-1191, where messages which are sent to a topic but are not consumed by a subscriber - * due to a selector can be leaked. - * @throws Exception + * This tests was added to demonstrate QPID-3542. The Java Client when used with the CPP Broker was failing to + * ack messages received that did not match the selector. This meant the messages remained indefinitely on the Broker. */ - public void testNonMatchingMessagesDoNotFillQueue() throws Exception + public void testNonMatchingMessagesHandledCorrectly() throws Exception { - AMQConnection con = (AMQConnection) getConnection("guest", "guest"); - - // Setup Topic - AMQTopic topic = new AMQTopic(con, "testNoLocal"); - - TopicSession session = con.createTopicSession(true, AMQSession.NO_ACKNOWLEDGE); + final String topicName = getName(); + final String clientId = "clientId" + topicName; + final Connection con1 = getConnection(); + final Session session1 = con1.createSession(false, Session.AUTO_ACKNOWLEDGE); + final Topic topic1 = session1.createTopic(topicName); + final AMQQueue internalNameOnBroker = new AMQQueue("amq.topic", "clientid" + ":" + clientId); // Setup subscriber with selector - TopicSubscriber selector = session.createSubscriber(topic, "Selector = 'select'", false); - TopicPublisher publisher = session.createPublisher(topic); + final TopicSubscriber subscriberWithSelector = session1.createDurableSubscriber(topic1, clientId, "Selector = 'select'", false); + final MessageProducer publisher = session1.createProducer(topic1); - con.start(); - TextMessage m; - TextMessage message; + con1.start(); // Send non-matching message - message = session.createTextMessage("non-matching 1"); - publisher.publish(message); - session.commit(); + final Message sentMessage = session1.createTextMessage("hello"); + sentMessage.setStringProperty("Selector", "nonMatch"); + publisher.send(sentMessage); - // Send and consume matching message - message = session.createTextMessage("hello"); - message.setStringProperty("Selector", "select"); + // Try to consume non-message, expect this to fail. + final Message message1 = subscriberWithSelector.receive(1000); + assertNull("should not have received message", message1); + subscriberWithSelector.close(); - publisher.publish(message); - session.commit(); - - m = (TextMessage) selector.receive(1000); - assertNotNull("should have received message", m); - assertEquals("Message contents were wrong", "hello", m.getText()); + session1.close(); - // Send non-matching message - message = session.createTextMessage("non-matching 2"); - publisher.publish(message); - session.commit(); - - // Assert queue count is 0 - long depth = ((AMQTopicSessionAdaptor) session).getSession().getQueueDepth(topic); - assertEquals("Queue depth was wrong", 0, depth); - - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(TopicSessionTest.class); + // Now verify queue depth on broker. + final Session session2 = con1.createSession(false, Session.AUTO_ACKNOWLEDGE); + final long depth = ((AMQSession) session2).getQueueDepth(internalNameOnBroker); + assertEquals("Expected queue depth of zero", 0, depth); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java new file mode 100644 index 0000000000..fd8beffbe6 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java @@ -0,0 +1,74 @@ +/* + * + * 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.test.unit.transacted; + +/** + * This verifies that the default behaviour is not to time out transactions. + */ +public class TransactionTimeoutDisabledTest extends TransactionTimeoutTestCase +{ + @Override + protected void configure() throws Exception + { + // Setup housekeeping every second + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + + // No transaction timeout configuration. + } + + public void testProducerIdleCommit() throws Exception + { + try + { + send(5, 0); + + sleep(2.0f); + + _psession.commit(); + } + catch (Exception e) + { + fail("Should have succeeded"); + } + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } + + public void testProducerOpenCommit() throws Exception + { + try + { + send(5, 0.3f); + + _psession.commit(); + } + catch (Exception e) + { + fail("Should have succeeded"); + } + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java new file mode 100644 index 0000000000..f554b0089e --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java @@ -0,0 +1,308 @@ +/* + * + * 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.test.unit.transacted; + +/** + * This tests the behaviour of transactional sessions when the {@code transactionTimeout} configuration + * is set for a virtual host. + * + * A producer that is idle for too long or open for too long will have its connection closed and + * any further operations will fail with a 408 resource timeout exception. Consumers will not + * be affected by the transaction timeout configuration. + */ +public class TransactionTimeoutTest extends TransactionTimeoutTestCase +{ + + protected void configure() throws Exception + { + // Setup housekeeping every second + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + + if (getName().contains("ProducerIdle")) + { + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "0"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "0"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1500"); + } + else if (getName().contains("ProducerOpen")) + { + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "0"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "0"); + } + else + { + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); + setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1000"); + } + } + + public void testProducerIdle() throws Exception + { + sleep(2.0f); + + _psession.commit(); + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } + + public void testProducerIdleCommit() throws Exception + { + send(5, 0); + // Idle for more than idleClose to generate idle-warns and cause a close. + sleep(2.0f); + + try + { + _psession.commit(); + fail("Exception not thrown"); + } + catch (Exception e) + { + _exception = e; + } + + monitor(10, 0); + + check(IDLE); + } + + public void testProducerIdleCommitTwice() throws Exception + { + send(5, 0); + // Idle for less than idleClose to generate idle-warns + sleep(1.0f); + + _psession.commit(); + + send(5, 0); + // Now idle for more than idleClose to generate more idle-warns and cause a close. + sleep(2.0f); + + try + { + _psession.commit(); + fail("Exception not thrown"); + } + catch (Exception e) + { + _exception = e; + } + + monitor(15, 0); + + check(IDLE); + } + + public void testProducerIdleRollback() throws Exception + { + send(5, 0); + // Now idle for more than idleClose to generate more idle-warns and cause a close. + sleep(2.0f); + try + { + _psession.rollback(); + fail("Exception not thrown"); + } + catch (Exception e) + { + _exception = e; + } + + monitor(10, 0); + + check(IDLE); + } + + public void testProducerIdleRollbackTwice() throws Exception + { + send(5, 0); + // Idle for less than idleClose to generate idle-warns + sleep(1.0f); + _psession.rollback(); + send(5, 0); + // Now idle for more than idleClose to generate more idle-warns and cause a close. + sleep(2.0f); + try + { + _psession.rollback(); + fail("should fail"); + } + catch (Exception e) + { + _exception = e; + } + + monitor(15, 0); + + check(IDLE); + } + + public void testProducerOpenCommit() throws Exception + { + try + { + // Sleep between sends to cause open warns and then cause a close. + send(6, 0.5f); + _psession.commit(); + fail("Exception not thrown"); + } + catch (Exception e) + { + _exception = e; + } + + monitor(0, 10); + + check(OPEN); + } + + public void testProducerOpenCommitTwice() throws Exception + { + send(5, 0); + sleep(1.0f); + _psession.commit(); + + try + { + // Now sleep between sends to cause open warns and then cause a close. + send(6, 0.5f); + _psession.commit(); + fail("Exception not thrown"); + } + catch (Exception e) + { + _exception = e; + } + + monitor(0, 10); + + check(OPEN); + } + + public void testConsumerCommitClose() throws Exception + { + send(1, 0); + + _psession.commit(); + + expect(1, 0); + + _csession.commit(); + + sleep(3.0f); + + _csession.close(); + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } + + public void testConsumerIdleReceiveCommit() throws Exception + { + send(1, 0); + + _psession.commit(); + + sleep(2.0f); + + expect(1, 0); + + sleep(2.0f); + + _csession.commit(); + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } + + public void testConsumerIdleCommit() throws Exception + { + send(1, 0); + + _psession.commit(); + + expect(1, 0); + + sleep(2.0f); + + _csession.commit(); + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } + + public void testConsumerIdleRollback() throws Exception + { + send(1, 0); + + _psession.commit(); + + expect(1, 0); + + sleep(2.0f); + + _csession.rollback(); + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } + + public void testConsumerOpenCommit() throws Exception + { + send(1, 0); + + _psession.commit(); + + sleep(3.0f); + + _csession.commit(); + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } + + public void testConsumerOpenRollback() throws Exception + { + send(1, 0); + + _psession.commit(); + + sleep(3.0f); + + _csession.rollback(); + + assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions()); + + monitor(0, 0); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java new file mode 100644 index 0000000000..2b90d38049 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java @@ -0,0 +1,246 @@ +/* + * + * 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.test.unit.transacted; + +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.jms.DeliveryMode; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.TextMessage; + +import junit.framework.TestCase; + +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.jms.Session; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.util.LogMonitor; + +/** + * The {@link TestCase} for transaction timeout testing. + */ +public abstract class TransactionTimeoutTestCase extends QpidBrokerTestCase implements ExceptionListener +{ + public static final String VIRTUALHOST = "test"; + public static final String TEXT = "0123456789abcdefghiforgettherest"; + public static final String CHN_OPEN_TXN = "CHN-1007"; + public static final String CHN_IDLE_TXN = "CHN-1008"; + public static final String IDLE = "Idle"; + public static final String OPEN = "Open"; + + protected LogMonitor _monitor; + protected AMQConnection _con; + protected Session _psession, _csession; + protected Queue _queue; + protected MessageConsumer _consumer; + protected MessageProducer _producer; + private CountDownLatch _exceptionLatch = new CountDownLatch(1); + protected AtomicInteger _exceptionCount = new AtomicInteger(0); + protected String _message; + protected Exception _exception; + protected AMQConstant _code; + + /** + * Subclasses must implement this to configure transaction timeout parameters. + */ + protected abstract void configure() throws Exception; + + protected void setUp() throws Exception + { + // Configure timeouts + configure(); + + // Monitor log file + _monitor = new LogMonitor(_outputFile); + + // Start broker + super.setUp(); + + // Connect to broker + String broker = ("tcp://localhost:" + DEFAULT_PORT); + ConnectionURL url = new AMQConnectionURL("amqp://guest:guest@clientid/test?brokerlist='" + broker + "'&maxprefetch='1'"); + _con = (AMQConnection) getConnection(url); + _con.setExceptionListener(this); + _con.start(); + + // Create queue + Session qsession = _con.createSession(true, Session.SESSION_TRANSACTED); + AMQShortString queueName = new AMQShortString("test"); + _queue = new AMQQueue(qsession.getDefaultQueueExchangeName(), queueName, queueName, false, true); + qsession.close(); + + // Create producer and consumer + producer(); + consumer(); + } + + protected void tearDown() throws Exception + { + try + { + _con.close(); + } + finally + { + super.tearDown(); + } + } + + /** + * Create a transacted persistent message producer session. + */ + protected void producer() throws Exception + { + _psession = _con.createSession(true, Session.SESSION_TRANSACTED); + _producer = _psession.createProducer(_queue); + _producer.setDeliveryMode(DeliveryMode.PERSISTENT); + } + + /** + * Create a transacted message consumer session. + */ + protected void consumer() throws Exception + { + _csession = _con.createSession(true, Session.SESSION_TRANSACTED); + _consumer = _csession.createConsumer(_queue); + } + + /** + * Send a number of messages to the queue, optionally pausing after each. + */ + protected void send(int count, float delay) throws Exception + { + for (int i = 0; i < count; i++) + { + sleep(delay); + Message msg = _psession.createTextMessage(TEXT); + msg.setIntProperty("i", i); + _producer.send(msg); + } + } + + /** + * Sleep for a number of seconds. + */ + protected void sleep(float seconds) throws Exception + { + try + { + Thread.sleep((long) (seconds * 1000.0f)); + } + catch (InterruptedException ie) + { + throw new RuntimeException("Interrupted"); + } + } + + /** + * Check for idle and open messages. + * + * Either exactly zero messages, or +-2 error accepted around the specified number. + */ + protected void monitor(int idle, int open) throws Exception + { + List<String> idleMsgs = _monitor.findMatches(CHN_IDLE_TXN); + List<String> openMsgs = _monitor.findMatches(CHN_OPEN_TXN); + + String idleErr = "Expected " + idle + " but found " + idleMsgs.size() + " txn idle messages"; + String openErr = "Expected " + open + " but found " + openMsgs.size() + " txn open messages"; + + if (idle == 0) + { + assertTrue(idleErr, idleMsgs.isEmpty()); + } + else + { + assertTrue(idleErr, idleMsgs.size() >= idle - 2 && idleMsgs.size() <= idle + 2); + } + + if (open == 0) + { + assertTrue(openErr, openMsgs.isEmpty()); + } + else + { + assertTrue(openErr, openMsgs.size() >= open - 2 && openMsgs.size() <= open + 2); + } + } + + /** + * Receive a number of messages, optionally pausing after each. + */ + protected void expect(int count, float delay) throws Exception + { + for (int i = 0; i < count; i++) + { + sleep(delay); + Message msg = _consumer.receive(1000); + assertNotNull("Message should not be null", msg); + assertTrue("Message should be a text message", msg instanceof TextMessage); + assertEquals("Message content does not match expected", TEXT, ((TextMessage) msg).getText()); + assertEquals("Message order is incorrect", i, msg.getIntProperty("i")); + } + } + + /** + * Checks that the correct exception was thrown and was received + * by the listener with a 506 error code. + */ + protected void check(String reason)throws InterruptedException + { + assertTrue("Should have caught exception in listener", _exceptionLatch.await(1, TimeUnit.SECONDS)); + assertNotNull("Should have thrown exception to client", _exception); + assertTrue("Exception message should contain '" + reason + "': " + _message, _message.contains(reason + " transaction timed out")); + assertNotNull("Exception should have an error code", _code); + assertEquals("Error code should be 506", AMQConstant.RESOURCE_ERROR, _code); + } + + /** @see javax.jms.ExceptionListener#onException(javax.jms.JMSException) */ + public void onException(JMSException jmse) + { + _exceptionLatch.countDown(); + _exceptionCount.incrementAndGet(); + + _message = jmse.getLinkedException().getMessage(); + if (jmse.getLinkedException() instanceof AMQException) + { + _code = ((AMQException) jmse.getLinkedException()).getErrorCode(); + } + } + + protected int getNumberOfDeliveredExceptions() + { + return _exceptionCount.get(); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java new file mode 100644 index 0000000000..8345803d56 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java @@ -0,0 +1,26 @@ +/* + * + * 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.test.utils; + +public interface BrokerHolder +{ + void shutdown(); +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java index d3b429e315..10217585c1 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java @@ -34,24 +34,10 @@ public class FailoverBaseCase extends QpidBrokerTestCase { protected static final Logger _logger = LoggerFactory.getLogger(FailoverBaseCase.class); - public static int FAILING_VM_PORT = 2; - public static int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt")); public static final long DEFAULT_FAILOVER_TIME = 10000L; protected int failingPort; - protected int getFailingPort() - { - if (_broker.equals(VM)) - { - return FAILING_VM_PORT; - } - else - { - return FAILING_PORT; - } - } - protected void setUp() throws java.lang.Exception { super.setUp(); @@ -82,6 +68,14 @@ public class FailoverBaseCase extends QpidBrokerTestCase return _connectionFactory; } + @Override + public void stopBroker(int port) throws Exception + { + if (isBrokerPresent(port)) + { + super.stopBroker(port); + } + } public void tearDown() throws Exception { diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java new file mode 100644 index 0000000000..340f00fed8 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java @@ -0,0 +1,50 @@ +/* + * + * 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.test.utils; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.Broker; + +public class InternalBrokerHolder implements BrokerHolder +{ + private static final Logger LOGGER = Logger.getLogger(InternalBrokerHolder.class); + private final Broker _broker; + + public InternalBrokerHolder(final Broker broker) + { + if(broker == null) + { + throw new IllegalArgumentException("Broker must not be null"); + } + + _broker = broker; + } + + public void shutdown() + { + LOGGER.info("Shutting down Broker instance"); + + _broker.shutdown(); + + LOGGER.info("Broker instance shutdown"); + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java index ff80c91fac..1fde6c7c73 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java @@ -21,6 +21,8 @@ package org.apache.qpid.test.utils; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import javax.management.JMException; @@ -31,14 +33,17 @@ import javax.management.ObjectName; import javax.management.MalformedObjectNameException; import javax.management.remote.JMXConnector; +import junit.framework.TestCase; + import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.commands.objects.AllObjects; import org.apache.qpid.management.common.JMXConnnectionFactory; import org.apache.qpid.management.common.mbeans.ManagedBroker; +import org.apache.qpid.management.common.mbeans.ManagedConnection; import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.management.common.mbeans.LoggingManagement; import org.apache.qpid.management.common.mbeans.ConfigurationManagement; import org.apache.qpid.management.common.mbeans.ManagedQueue; +import org.apache.qpid.management.common.mbeans.ServerInformation; import org.apache.qpid.management.common.mbeans.UserManagement; /** @@ -231,10 +236,10 @@ public class JMXTestUtils public ObjectName getVirtualHostManagerObjectName(String vhostName) { // Get the name of the test manager - AllObjects allObject = new AllObjects(_mbsc); - allObject.querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=" + vhostName + ",*"; + String query = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=" + + ObjectName.quote(vhostName) + ",*"; - Set<ObjectName> objectNames = allObject.returnObjects(); + Set<ObjectName> objectNames = queryObjects(query); _test.assertNotNull("Null ObjectName Set returned", objectNames); _test.assertEquals("Incorrect number test vhosts returned", 1, objectNames.size()); @@ -258,14 +263,14 @@ public class JMXTestUtils public ObjectName getQueueObjectName(String virtualHostName, String queue) { // Get the name of the test manager - AllObjects allObject = new AllObjects(_mbsc); - allObject.querystring = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + virtualHostName + ",name=" + queue + ",*"; + String query = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + + ObjectName.quote(virtualHostName) + ",name=" + + ObjectName.quote(queue) + ",*"; - Set<ObjectName> objectNames = allObject.returnObjects(); + Set<ObjectName> objectNames = queryObjects(query); _test.assertNotNull("Null ObjectName Set returned", objectNames); - _test.assertEquals("Incorrect number of queues with name '" + allObject.querystring + - "' returned", 1, objectNames.size()); + _test.assertEquals("Incorrect number of queues with name '" + queue + "' returned", 1, objectNames.size()); // We have verified we have only one value in objectNames so return it ObjectName objectName = objectNames.iterator().next(); @@ -286,10 +291,11 @@ public class JMXTestUtils public ObjectName getExchangeObjectName(String virtualHostName, String exchange) { // Get the name of the test manager - AllObjects allObject = new AllObjects(_mbsc); - allObject.querystring = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + virtualHostName + ",name=" + exchange + ",*"; + String query = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + + ObjectName.quote(virtualHostName) + ",name=" + + ObjectName.quote(exchange) + ",*"; - Set<ObjectName> objectNames = allObject.returnObjects(); + Set<ObjectName> objectNames = queryObjects(query); _test.assertNotNull("Null ObjectName Set returned", objectNames); _test.assertEquals("Incorrect number of exchange with name '" + exchange + "' returned", 1, objectNames.size()); @@ -301,12 +307,9 @@ public class JMXTestUtils } @SuppressWarnings("static-access") - public <T> T getManagedObject(Class<T> managedClass, String queryString) + public <T> T getManagedObject(Class<T> managedClass, String query) { - AllObjects allObject = new AllObjects(_mbsc); - allObject.querystring = queryString; - - Set<ObjectName> objectNames = allObject.returnObjects(); + Set<ObjectName> objectNames = queryObjects(query); _test.assertNotNull("Null ObjectName Set returned", objectNames); _test.assertEquals("More than one " + managedClass + " returned", 1, objectNames.size()); @@ -321,6 +324,16 @@ public class JMXTestUtils return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, managedClass, false); } + public <T> List<T> getManagedObjectList(Class<T> managedClass, Set<ObjectName> objectNames) + { + List<T> objects = new ArrayList<T>(); + for (ObjectName name : objectNames) + { + objects.add(getManagedObject(managedClass, name)); + } + return objects; + } + public ManagedBroker getManagedBroker(String virtualHost) { return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost)); @@ -355,4 +368,68 @@ public class JMXTestUtils ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement"); return getManagedObject(UserManagement.class, objectName); } + + /** + * Retrive {@link ServerInformation} JMX MBean. + */ + public ServerInformation getServerInformation() + { + // Get the name of the test manager + String query = "org.apache.qpid:type=ServerInformation,name=ServerInformation,*"; + + Set<ObjectName> objectNames = queryObjects(query); + + TestCase.assertNotNull("Null ObjectName Set returned", objectNames); + TestCase.assertEquals("Incorrect number of objects returned", 1, objectNames.size()); + + // We have verified we have only one value in objectNames so return it + return getManagedObject(ServerInformation.class, objectNames.iterator().next()); + } + + /** + * Retrive all {@link ManagedConnection} objects. + */ + public List<ManagedConnection> getAllManagedConnections() + { + // Get the name of the test manager + String query = "org.apache.qpid:type=VirtualHost.Connection,VirtualHost=*,name=*"; + + Set<ObjectName> objectNames = queryObjects(query); + + TestCase.assertNotNull("Null ObjectName Set returned", objectNames); + + return getManagedObjectList(ManagedConnection.class, objectNames); + } + + /** + * Retrive all {@link ManagedConnection} objects for a particular virtual host. + */ + public List<ManagedConnection> getManagedConnections(String vhost) + { + // Get the name of the test manager + String query = "org.apache.qpid:type=VirtualHost.Connection,VirtualHost=" + ObjectName.quote(vhost) + ",name=*"; + + Set<ObjectName> objectNames = queryObjects(query); + + TestCase.assertNotNull("Null ObjectName Set returned", objectNames); + + return getManagedObjectList(ManagedConnection.class, objectNames); + } + + /** + * Returns the Set of ObjectNames returned by the broker for the given query, + * or null if there is problem while performing the query. + */ + private Set<ObjectName> queryObjects(String query) + { + try + { + return _mbsc.queryNames(new ObjectName(query), null); + } + catch (Exception e) + { + e.printStackTrace(); + return null; + } + } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index ae38a75e7a..bb44aea659 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -25,6 +25,7 @@ import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.PrintStream; import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -51,22 +52,22 @@ import javax.naming.NamingException; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.management.common.mbeans.ConfigurationManagement; +import org.apache.qpid.server.Broker; +import org.apache.qpid.server.BrokerOptions; +import org.apache.qpid.server.ProtocolExclusion; import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; import org.apache.qpid.server.store.DerbyMessageStore; import org.apache.qpid.url.URLSyntaxException; +import org.apache.qpid.util.FileUtils; import org.apache.qpid.util.LogMonitor; /** @@ -74,7 +75,14 @@ import org.apache.qpid.util.LogMonitor; */ public class QpidBrokerTestCase extends QpidTestCase { - protected final String QpidHome = System.getProperty("QPID_HOME"); + + public enum BrokerType + { + EXTERNAL /** Test case relies on a Broker started independently of the test-suite */, + INTERNAL /** Test case starts an embedded broker within this JVM */, + SPAWNED /** Test case spawns a new broker as a separate process */ + } + protected final static String QpidHome = System.getProperty("QPID_HOME"); protected File _configFile = new File(System.getProperty("broker.config")); protected static final Logger _logger = Logger.getLogger(QpidBrokerTestCase.class); @@ -82,9 +90,7 @@ public class QpidBrokerTestCase extends QpidTestCase protected long RECEIVE_TIMEOUT = 1000l; - private Map<String, String> _propertiesSetForTestOnly = new HashMap<String, String>(); private Map<String, String> _propertiesSetForBroker = new HashMap<String, String>(); - private Map<Logger, Level> _loggerLevelSetForTest = new HashMap<Logger, Level>(); private XMLConfiguration _testConfiguration = new XMLConfiguration(); private XMLConfiguration _testVirtualhosts = new XMLConfiguration(); @@ -106,9 +112,10 @@ public class QpidBrokerTestCase extends QpidTestCase // system properties private static final String BROKER_LANGUAGE = "broker.language"; - private static final String BROKER = "broker"; - private static final String BROKER_CLEAN = "broker.clean"; + private static final String BROKER_TYPE = "broker.type"; + private static final String BROKER_COMMAND = "broker.command"; private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests"; + private static final String BROKER_EXISTING_QPID_WORK = "broker.existing.qpid.work"; private static final String BROKER_VERSION = "broker.version"; protected static final String BROKER_READY = "broker.ready"; private static final String BROKER_STOPPED = "broker.stopped"; @@ -116,29 +123,29 @@ public class QpidBrokerTestCase extends QpidTestCase private static final String BROKER_LOG_INTERLEAVE = "broker.log.interleave"; private static final String BROKER_LOG_PREFIX = "broker.log.prefix"; private static final String BROKER_PERSITENT = "broker.persistent"; + private static final String BROKER_PROTOCOL_EXCLUDES = "broker.protocol.excludes"; + // values protected static final String JAVA = "java"; protected static final String CPP = "cpp"; - protected static final String VM = "vm"; - protected static final String EXTERNAL = "external"; - private static final String VERSION_08 = "0-8"; - private static final String VERSION_010 = "0-10"; protected static final String QPID_HOME = "QPID_HOME"; public static final int DEFAULT_VM_PORT = 1; public static final int DEFAULT_PORT = Integer.getInteger("test.port", ServerConfiguration.DEFAULT_PORT); - public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", ServerConfiguration.DEFAULT_JMXPORT); - public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.sslport", ServerConfiguration.DEFAULT_SSL_PORT); + public static final int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt")); + public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", ServerConfiguration.DEFAULT_JMXPORT_REGISTRYSERVER); + public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", ServerConfiguration.DEFAULT_SSL_PORT); protected String _brokerLanguage = System.getProperty(BROKER_LANGUAGE, JAVA); - protected String _broker = System.getProperty(BROKER, VM); - private String _brokerClean = System.getProperty(BROKER_CLEAN, null); + protected BrokerType _brokerType = BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase()); + protected String _brokerCommand = System.getProperty(BROKER_COMMAND); private Boolean _brokerCleanBetweenTests = Boolean.getBoolean(BROKER_CLEAN_BETWEEN_TESTS); - private String _brokerVersion = System.getProperty(BROKER_VERSION, VERSION_08); - protected String _output = System.getProperty(TEST_OUTPUT); + private final AmqpProtocolVersion _brokerVersion = AmqpProtocolVersion.valueOf(System.getProperty(BROKER_VERSION, "")); + protected String _output = System.getProperty(TEST_OUTPUT, System.getProperty("java.io.tmpdir")); protected Boolean _brokerPersistent = Boolean.getBoolean(BROKER_PERSITENT); + private String _brokerProtocolExcludes = System.getProperty(BROKER_PROTOCOL_EXCLUDES); protected static String _brokerLogPrefix = System.getProperty(BROKER_LOG_PREFIX,"BROKER: "); protected static boolean _interleaveBrokerLog = Boolean.getBoolean(BROKER_LOG_INTERLEAVE); @@ -147,13 +154,11 @@ public class QpidBrokerTestCase extends QpidTestCase protected PrintStream _brokerOutputStream; - protected Map<Integer, Process> _brokers = new HashMap<Integer, Process>(); + protected Map<Integer, BrokerHolder> _brokers = new HashMap<Integer, BrokerHolder>(); protected InitialContext _initialContext; protected AMQConnectionFactory _connectionFactory; - protected String _testName; - // the connections created for a given test protected List<Connection> _connections = new ArrayList<Connection>(); public static final String QUEUE = "queue"; @@ -195,7 +200,6 @@ public class QpidBrokerTestCase extends QpidTestCase public void runBare() throws Throwable { - _testName = getClass().getSimpleName() + "." + getName(); String qname = getClass().getName() + "." + getName(); // Initialize this for each test run @@ -210,8 +214,13 @@ public class QpidBrokerTestCase extends QpidTestCase if (redirected) { _outputFile = new File(String.format("%s/TEST-%s.out", _output, qname)); - out = new PrintStream(_outputFile); + out = new PrintStream(new FileOutputStream(_outputFile), true); err = new PrintStream(String.format("%s/TEST-%s.err", _output, qname)); + + // This is relying on behaviour specific to log4j 1.2.12. If we were to upgrade to 1.2.13 or + // beyond we must change either code (or config) to ensure that ConsoleAppender#setFollow + // is set to true otherwise log4j logging will not respect the following reassignment. + System.setOut(out); System.setErr(err); @@ -226,7 +235,6 @@ public class QpidBrokerTestCase extends QpidTestCase } } - _logger.info("========== start " + _testName + " =========="); try { super.runBare(); @@ -247,19 +255,18 @@ public class QpidBrokerTestCase extends QpidTestCase _logger.error("exception stopping broker", e); } + // reset properties used in the test + revertSystemProperties(); + revertLoggingLevels(); + if(_brokerCleanBetweenTests) { - try - { - cleanBroker(); - } - catch (Exception e) - { - _logger.error("exception cleaning up broker", e); - } + final String qpidWork = System.getProperty("QPID_WORK"); + cleanBrokerWork(qpidWork); + createBrokerWork(qpidWork); } - _logger.info("========== stop " + _testName + " =========="); + _logger.info("========== stop " + getTestName() + " =========="); if (redirected) { @@ -278,11 +285,23 @@ public class QpidBrokerTestCase extends QpidTestCase @Override protected void setUp() throws Exception { + super.setUp(); + if (!_configFile.exists()) { fail("Unable to test without config file:" + _configFile); } + String existingQpidWorkPath = System.getProperty(BROKER_EXISTING_QPID_WORK); + if(existingQpidWorkPath != null && !existingQpidWorkPath.equals("")) + { + + String qpidWork = getQpidWork(_brokerType, getPort()); + File existing = new File(existingQpidWorkPath); + cleanBrokerWork(qpidWork); + FileUtils.copyRecursive(existing, new File(qpidWork)); + } + startBroker(); } @@ -383,13 +402,8 @@ public class QpidBrokerTestCase extends QpidTestCase } } - public void startBroker() throws Exception - { - startBroker(0); - } - /** - * Return the management portin use by the broker on this main port + * Return the management port in use by the broker on this main port * * @param mainPort the broker's main port. * @@ -397,7 +411,7 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected int getManagementPort(int mainPort) { - return mainPort + (DEFAULT_MANAGEMENT_PORT - (_broker.equals(VM) ? DEFAULT_VM_PORT : DEFAULT_PORT)); + return mainPort + (DEFAULT_MANAGEMENT_PORT - DEFAULT_PORT); } /** @@ -412,11 +426,7 @@ public class QpidBrokerTestCase extends QpidTestCase protected int getPort(int port) { - if (_broker.equals(VM)) - { - return port == 0 ? DEFAULT_VM_PORT : port; - } - else if (!_broker.equals(EXTERNAL)) + if (!_brokerType.equals(BrokerType.EXTERNAL)) { return port == 0 ? DEFAULT_PORT : port; } @@ -428,11 +438,19 @@ public class QpidBrokerTestCase extends QpidTestCase protected String getBrokerCommand(int port) throws MalformedURLException { - return _broker + final int sslPort = port-1; + final String protocolExcludesList = getProtocolExcludesList(port, sslPort); + return _brokerCommand .replace("@PORT", "" + port) - .replace("@SSL_PORT", "" + (port - 1)) + .replace("@SSL_PORT", "" + sslPort) .replace("@MPORT", "" + getManagementPort(port)) - .replace("@CONFIG_FILE", _configFile.toString()); + .replace("@CONFIG_FILE", _configFile.toString()) + .replace("@EXCLUDES", protocolExcludesList); + } + + public void startBroker() throws Exception + { + startBroker(0); } public void startBroker(int port) throws Exception @@ -443,55 +461,52 @@ public class QpidBrokerTestCase extends QpidTestCase saveTestConfiguration(); saveTestVirtualhosts(); - Process process = null; - if (_broker.equals(VM)) + if(_brokers.get(port) != null) + { + throw new IllegalStateException("There is already an existing broker running on port " + port); + } + + if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker()) { - setConfigurationProperty("management.jmxport", String.valueOf(getManagementPort(port))); setConfigurationProperty(ServerConfiguration.MGMT_CUSTOM_REGISTRY_SOCKET, String.valueOf(false)); saveTestConfiguration(); - - // create an in_VM broker - final ConfigurationFileApplicationRegistry registry = new ConfigurationFileApplicationRegistry(_configFile); - try - { - ApplicationRegistry.initialise(registry, port); - } - catch (Exception e) - { - _logger.error("Broker initialise failed due to:",e); - try - { - registry.close(); - } - catch (Throwable closeE) - { - closeE.printStackTrace(); - } - throw e; - } - TransportConnection.createVMBroker(port); + + BrokerOptions options = new BrokerOptions(); + options.setConfigFile(_configFile.getAbsolutePath()); + options.addPort(port); + + addExcludedPorts(port, DEFAULT_SSL_PORT, options); + + options.setJmxPortRegistryServer(getManagementPort(port)); + + //Set the log config file, relying on the log4j.configuration system property + //set on the JVM by the JUnit runner task in module.xml. + options.setLogConfigFile(new URL(System.getProperty("log4j.configuration")).getFile()); + + Broker broker = new Broker(); + _logger.info("starting internal broker (same JVM)"); + broker.startup(options); + + _brokers.put(port, new InternalBrokerHolder(broker)); } - else if (!_broker.equals(EXTERNAL)) + else if (!_brokerType.equals(BrokerType.EXTERNAL)) { + // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests + final String qpidWork = getQpidWork(_brokerType, port); String cmd = getBrokerCommand(port); - _logger.info("starting broker: " + cmd); + _logger.info("starting external broker: " + cmd); ProcessBuilder pb = new ProcessBuilder(cmd.split("\\s+")); pb.redirectErrorStream(true); - Map<String, String> env = pb.environment(); - String qpidHome = System.getProperty(QPID_HOME); env.put(QPID_HOME, qpidHome); - //Augment Path with bin directory in QPID_HOME. env.put("PATH", env.get("PATH").concat(File.pathSeparator + qpidHome + "/bin")); //Add the test name to the broker run. // DON'T change PNAME, qpid.stop needs this value. - env.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + _testName + "\""); - // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests - env.put("QPID_WORK", System.getProperty("QPID_WORK")+ "/" + port); - + env.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + getTestName() + "\""); + env.put("QPID_WORK", qpidWork); // Use the environment variable to set amqj.logging.level for the broker // The value used is a 'server' value in the test configuration to @@ -543,7 +558,10 @@ public class QpidBrokerTestCase extends QpidTestCase } } - process = pb.start(); + // cpp broker requires that the work directory is created + createBrokerWork(qpidWork); + + Process process = pb.start();; Piper p = new Piper(process.getInputStream(), _brokerOutputStream, @@ -557,44 +575,106 @@ public class QpidBrokerTestCase extends QpidTestCase _logger.info("broker failed to become ready (" + p.ready + "):" + p.getStopLine()); //Ensure broker has stopped process.destroy(); - cleanBroker(); + cleanBrokerWork(qpidWork); throw new RuntimeException("broker failed to become ready:" + p.getStopLine()); } try { + //test that the broker is still running and hasn't exited unexpectedly int exit = process.exitValue(); _logger.info("broker aborted: " + exit); - cleanBroker(); + cleanBrokerWork(qpidWork); throw new RuntimeException("broker aborted: " + exit); } catch (IllegalThreadStateException e) { - // this is expect if the broker started succesfully + // this is expect if the broker started successfully + } + + _brokers.put(port, new SpawnedBrokerHolder(process)); + } + } + + private void addExcludedPorts(int port, int sslPort, BrokerOptions options) + { + final String protocolExcludesList = getProtocolExcludesList(port, sslPort); + + if (protocolExcludesList.equals("")) + { + return; + } + final String[] toks = protocolExcludesList.split("\\s"); + + if(toks.length % 2 != 0) + { + throw new IllegalArgumentException("Must be an even number of tokens in '" + protocolExcludesList + "'"); + } + for (int i = 0; i < toks.length; i=i+2) + { + String excludeArg = toks[i]; + final int excludedPort = Integer.parseInt(toks[i+1]); + options.addExcludedPort(ProtocolExclusion.lookup(excludeArg), excludedPort); + + _logger.info("Adding protocol exclusion " + excludeArg + " " + excludedPort); + } + } + + protected String getProtocolExcludesList(int port, int sslPort) + { + final String protocolExcludesList = + _brokerProtocolExcludes.replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort); + return protocolExcludesList; + } + + private boolean existingInternalBroker() + { + for(BrokerHolder holder : _brokers.values()) + { + if(holder instanceof InternalBrokerHolder) + { + return true; } } - _brokers.put(port, process); + return false; + } + + private String getQpidWork(BrokerType broker, int port) + { + if (!broker.equals(BrokerType.EXTERNAL)) + { + return System.getProperty("QPID_WORK")+ "/" + port; + } + + return System.getProperty("QPID_WORK"); } public String getTestConfigFile() { - String path = _output == null ? System.getProperty("java.io.tmpdir") : _output; - return path + "/" + getTestQueueName() + "-config.xml"; + return _output + "/" + getTestQueueName() + "-config.xml"; } public String getTestVirtualhostsFile() { - String path = _output == null ? System.getProperty("java.io.tmpdir") : _output; - return path + "/" + getTestQueueName() + "-virtualhosts.xml"; + return _output + "/" + getTestQueueName() + "-virtualhosts.xml"; + } + + private String relativeToQpidHome(String file) + { + return file.replace(System.getProperty(QPID_HOME,"QPID_HOME") + "/",""); } protected void saveTestConfiguration() throws ConfigurationException { - // Specifiy the test config file + // Specify the test config file String testConfig = getTestConfigFile(); - setSystemProperty("test.config", testConfig); + String relative = relativeToQpidHome(testConfig); + + setSystemProperty("test.config", relative); + _logger.info("Set test.config property to: " + relative); + _logger.info("Saving test virtualhosts file at: " + testConfig); // Create the file if configuration does not exist if (_testConfiguration.isEmpty()) @@ -606,9 +686,13 @@ public class QpidBrokerTestCase extends QpidTestCase protected void saveTestVirtualhosts() throws ConfigurationException { - // Specifiy the test virtualhosts file + // Specify the test virtualhosts file String testVirtualhosts = getTestVirtualhostsFile(); - setSystemProperty("test.virtualhosts", testVirtualhosts); + String relative = relativeToQpidHome(testVirtualhosts); + + setSystemProperty("test.virtualhosts", relative); + _logger.info("Set test.virtualhosts property to: " + relative); + _logger.info("Saving test virtualhosts file at: " + testVirtualhosts); // Create the file if configuration does not exist if (_testVirtualhosts.isEmpty()) @@ -618,30 +702,33 @@ public class QpidBrokerTestCase extends QpidTestCase _testVirtualhosts.save(testVirtualhosts); } - public void cleanBroker() + protected void cleanBrokerWork(final String qpidWork) { - if (_brokerClean != null) + if (qpidWork != null) { - _logger.info("clean: " + _brokerClean); + _logger.info("Cleaning broker work dir: " + qpidWork); - try + File file = new File(qpidWork); + if (file.exists()) { - ProcessBuilder pb = new ProcessBuilder(_brokerClean.split("\\s+")); - pb.redirectErrorStream(true); - Process clean = pb.start(); - new Piper(clean.getInputStream(),_brokerOutputStream).start(); - - clean.waitFor(); - - _logger.info("clean exited: " + clean.exitValue()); - } - catch (IOException e) - { - throw new RuntimeException(e); + final boolean success = FileUtils.delete(file, true); + if(!success) + { + throw new RuntimeException("Failed to recursively delete beneath : " + file); + } } - catch (InterruptedException e) + } + } + + protected void createBrokerWork(final String qpidWork) + { + if (qpidWork != null) + { + final File dir = new File(qpidWork); + dir.mkdirs(); + if (!dir.isDirectory()) { - throw new RuntimeException(e); + throw new RuntimeException("Failed to created Qpid work directory : " + qpidWork); } } } @@ -655,21 +742,18 @@ public class QpidBrokerTestCase extends QpidTestCase { port = getPort(port); - _logger.info("stopping broker: " + getBrokerCommand(port)); - Process process = _brokers.remove(port); - if (process != null) - { - process.destroy(); - process.waitFor(); - _logger.info("broker exited: " + process.exitValue()); - } - else if (_broker.equals(VM)) - { - TransportConnection.killVMBroker(port); - ApplicationRegistry.remove(port); - } + _logger.info("stopping broker on port : " + port); + BrokerHolder broker = _brokers.remove(port); + broker.shutdown(); } + public boolean isBrokerPresent(int port) throws Exception + { + port = getPort(port); + + return _brokers.containsKey(port); + } + /** * Attempt to set the Java Broker to use the BDBMessageStore for persistence * Falling back to the DerbyMessageStore if @@ -811,20 +895,14 @@ public class QpidBrokerTestCase extends QpidTestCase } /** - * Set a System (-D) property for the external Broker of this test. + * Set a System property for the client (and broker if using the same vm) of this test. * * @param property The property to set * @param value the value to set it to. */ protected void setTestClientSystemProperty(String property, String value) { - if (!_propertiesSetForTestOnly.containsKey(property)) - { - // Record the current value so we can revert it later. - _propertiesSetForTestOnly.put(property, System.getProperty(property)); - } - - System.setProperty(property, value); + setTestSystemProperty(property, value); } /** @@ -832,20 +910,7 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected void revertSystemProperties() { - for (String key : _propertiesSetForTestOnly.keySet()) - { - String value = _propertiesSetForTestOnly.get(key); - if (value != null) - { - System.setProperty(key, value); - } - else - { - System.clearProperty(key); - } - } - - _propertiesSetForTestOnly.clear(); + revertTestSystemProperties(); // We don't change the current VMs settings for Broker only properties // so we can just clear this map @@ -853,7 +918,7 @@ public class QpidBrokerTestCase extends QpidTestCase } /** - * Add an environtmen variable for the external broker environment + * Add an environment variable for the external broker environment * * @param property the property to set * @param value the value to set it to @@ -864,57 +929,23 @@ public class QpidBrokerTestCase extends QpidTestCase } /** - * Adjust the VMs Log4j Settings just for this test run - * - * @param logger the logger to change - * @param level the level to set - */ - protected void setLoggerLevel(Logger logger, Level level) - { - assertNotNull("Cannot set level of null logger", logger); - assertNotNull("Cannot set Logger("+logger.getName()+") to null level.",level); - - if (!_loggerLevelSetForTest.containsKey(logger)) - { - // Record the current value so we can revert it later. - _loggerLevelSetForTest.put(logger, logger.getLevel()); - } - - logger.setLevel(level); - } - - /** - * Restore the logging levels defined by this test. - */ - protected void revertLoggingLevels() - { - for (Logger logger : _loggerLevelSetForTest.keySet()) - { - logger.setLevel(_loggerLevelSetForTest.get(logger)); - } - - _loggerLevelSetForTest.clear(); - - } - - /** * Check whether the broker is an 0.8 * * @return true if the broker is an 0_8 version, false otherwise. */ public boolean isBroker08() { - return _brokerVersion.equals(VERSION_08); + return _brokerVersion.equals(AmqpProtocolVersion.v0_8); } public boolean isBroker010() { - return _brokerVersion.equals(VERSION_010); + return _brokerVersion.equals(AmqpProtocolVersion.v0_10); } protected boolean isJavaBroker() { - return _brokerLanguage.equals("java") || _broker.equals("vm"); + return _brokerLanguage.equals("java") || _brokerType.equals("vm"); } protected boolean isCppBroker() @@ -924,9 +955,14 @@ public class QpidBrokerTestCase extends QpidTestCase protected boolean isExternalBroker() { - return !_broker.equals("vm"); + return !_brokerType.equals("vm"); //TODO } - + + protected boolean isInternalBroker() + { + return _brokerType.equals(BrokerType.INTERNAL); + } + protected boolean isBrokerStorePersistent() { return _brokerPersistent; @@ -966,9 +1002,9 @@ public class QpidBrokerTestCase extends QpidTestCase * Get the default connection factory for the currently used broker * Default factory is "local" * - * @return A conection factory + * @return A connection factory * - * @throws Exception if there is an error getting the tactory + * @throws Exception if there is an error getting the factory */ public AMQConnectionFactory getConnectionFactory() throws NamingException { @@ -992,20 +1028,15 @@ public class QpidBrokerTestCase extends QpidTestCase * * @param factoryName The factory name * - * @return A conection factory + * @return A connection factory * * @throws Exception if there is an error getting the tactory */ public AMQConnectionFactory getConnectionFactory(String factoryName) throws NamingException { - if (_broker.equals(VM)) - { - factoryName += ".vm"; - } - return (AMQConnectionFactory) getInitialContext().lookup(factoryName); } - + public Connection getConnection() throws JMSException, NamingException { return getConnection("guest", "guest"); @@ -1035,7 +1066,7 @@ public class QpidBrokerTestCase extends QpidTestCase { _logger.info("get connection"); Connection con = getConnectionFactory().createConnection(username, password); - //add the connection in the lis of connections + //add the connection in the list of connections _connections.add(con); return con; } @@ -1043,16 +1074,8 @@ public class QpidBrokerTestCase extends QpidTestCase public Connection getClientConnection(String username, String password, String id) throws JMSException, URLSyntaxException, AMQException, NamingException { _logger.info("get Connection"); - Connection con; - if (_broker.equals(VM)) - { - con = new AMQConnection("vm://:1", username, password, id, "test"); - } - else - { - con = getConnectionFactory().createConnection(username, password, id); - } - //add the connection in the lis of connections + Connection con = getConnectionFactory().createConnection(username, password, id); + //add the connection in the list of connections _connections.add(con); return con; } @@ -1081,18 +1104,12 @@ public class QpidBrokerTestCase extends QpidTestCase protected void tearDown() throws java.lang.Exception { - try + super.tearDown(); + + // close all the connections used by this test. + for (Connection c : _connections) { - // close all the connections used by this test. - for (Connection c : _connections) - { - c.close(); - } - } - finally{ - // Ensure any problems with close does not interfer with property resets - revertSystemProperties(); - revertLoggingLevels(); + c.close(); } } @@ -1149,7 +1166,7 @@ public class QpidBrokerTestCase extends QpidTestCase /** * Send messages to the given destination. * - * If session is transacted then messages will be commited before returning + * If session is transacted then messages will be committed before returning * * @param session the session to use for sending * @param destination where to send them to @@ -1157,7 +1174,7 @@ public class QpidBrokerTestCase extends QpidTestCase * * @param batchSize the batchSize in which to commit, 0 means no batching, * but a single commit at the end - * @return the sent messgse + * @return the sent message * * @throws Exception */ @@ -1170,7 +1187,7 @@ public class QpidBrokerTestCase extends QpidTestCase /** * Send messages to the given destination. * - * If session is transacted then messages will be commited before returning + * If session is transacted then messages will be committed before returning * * @param session the session to use for sending * @param destination where to send them to @@ -1179,7 +1196,7 @@ public class QpidBrokerTestCase extends QpidTestCase * @param offset offset allows the INDEX value of the message to be adjusted. * @param batchSize the batchSize in which to commit, 0 means no batching, * but a single commit at the end - * @return the sent messgse + * @return the sent message * * @throws Exception */ @@ -1190,7 +1207,8 @@ public class QpidBrokerTestCase extends QpidTestCase MessageProducer producer = session.createProducer(destination); - for (int i = offset; i < (count + offset); i++) + int i = offset; + for (; i < (count + offset); i++) { Message next = createNextMessage(session, i); @@ -1213,7 +1231,7 @@ public class QpidBrokerTestCase extends QpidTestCase // we have no batchSize or // our count is not divible by batchSize. if (session.getTransacted() && - ( batchSize == 0 || count % batchSize != 0)) + ( batchSize == 0 || (i-1) % batchSize != 0)) { session.commit(); } @@ -1308,29 +1326,26 @@ public class QpidBrokerTestCase extends QpidTestCase */ public void reloadBrokerSecurityConfig() throws Exception { - if (_broker.equals(VM)) + JMXTestUtils jmxu = new JMXTestUtils(this, "admin" , "admin"); + jmxu.open(); + + try { - ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections(); + ConfigurationManagement configMBean = jmxu.getConfigurationManagement(); + configMBean.reloadSecurityConfiguration(); } - else + finally { - JMXTestUtils jmxu = new JMXTestUtils(this, "admin" , "admin"); - jmxu.open(); - - try - { - ConfigurationManagement configMBean = jmxu.getConfigurationManagement(); - configMBean.reloadSecurityConfiguration(); - } - finally - { - jmxu.close(); - } - - LogMonitor _monitor = new LogMonitor(_outputFile); - assertTrue("The expected server security configuration reload did not occur", - _monitor.waitForMessage(ServerConfiguration.SECURITY_CONFIG_RELOADED, LOGMONITOR_TIMEOUT)); - + jmxu.close(); } + + LogMonitor _monitor = new LogMonitor(_outputFile); + assertTrue("The expected server security configuration reload did not occur", + _monitor.waitForMessage(ServerConfiguration.SECURITY_CONFIG_RELOADED, LOGMONITOR_TIMEOUT)); + } + + protected int getFailingPort() + { + return FAILING_PORT; } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java new file mode 100644 index 0000000000..65239bbe02 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java @@ -0,0 +1,58 @@ +/* + * + * 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.test.utils; + +import org.apache.log4j.Logger; + +public class SpawnedBrokerHolder implements BrokerHolder +{ + private static final Logger LOGGER = Logger.getLogger(SpawnedBrokerHolder.class); + + private final Process _process; + + public SpawnedBrokerHolder(final Process process) + { + if(process == null) + { + throw new IllegalArgumentException("Process must not be null"); + } + + _process = process; + } + + public void shutdown() + { + LOGGER.info("Destroying broker process"); + + _process.destroy(); + + try + { + _process.waitFor(); + LOGGER.info("broker exited: " + _process.exitValue()); + } + catch (InterruptedException e) + { + LOGGER.error("Interrupted whilst waiting for process destruction"); + Thread.currentThread().interrupt(); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java b/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java deleted file mode 100644 index f1eb8159b6..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * 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.test.utils.protocol; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import org.apache.mina.common.IoFilterChain; -import org.apache.mina.common.IoHandler; -import org.apache.mina.common.IoService; -import org.apache.mina.common.IoServiceConfig; -import org.apache.mina.common.IoSessionConfig; -import org.apache.mina.common.TransportType; -import org.apache.mina.common.support.BaseIoSession; - -public class TestIoSession extends BaseIoSession { - - private String _stringLocalAddress; - private int _localPort; - - public SocketAddress getLocalAddress() - { - //create a new address for testing purposes using member variables - return new InetSocketAddress(_stringLocalAddress,_localPort); - } - - protected void updateTrafficMask() { - //dummy - } - - public IoService getService() { - return null; - } - - public IoServiceConfig getServiceConfig() { - return null; - } - - public IoHandler getHandler() { - return null; - } - - public IoSessionConfig getConfig() { - return null; - } - - public IoFilterChain getFilterChain() { - return null; - } - - public TransportType getTransportType() { - return null; - } - - public SocketAddress getRemoteAddress() { - return null; - } - - public SocketAddress getServiceAddress() { - return null; - } - - public int getScheduledWriteRequests() { - return 0; - } - - public int getScheduledWriteBytes() { - return 0; - } - - public String getStringLocalAddress() { - return _stringLocalAddress; - } - - public void setStringLocalAddress(String _stringLocalAddress) { - this._stringLocalAddress = _stringLocalAddress; - } - - public int getLocalPort() { - return _localPort; - } - - public void setLocalPort(int _localPort) { - this._localPort = _localPort; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java index a5e2b80f64..c09e63308c 100644 --- a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java +++ b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java @@ -27,11 +27,9 @@ import org.apache.log4j.SimpleLayout; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.ArrayList; +import java.io.LineNumberReader; import java.util.List; import java.util.LinkedList; @@ -45,10 +43,12 @@ import java.util.LinkedList; public class LogMonitor { // The file that the log statements will be written to. - private File _logfile; + private final File _logfile; // The appender we added to the get messages - private FileAppender _appender; + private final FileAppender _appender; + + private int _linesToSkip = 0; /** * Create a new LogMonitor that creates a new Log4j Appender and monitors @@ -78,6 +78,7 @@ public class LogMonitor if (file != null && file.exists()) { _logfile = file; + _appender = null; } else { @@ -99,13 +100,13 @@ public class LogMonitor * @param wait the time in ms to wait for the message to occur * @return true if the message was found * - * @throws java.io.FileNotFoundException if the Log file can nolonger be found + * @throws java.io.FileNotFoundException if the Log file can no longer be found * @throws IOException thrown when reading the log file */ public List<String> waitAndFindMatches(String message, long wait) throws FileNotFoundException, IOException { - if (waitForMessage(message, wait, true)) + if (waitForMessage(message, wait)) { return findMatches(message); } @@ -116,7 +117,9 @@ public class LogMonitor } /** - * Checks the log for instances of the search string. + * Checks the log for instances of the search string. If the caller + * has previously called {@link #markDiscardPoint()}, lines up until the discard + * point are not considered. * * The pattern parameter can take any valid argument used in String.contains() * @@ -130,66 +133,99 @@ public class LogMonitor */ public List<String> findMatches(String pattern) throws IOException { - return FileUtils.searchFile(_logfile, pattern); + + List<String> results = new LinkedList<String>(); + + LineNumberReader reader = new LineNumberReader(new FileReader(_logfile)); + try + { + while (reader.ready()) + { + String line = reader.readLine(); + if (reader.getLineNumber() > _linesToSkip && line.contains(pattern)) + { + results.add(line); + } + } + } + finally + { + reader.close(); + } + + return results; } /** - * Checks the log file for a given message to appear. + * Checks the log file for a given message to appear. If the caller + * has previously called {@link #markDiscardPoint()}, lines up until the discard + * point are not considered. * * @param message the message to wait for in the log * @param wait the time in ms to wait for the message to occur - * - * @param printFileOnFailure should we print the contents that have been - * read if we fail ot find the message. * @return true if the message was found * - * @throws java.io.FileNotFoundException if the Log file can nolonger be found + * @throws java.io.FileNotFoundException if the Log file can no longer be found * @throws IOException thrown when reading the log file */ - public boolean waitForMessage(String message, long wait, boolean printFileOnFailure) + public boolean waitForMessage(String message, long wait) throws FileNotFoundException, IOException { // Loop through alerts until we're done or wait ms seconds have passed, // just in case the logfile takes a while to flush. - BufferedReader reader = new BufferedReader(new FileReader(_logfile)); - boolean found = false; - long endtime = System.currentTimeMillis() + wait; - ArrayList<String> contents = new ArrayList<String>(); - while (!found && System.currentTimeMillis() < endtime) + LineNumberReader reader = null; + try { - while (reader.ready()) + reader = new LineNumberReader(new FileReader(_logfile)); + + boolean found = false; + long endtime = System.currentTimeMillis() + wait; + while (!found && System.currentTimeMillis() < endtime) { - String line = reader.readLine(); - contents.add(line); - if (line.contains(message)) + boolean ready = true; + while (ready = reader.ready()) { - found = true; + String line = reader.readLine(); + + if (reader.getLineNumber() > _linesToSkip) + { + if (line.contains(message)) + { + found = true; + break; + } + } + } + if (!ready) + { + try + { + Thread.sleep(50); + } + catch (InterruptedException ie) + { + Thread.currentThread().interrupt(); + } } } + return found; + } - if (!found && printFileOnFailure) + finally { - for (String line : contents) + if (reader != null) { - System.out.println(line); + reader.close(); } } - return found; } - - public boolean waitForMessage(String message, long alertLogWaitPeriod) throws FileNotFoundException, IOException - { - return waitForMessage(message, alertLogWaitPeriod, true); - } - - /** * Read the log file in to memory as a String * * @return the current contents of the log file * - * @throws java.io.FileNotFoundException if the Log file can nolonger be found + * @throws java.io.FileNotFoundException if the Log file can no longer be found * @throws IOException thrown when reading the log file */ public String readFile() throws FileNotFoundException, IOException @@ -208,14 +244,37 @@ public class LogMonitor } /** - * Clears the log file and writes: 'Log Monitor Reset' at the start of the file + * Marks the discard point in the log file. * - * @throws java.io.FileNotFoundException if the Log file can nolonger be found + * @throws java.io.FileNotFoundException if the Log file can no longer be found * @throws IOException thrown if there is a problem with the log file */ - public void reset() throws FileNotFoundException, IOException + public void markDiscardPoint() throws FileNotFoundException, IOException + { + _linesToSkip = countLinesInFile(); + } + + private int countLinesInFile() throws IOException { - new FileOutputStream(_logfile).getChannel().truncate(0); + int lineCount = 0; + BufferedReader br = null; + try + { + br = new BufferedReader(new FileReader(_logfile)); + while(br.readLine() != null) + { + lineCount++; + } + + return lineCount; + } + finally + { + if (br != null) + { + br.close(); + } + } } /** diff --git a/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java b/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java index a99abe4b94..89f707fbef 100644 --- a/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java +++ b/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java @@ -155,7 +155,7 @@ public class LogMonitorTest extends TestCase String notLogged = "This text was not logged"; - validateLogDoesNotContainsMessage(_monitor, notLogged); + validateLogDoesNotContainMessage(_monitor, notLogged); } public void testWaitForMessage_Timeout() throws IOException @@ -168,28 +168,27 @@ public class LogMonitorTest extends TestCase // Verify that we can time out waiting for a message assertFalse("Message was logged ", - _monitor.waitForMessage(message, TIME_OUT / 2, false)); + _monitor.waitForMessage(message, TIME_OUT / 2)); // Verify that the message did eventually get logged. assertTrue("Message was never logged.", _monitor.waitForMessage(message, TIME_OUT)); } - public void testReset() throws IOException + public void testDiscardPoint() throws IOException { - String message = getName() + ": Test Message"; - - Logger.getRootLogger().warn(message); - - validateLogContainsMessage(_monitor, message); + String firstMessage = getName() + ": Test Message1"; + Logger.getRootLogger().warn(firstMessage); - String LOG_RESET_TEXT = "Log Monitor Reset"; + validateLogContainsMessage(_monitor, firstMessage); - validateLogDoesNotContainsMessage(_monitor, LOG_RESET_TEXT); + _monitor.markDiscardPoint(); - _monitor.reset(); + validateLogDoesNotContainMessage(_monitor, firstMessage); - assertEquals("", _monitor.readFile()); + String secondMessage = getName() + ": Test Message2"; + Logger.getRootLogger().warn(secondMessage); + validateLogContainsMessage(_monitor, secondMessage); } public void testRead() throws IOException @@ -214,7 +213,7 @@ public class LogMonitorTest extends TestCase * * @throws IOException if a problems occurs */ - protected void validateLogDoesNotContainsMessage(LogMonitor log, String message) + protected void validateLogDoesNotContainMessage(LogMonitor log, String message) throws IOException { List<String> results = log.findMatches(message); |