summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRupert Smith <rupertlssmith@apache.org>2007-07-25 12:17:59 +0000
committerRupert Smith <rupertlssmith@apache.org>2007-07-25 12:17:59 +0000
commit6d6b33149a156052d6d768ec839b60f3afb62c9e (patch)
tree8e9210095a3c9c7498396eaff7d71d7c693df89c
parent0ff9d7687de145a70332b4f517a63dc38be2df4d (diff)
downloadqpid-python-6d6b33149a156052d6d768ec839b60f3afb62c9e.tar.gz
Refactored interop tests into general distributed test framework. Moved framework under systests from integrationtests.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2@559419 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java1
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java14
-rw-r--r--java/etc/coding_standards.xml3
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestCase.java179
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestCase.java259
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java101
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java23
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java29
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java23
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java4
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java11
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java2
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java4
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java10
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java12
-rw-r--r--java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java20
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java27
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java2
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java9
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java)175
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java81
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java)34
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java)42
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java)48
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java)11
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java116
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java129
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java75
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java171
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java137
-rw-r--r--java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java66
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java92
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java104
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java13
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTestManual.java69
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java19
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java74
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java18
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java14
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java12
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java57
-rw-r--r--java/systests/src/main/java/org/apache/qpid/util/ClasspathScanner.java234
-rw-r--r--java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java479
47 files changed, 2202 insertions, 807 deletions
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
index d2680ffcc8..959ca03c80 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.queue;
+
public interface QueueNotificationListener
{
void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
diff --git a/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java b/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
index 61955160be..dc73bce28f 100644
--- a/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
+++ b/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
@@ -483,9 +483,9 @@ public class CommandLineParser
}
/**
- * If a command line has been parsed, calling this method sets all of its parsed options as system properties.
+ * If a command line has been parsed, calling this method sets all of its parsed options into the specified properties.
*/
- public void addCommandLineToSysProperties()
+ public void addCommandLineToProperties(Properties properties)
{
if (parsedProperties != null)
{
@@ -494,7 +494,7 @@ public class CommandLineParser
String name = (String) propKey;
String value = parsedProperties.getProperty(name);
- System.setProperty(name, value);
+ properties.setProperty(name, value);
}
}
}
@@ -606,11 +606,13 @@ public class CommandLineParser
* Extracts all name=value pairs from the command line, sets them all as system properties and also returns
* a map of properties containing them.
*
- * @param args The command line.
+ * @param args The command line.
+ * @param commandLine The command line parser.
+ * @param properties The properties object to inject all parsed properties into (optional may be <tt>null</tt>).
*
* @return A set of properties containing all name=value pairs from the command line.
*/
- public static Properties processCommandLine(String[] args, CommandLineParser commandLine)
+ public static Properties processCommandLine(String[] args, CommandLineParser commandLine, Properties properties)
{
// Capture the command line arguments or display errors and correct usage and then exit.
Properties options = null;
@@ -621,7 +623,7 @@ public class CommandLineParser
// Add all the trailing command line options (name=value pairs) to system properties. They may be picked up
// from there.
- commandLine.addCommandLineToSysProperties();
+ commandLine.addCommandLineToProperties(properties);
}
catch (IllegalArgumentException e)
{
diff --git a/java/etc/coding_standards.xml b/java/etc/coding_standards.xml
index 00b1a9516a..8f8b808884 100644
--- a/java/etc/coding_standards.xml
+++ b/java/etc/coding_standards.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.1//EN" "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
<module name="Checker">
+
<!-- Checks package.html defined for all packages. -->
- <module name="PackageHtml"/>
+ <!-- <module name="PackageHtml"/> -->
<module name="TreeWalker">
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestCase.java
deleted file mode 100644
index ba737dffab..0000000000
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestCase.java
+++ /dev/null
@@ -1,179 +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.interop.coordinator;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.util.ConversationFactory;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.Session;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * FanOutTestCase is a {@link org.apache.qpid.interop.coordinator.InteropTestCase} across one sending client and
- * zero or more receiving clients. Its main purpose is to coordinate the setting up of one test client in the sending
- * role and the remainder in the receiving role.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Accept notification of test case participants.
- * <td> {@link org.apache.qpid.interop.coordinator.InvitingTestDecorator}
- * <tr><td> Accept JMS Connection to carry out the coordination over.
- * <tr><td> Coordinate the test sequence amongst participants. <td> {@link ConversationFactory}
- * <tr><td> Supply test properties
- * </table>
- *
- * @todo Gather all the receivers reports.
- */
-public abstract class FanOutTestCase extends InteropTestCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(FanOutTestCase.class);
-
- /** The test clients in the receiving role. */
- private List<TestClientDetails> receivers = new LinkedList<TestClientDetails>();
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public FanOutTestCase(String name)
- {
- super(name);
- }
-
- /**
- * Adds a receiver to this test.
- *
- * @param receiver The contact details of the sending client in the test.
- */
- public void setReceiver(TestClientDetails receiver)
- {
- receivers.add(receiver);
- }
-
- /**
- * Holds a test coordinating conversation with the test clients. This is the basic implementation of the inner loop
- * of Use Case 5. It consists of assigning the test roles, begining the test and gathering the test reports from the
- * participants.
- *
- * @param testProperties The test case definition.
- *
- * @return The test results from the senders and receivers. The senders report will always be returned first,
- * followed by the receivers reports.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- protected Message[] sequenceTest(Map<String, Object> testProperties) throws JMSException
- {
- log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
-
- // Create a conversation on the sender clients private control rouete.
- Session session = conversationFactory.getSession();
- Destination senderControlTopic = session.createTopic(sender.privateControlKey);
- ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
-
- // Assign the sender role to the sending test client.
- Message assignSender = conversationFactory.getSession().createMessage();
- setPropertiesOnMessage(assignSender, testProperties);
- assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
- assignSender.setStringProperty("ROLE", "SENDER");
- assignSender.setStringProperty("CLIENT_NAME", "Sustained_SENDER");
-
- senderConversation.send(senderControlTopic, assignSender);
-
- // Wait for the sender to confirm its role.
- senderConversation.receive();
-
- // Assign the receivers roles.
- for (TestClientDetails receiver : receivers)
- {
- assignReceiverRole(receiver, testProperties, true);
- }
-
- // Start the test on the sender.
- Message start = session.createMessage();
- start.setStringProperty("CONTROL_TYPE", "START");
-
- senderConversation.send(senderControlTopic, start);
-
- // Wait for the test sender to return its report.
- Message senderReport = senderConversation.receive();
- TestUtils.pause(500);
-
- // Ask the receivers for their reports.
- Message statusRequest = session.createMessage();
- statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
-
- // Gather the reports from all of the receiving clients.
-
- // Return all of the test reports, the senders report first.
- return new Message[] { senderReport };
- }
-
- /**
- * Assigns the receiver role to the specified test client that is to act as a receiver during the test. This method
- * does not always wait for the receiving clients to confirm their role assignments. This is because this method
- * may be called from an 'onMessage' method, when a client is joining the test at a later point in time, and it
- * is not possible to do a synchronous receive during an 'onMessage' method. There is a flag to indicate whether
- * or not to wait for role confirmations.
- *
- * @param receiver The test client to assign the receiver role to.
- * @param testProperties The test parameters.
- * @param confirm Indicates whether role confirmation should be waited for.
- *
- * @throws JMSException Any JMSExceptions occurring during the conversation are allowed to fall through.
- */
- protected void assignReceiverRole(TestClientDetails receiver, Map<String, Object> testProperties, boolean confirm)
- throws JMSException
- {
- log.info("assignReceiverRole(TestClientDetails receiver = " + receiver + ", Map<String, Object> testProperties = "
- + testProperties + "): called");
-
- // Create a conversation with the receiving test client.
- Session session = conversationFactory.getSession();
- Destination receiverControlTopic = session.createTopic(receiver.privateControlKey);
- ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
-
- // Assign the receiver role to the receiving client.
- Message assignReceiver = session.createMessage();
- setPropertiesOnMessage(assignReceiver, testProperties);
- assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
- assignReceiver.setStringProperty("ROLE", "RECEIVER");
- assignReceiver.setStringProperty("CLIENT_NAME", receiver.clientName);
-
- receiverConversation.send(receiverControlTopic, assignReceiver);
-
- // Wait for the role confirmation to come back.
- if (confirm)
- {
- receiverConversation.receive();
- }
- }
-}
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestCase.java
deleted file mode 100644
index f895b781f0..0000000000
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestCase.java
+++ /dev/null
@@ -1,259 +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.interop.coordinator;
-
-import junit.framework.TestCase;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.util.ConversationFactory;
-
-import javax.jms.*;
-
-import java.util.Map;
-
-/**
- * A InteropTestCase is a JUnit test case extension that knows how to coordinate test clients that take part in a
- * test case as defined in the interop testing specification
- * (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification).
- *
- * <p/>The real logic of the test cases built on top of this, is embeded in the comparison of the sender and receiver
- * reports. An example test method might look like:
- *
- * <p/><pre>
- * public void testExample()
- * {
- * Properties testConfig = new Properties();
- * testConfig.add("TEST_CASE", "example");
- * ...
- *
- * Report[] reports = sequenceTest(testConfig);
- *
- * // Compare sender and receiver reports.
- * if (report[0] ... report[1] ...)
- * {
- * Assert.fail("Sender and receiver reports did not match up.");
- * }
- * }
- *
- * </pre>
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Accept notification of test case participants. <td> {@link InvitingTestDecorator}
- * <tr><td> Accpet JMS Connection to carry out the coordination over.
- * <tr><td> Coordinate the test sequence amongst participants. <td> {@link ConversationFactory}
- * <tr><td> Supply test properties
- * </table>
- */
-public abstract class InteropTestCase extends TestCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(InteropTestCase.class);
-
- /** Holds the contact details for the sending test client. */
- protected TestClientDetails sender;
-
- /** Holds the contact details for the receving test client. */
- protected TestClientDetails receiver;
-
- /** Holds the conversation factory over which to coordinate the test. */
- protected ConversationFactory conversationFactory;
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public InteropTestCase(String name)
- {
- super(name);
- }
-
- /**
- * Sets the sender test client to coordinate the test with.
- *
- * @param sender The contact details of the sending client in the test.
- */
- public void setSender(TestClientDetails sender)
- {
- log.debug("public void setSender(TestClientDetails sender = " + sender + "): called");
-
- this.sender = sender;
- }
-
- /**
- * Sets the receiving test client to coordinate the test with.
- *
- * @param receiver The contact details of the sending client in the test.
- */
- public void setReceiver(TestClientDetails receiver)
- {
- log.debug("public void setReceiver(TestClientDetails receiver = " + receiver + "): called");
-
- this.receiver = receiver;
- }
-
- /**
- * Supplies the sending test client.
- *
- * @return The sending test client.
- */
- public TestClientDetails getSender()
- {
- return sender;
- }
-
- /**
- * Supplies the receiving test client.
- *
- * @return The receiving test client.
- */
- public TestClientDetails getReceiver()
- {
- return receiver;
- }
-
- /**
- * Returns the name of the current test method of this test class, with the sending and receiving client names
- * appended on to it, so that the resulting name unqiuely identifies the test and the clients that participated
- * in it.
- *
- * @return The unique test and client name.
- */
- public String getName()
- {
- if ((sender == null) || (receiver == null))
- {
- return super.getName();
- }
- else
- {
- return super.getName() + "_sender_" + sender.clientName + "_receiver_" + receiver.clientName;
- }
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as known to the test
- * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
- * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
- * name "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- *
- * @return The name of the corresponding interop test case.
- */
- public abstract String getTestCaseNameForTestMethod(String methodName);
-
- /**
- * Accepts the conversation factory over which to hold the test coordinating conversation.
- *
- * @param conversationFactory The conversation factory to coordinate the test over.
- */
- public void setConversationFactory(ConversationFactory conversationFactory)
- {
- this.conversationFactory = conversationFactory;
- }
-
- /**
- * Holds a test coordinating conversation with the test clients. This is the basic implementation of the inner
- * loop of Use Case 5. It consists of assigning the test roles, begining the test and gathering the test reports
- * from the participants.
- *
- * @param testProperties The test case definition.
- *
- * @return The test results from the senders and receivers.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- protected Message[] sequenceTest(Map<String, Object> testProperties) throws JMSException
- {
- log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
-
- Session session = conversationFactory.getSession();
- Destination senderControlTopic = session.createTopic(sender.privateControlKey);
- Destination receiverControlTopic = session.createTopic(receiver.privateControlKey);
-
- ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
- ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
-
- // Assign the sender role to the sending test client.
- Message assignSender = conversationFactory.getSession().createMessage();
- setPropertiesOnMessage(assignSender, testProperties);
- assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
- assignSender.setStringProperty("ROLE", "SENDER");
-
- senderConversation.send(senderControlTopic, assignSender);
-
- // Assign the receiver role the receiving client.
- Message assignReceiver = session.createMessage();
- setPropertiesOnMessage(assignReceiver, testProperties);
- assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
- assignReceiver.setStringProperty("ROLE", "RECEIVER");
-
- receiverConversation.send(receiverControlTopic, assignReceiver);
-
- // Wait for the senders and receivers to confirm their roles.
- senderConversation.receive();
- receiverConversation.receive();
-
- // Start the test.
- Message start = session.createMessage();
- start.setStringProperty("CONTROL_TYPE", "START");
-
- senderConversation.send(senderControlTopic, start);
-
- // Wait for the test sender to return its report.
- Message senderReport = senderConversation.receive();
- TestUtils.pause(500);
-
- // Ask the receiver for its report.
- Message statusRequest = session.createMessage();
- statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
-
- receiverConversation.send(receiverControlTopic, statusRequest);
-
- // Wait for the receiver to send its report.
- Message receiverReport = receiverConversation.receive();
-
- return new Message[] { senderReport, receiverReport };
- }
-
- /**
- * Sets properties of different types on a JMS Message.
- *
- * @param message The message to set properties on.
- * @param properties The property name/value pairs to set.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- public void setPropertiesOnMessage(Message message, Map<String, Object> properties) throws JMSException
- {
- for (Map.Entry<String, Object> entry : properties.entrySet())
- {
- String name = entry.getKey();
- Object value = entry.getValue();
-
- message.setObjectProperty(name, value);
- }
- }
-}
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java
new file mode 100644
index 0000000000..81a3e891fd
--- /dev/null
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java
@@ -0,0 +1,101 @@
+/*
+ *
+ * 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.interop.coordinator.testcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+/**
+ * CircuitTestCase runs a test over a {@link Circuit} controlled by the test parameters.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ *
+ * @todo When working with test context properties, add overrides to defaults to the singleton instance, but when taking
+ * a starting point to add specific test case parameters to, take a copy. Use the copy with test case specifics
+ * to control the test.
+ */
+public class CircuitTestCase extends FrameworkBaseCase
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(CircuitTestCase.class);
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public CircuitTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the a basic P2P test case.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testBasicP2P() throws Exception
+ {
+ log.debug("public void testBasicP2P(): called");
+
+ // Get the test parameters, any overrides on the command line will have been applied.
+ ParsedProperties testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ // Customize the test parameters.
+ testProps.setProperty("TEST_NAME", "DEFAULT_CIRCUIT_TEST");
+ testProps.setProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME, "testqueue");
+
+ // Get the test sequencer to create test circuits and run the standard test procedure through.
+ TestCaseSequencer sequencer = getTestSequencer();
+
+ // Send the test messages, and check that there were no errors doing so.
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
+
+ // Check that all of the message were sent.
+ // Check that the receiving end got the same number of messages as the publishing end.
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as known to the test
+ * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ * name "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ *
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ return "DEFAULT_CIRCUIT_TEST";
+ }
+}
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java
index b74a55d964..075d5ecad4 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java
@@ -20,28 +20,23 @@
*/
package org.apache.qpid.interop.coordinator.testcases;
-import junit.framework.Assert;
-
import org.apache.log4j.Logger;
-import org.apache.qpid.interop.coordinator.InteropTestCase;
-
-import javax.jms.Message;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
/**
- * Coordinates test case 1, from the interop test specification. This test connects up the sender and receiver roles,
+ * Coordinates test case 1, from the interop test specification. This test connects up the sender and receivers roles,
* and gets some dummy test reports from them, in order to check that the test framework itself is operational.
*
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Exercises the interop testing framework without actually sending any test messages.
- * <td> {@link org.apache.qpid.interop.coordinator.InteropTestCase}
+ * <td> {@link org.apache.qpid.interop.coordinator.DistributedTestCase}
* </table>
*/
-public class InteropTestCase1DummyRun extends InteropTestCase
+public class InteropTestCase1DummyRun extends DistributedTestCase
{
/** Used for debugging. */
private static final Logger log = Logger.getLogger(InteropTestCase1DummyRun.class);
@@ -65,13 +60,13 @@ public class InteropTestCase1DummyRun extends InteropTestCase
{
log.debug("public void testDummyRun(): called");
- Map<String, Object> testConfig = new HashMap<String, Object>();
+ Properties testConfig = new Properties();
testConfig.put("TEST_NAME", "TC1_DummyRun");
- Message[] reports = sequenceTest(testConfig);
+ /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig);
- // Compare sender and receiver reports.
- Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length);
+ // Compare sender and receivers reports.
+ // Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length);
}
/**
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java
index 406b8b42a6..1b75a13712 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java
@@ -20,28 +20,23 @@
*/
package org.apache.qpid.interop.coordinator.testcases;
-import junit.framework.Assert;
-
import org.apache.log4j.Logger;
-import org.apache.qpid.interop.coordinator.InteropTestCase;
-
-import javax.jms.Message;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
/**
* Implements test case 2, from the interop test specification. This test sets up the TC2_BasicP2P test for 50
- * messages. It checks that the sender and receiver reports both indicate that all the test messages were transmitted
+ * messages. It checks that the sender and receivers reports both indicate that all the test messages were transmitted
* successfully.
*
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link InteropTestCase}
+ * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link DistributedTestCase}
* </table>
*/
-public class InteropTestCase2BasicP2P extends InteropTestCase
+public class InteropTestCase2BasicP2P extends DistributedTestCase
{
/** Used for debugging. */
private static final Logger log = Logger.getLogger(InteropTestCase2BasicP2P.class);
@@ -65,19 +60,19 @@ public class InteropTestCase2BasicP2P extends InteropTestCase
{
log.debug("public void testBasicP2P(): called");
- Map<String, Object> testConfig = new HashMap<String, Object>();
- testConfig.put("TEST_NAME", "TC2_BasicP2P");
- testConfig.put("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
+ Properties testConfig = new Properties();
+ testConfig.setProperty("TEST_NAME", "TC2_BasicP2P");
+ testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
testConfig.put("P2P_NUM_MESSAGES", 50);
- Message[] reports = sequenceTest(testConfig);
+ /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig);
- // Compare sender and receiver reports.
- int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+ // Compare sender and receivers reports.
+ /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
- Assert.assertEquals("Sender and receiver messages sent did not match up.", messagesSent, messagesReceived);
+ Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);*/
}
/**
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java
index ebb4cd764e..6d4db4c13c 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java
@@ -20,24 +20,19 @@
*/
package org.apache.qpid.interop.coordinator.testcases;
-import junit.framework.Assert;
-
import org.apache.log4j.Logger;
-import org.apache.qpid.interop.coordinator.InteropTestCase;
-
-import javax.jms.Message;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
/**
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link InteropTestCase}
+ * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link DistributedTestCase}
* </table>
*/
-public class InteropTestCase3BasicPubSub extends InteropTestCase
+public class InteropTestCase3BasicPubSub extends DistributedTestCase
{
/** Used for debugging. */
private static final Logger log = Logger.getLogger(InteropTestCase3BasicPubSub.class);
@@ -61,21 +56,21 @@ public class InteropTestCase3BasicPubSub extends InteropTestCase
{
log.debug("public void testBasicPubSub(): called");
- Map<String, Object> testConfig = new HashMap<String, Object>();
+ Properties testConfig = new Properties();
testConfig.put("TEST_NAME", "TC3_BasicPubSub");
testConfig.put("PUBSUB_KEY", "tc3route");
testConfig.put("PUBSUB_NUM_MESSAGES", 10);
testConfig.put("PUBSUB_NUM_RECEIVERS", 5);
- Message[] reports = sequenceTest(testConfig);
+ /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig);
- // Compare sender and receiver reports.
- int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+ // Compare sender and receivers reports.
+ /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
Assert.assertEquals("The requested number of messages were not sent.", 10, messagesSent);
Assert.assertEquals("Received messages did not match up to num sent * num receivers.", messagesSent * 5,
- messagesReceived);
+ messagesReceived);*/
}
/**
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java
index 87f09faf1e..216efd3aff 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java
@@ -47,7 +47,7 @@ public interface InteropClientTestCase extends MessageListener
/** Specifies the sender role. */
SENDER,
- /** Specifies the receiver role. */
+ /** Specifies the receivers role. */
RECEIVER
}
@@ -74,7 +74,7 @@ public interface InteropClientTestCase extends MessageListener
* Assigns the role to be played by this test case. The test parameters are fully specified in the
* assignment message. When this method return the test case will be ready to execute.
*
- * @param role The role to be played; sender or receiver.
+ * @param role The role to be played; sender or receivers.
* @param assignRoleMessage The role assingment message, contains the full test parameters.
*
* @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java
index baf8bc033d..26b00aa442 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java
@@ -25,6 +25,7 @@ import org.apache.log4j.Logger;
import org.apache.qpid.interop.testclient.testcases.TestCase1DummyRun;
import org.apache.qpid.interop.testclient.testcases.TestCase2BasicP2P;
import org.apache.qpid.interop.testclient.testcases.TestCase3BasicPubSub;
+import org.apache.qpid.sustained.SustainedClientTestCase;
import org.apache.qpid.test.framework.MessagingTestConfigProperties;
import org.apache.qpid.test.framework.TestUtils;
@@ -63,7 +64,10 @@ import java.util.Map;
public class TestClient implements MessageListener
{
/** Used for debugging. */
- private static Logger log = Logger.getLogger(TestClient.class);
+ private static final Logger log = Logger.getLogger(TestClient.class);
+
+ /** Used for reporting to the console. */
+ private static final Logger console = Logger.getLogger("CONSOLE");
/** Holds the default identifying name of the test client. */
public static final String CLIENT_NAME = "java";
@@ -169,7 +173,8 @@ public class TestClient implements MessageListener
Collection<Class<? extends InteropClientTestCase>> testCaseClasses =
new ArrayList<Class<? extends InteropClientTestCase>>();
// ClasspathScanner.getMatches(InteropClientTestCase.class, "^TestCase.*", true);
- Collections.addAll(testCaseClasses, TestCase1DummyRun.class, TestCase2BasicP2P.class, TestCase3BasicPubSub.class);
+ Collections.addAll(testCaseClasses, TestCase1DummyRun.class, TestCase2BasicP2P.class, TestCase3BasicPubSub.class,
+ SustainedClientTestCase.class);
try
{
@@ -285,7 +290,7 @@ public class TestClient implements MessageListener
}
else
{
- log.warn("'" + testName + "' not part of this clients tests.");
+ log.debug("Received an invite to the test '" + testName + "' but this test is not known.");
}
}
else
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java
index 9629e79b2c..a8edeef80e 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java
@@ -80,7 +80,7 @@ public class TestCase1DummyRun implements InteropClientTestCase
* Assigns the role to be played by this test case. The test parameters are fully specified in the
* assignment message. When this method return the test case will be ready to execute.
*
- * @param role The role to be played; sender or receiver.
+ * @param role The role to be played; sender or receivers.
* @param assignRoleMessage The role assingment message, contains the full test parameters.
*
* @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java
index c93d1ab828..823ed51596 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java
@@ -98,7 +98,7 @@ public class TestCase2BasicP2P implements InteropClientTestCase
* Assigns the role to be played by this test case. The test parameters are fully specified in the
* assignment message. When this method return the test case will be ready to execute.
*
- * @param role The role to be played; sender or receiver.
+ * @param role The role to be played; sender or receivers.
*
* @param assignRoleMessage The role assingment message, contains the full test parameters.
*
@@ -134,7 +134,7 @@ public class TestCase2BasicP2P implements InteropClientTestCase
producer = session.createProducer(sendDestination);
break;
- // Otherwise the receiver role is being assigned, so set this up to listen for messages.
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages.
case RECEIVER:
MessageConsumer consumer = session.createConsumer(sendDestination);
consumer.setMessageListener(this);
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java
index 57e8634006..4cdb07c546 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java
@@ -30,7 +30,7 @@ import javax.jms.*;
/**
* Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
- * default topic exchange, using the specified number of receiver connections. Produces reports on the actual number of
+ * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
* messages sent/received.
*
* <p><table id="crc"><caption>CRC Card</caption>
@@ -99,7 +99,7 @@ public class TestCase3BasicPubSub implements InteropClientTestCase
* Assigns the role to be played by this test case. The test parameters are fully specified in the
* assignment message. When this method return the test case will be ready to execute.
*
- * @param role The role to be played; sender or receiver.
+ * @param role The role to be played; sender or receivers.
*
* @param assignRoleMessage The role assingment message, contains the full test parameters.
*
@@ -143,10 +143,10 @@ public class TestCase3BasicPubSub implements InteropClientTestCase
producer = session[0].createProducer(sendDestination);
break;
- // Otherwise the receiver role is being assigned, so set this up to listen for messages on the required number
- // of receiver connections.
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
+ // of receivers connections.
case RECEIVER:
- // Create the required number of receiver connections.
+ // Create the required number of receivers connections.
connection = new Connection[numReceivers];
session = new Session[numReceivers];
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
index 71ab38ec0a..edc6fdba1e 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
@@ -46,7 +46,7 @@ import java.util.concurrent.CountDownLatch;
/**
* Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
- * default topic exchange, using the specified number of receiver connections. Produces reports on the actual number of
+ * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
* messages sent/received.
*
* <p><table id="crc"><caption>CRC Card</caption>
@@ -68,7 +68,7 @@ public class SustainedClientTestCase extends TestCase3BasicPubSub implements Exc
/** The role to be played by the test. */
private Roles role;
- /** The number of receiver connection to use. */
+ /** The number of receivers connection to use. */
private int numReceivers;
/** The routing key to send them to on the default direct exchange. */
@@ -114,7 +114,7 @@ public class SustainedClientTestCase extends TestCase3BasicPubSub implements Exc
* Assigns the role to be played by this test case. The test parameters are fully specified in the assignment
* message. When this method return the test case will be ready to execute.
*
- * @param role The role to be played; sender or receiver.
+ * @param role The role to be played; sender or receivers.
* @param assignRoleMessage The role assingment message, contains the full test parameters.
*
* @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
@@ -172,11 +172,11 @@ public class SustainedClientTestCase extends TestCase3BasicPubSub implements Exc
break;
- // Otherwise the receiver role is being assigned, so set this up to listen for messages on the required number
- // of receiver connections.
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
+ // of receivers connections.
case RECEIVER:
console.info("Creating Receiver");
- // Create the required number of receiver connections.
+ // Create the required number of receivers connections.
connection = new Connection[numReceivers];
session = new Session[numReceivers];
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
index 3dd1326d80..84852078f0 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
+++ b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
@@ -23,18 +23,17 @@ package org.apache.qpid.sustained;
import org.apache.log4j.Logger;
import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
import org.apache.qpid.interop.coordinator.DropInTest;
import org.apache.qpid.interop.coordinator.TestClientDetails;
-import org.apache.qpid.interop.coordinator.FanOutTestCase;
import javax.jms.JMSException;
import javax.jms.Message;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
/**
- * SustainedTestCase is a {@link FanOutTestCase} that runs the "Perf_SustainedPubSub" test case. This consists of one
+ * SustainedTestCase is a {@link org.apache.qpid.interop.coordinator.DistributedTestCase} that runs the "Perf_SustainedPubSub" test case. This consists of one
* test client sending, and several receiving, and attempts to find the highest rate at which messages can be broadcast
* to the receivers. It is also a {@link DropInTest} to which more test clients may be added during a test run.
*
@@ -43,7 +42,7 @@ import java.util.Map;
* <tr><td>
* </table>
*/
-public class SustainedTestCase extends FanOutTestCase implements DropInTest
+public class SustainedTestCase extends DistributedTestCase implements DropInTest
{
/** Used for debugging. */
Logger log = Logger.getLogger(SustainedTestCase.class);
@@ -70,7 +69,7 @@ public class SustainedTestCase extends FanOutTestCase implements DropInTest
{
log.debug("public void testSinglePubSubCycle(): called");
- Map<String, Object> testConfig = new HashMap<String, Object>();
+ Properties testConfig = new Properties();
testConfig.put("TEST_NAME", "Perf_SustainedPubSub");
testConfig.put("SUSTAINED_KEY", SUSTAINED_KEY);
testConfig.put("SUSTAINED_NUM_RECEIVERS", Integer.getInteger("numReceives", 2));
@@ -80,7 +79,7 @@ public class SustainedTestCase extends FanOutTestCase implements DropInTest
log.info("Created Config: " + testConfig.entrySet().toArray());
- sequenceTest(testConfig);
+ getTestSequencer().sequenceTest(null, null, testConfig);
}
/**
@@ -98,14 +97,17 @@ public class SustainedTestCase extends FanOutTestCase implements DropInTest
*/
public void lateJoin(Message message) throws JMSException
{
+ throw new RuntimeException("Not implemented.");
+ /*
// Extract the joining clients details from its join request message.
TestClientDetails clientDetails = new TestClientDetails();
clientDetails.clientName = message.getStringProperty("CLIENT_NAME");
clientDetails.privateControlKey = message.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY");
- // Register the joining client, but do block for confirmation as cannot do a synchronous receiver during this
+ // Register the joining client, but do block for confirmation as cannot do a synchronous receivers during this
// method call, as it may have been called from an 'onMessage' method.
- assignReceiverRole(clientDetails, new HashMap<String, Object>(), false);
+ assignReceiverRole(clientDetails, new Properties(), false);
+ */
}
/**
diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
index 2765986868..c5f71b4774 100644
--- a/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
+++ b/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
@@ -20,18 +20,6 @@
*/
package org.apache.qpid.ping;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-
import org.apache.log4j.Logger;
import org.apache.qpid.requestreply.PingPongProducer;
@@ -40,6 +28,18 @@ import org.apache.qpid.util.CommandLineParser;
import uk.co.thebadgerset.junit.extensions.util.MathUtils;
import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* PingDurableClient is a variation of the {@link PingPongProducer} ping tool. Instead of sending its pings and
* receiving replies to them at the same time, this tool sends pings until it is signalled by some 'event' to stop
@@ -167,7 +167,8 @@ public class PingDurableClient extends PingPongProducer implements ExceptionList
try
{
// Create a ping producer overriding its defaults with all options passed on the command line.
- Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}));
+ Properties options =
+ CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
PingDurableClient pingProducer = new PingDurableClient(options);
// Create a shutdown hook to terminate the ping-pong producer.
diff --git a/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java b/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
index bbe337ca0a..2879f0c322 100644
--- a/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
+++ b/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
@@ -57,7 +57,7 @@ public class PingSendOnlyClient extends PingDurableClient
try
{
// Create a ping producer overriding its defaults with all options passed on the command line.
- Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}));
+ Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
PingSendOnlyClient pingProducer = new PingSendOnlyClient(options);
// Create a shutdown hook to terminate the ping-pong producer.
diff --git a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
index 5d3df1d9ec..03f5f0549d 100644
--- a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
+++ b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
@@ -44,9 +44,7 @@ import java.net.InetAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
-import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -89,7 +87,7 @@ import java.util.concurrent.atomic.AtomicLong;
* <tr><td> destinationCount <td> 1 <td> The number of receivers listening to the pings.
* <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
* <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
- * <tr><td> uniqueDests <td> true <td> Whether each receiver only listens to one ping destination or all.
+ * <tr><td> uniqueDests <td> true <td> Whether each receivers only listens to one ping destination or all.
* <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
* <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
* 0 - SESSION_TRANSACTED
@@ -373,7 +371,7 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
protected int _maxPendingSize;
/**
- * Holds a monitor which is used to synchronize sender and receiver threads, where the sender has elected
+ * Holds a monitor which is used to synchronize sender and receivers threads, where the sender has elected
* to wait until the number of unreceived message is reduced before continuing to send.
*/
protected Object _sendPauseMonitor = new Object();
@@ -570,7 +568,8 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
{
try
{
- Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}));
+ Properties options =
+ CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
// Create a ping producer overriding its defaults with all options passed on the command line.
PingPongProducer pingProducer = new PingPongProducer(options);
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java
index 6cc2740596..28d8ce79a0 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java
@@ -26,9 +26,6 @@ import junit.framework.TestSuite;
import org.apache.log4j.Logger;
-import org.apache.qpid.interop.coordinator.testcases.InteropTestCase1DummyRun;
-import org.apache.qpid.interop.coordinator.testcases.InteropTestCase2BasicP2P;
-import org.apache.qpid.interop.coordinator.testcases.InteropTestCase3BasicPubSub;
import org.apache.qpid.test.framework.MessagingTestConfigProperties;
import org.apache.qpid.test.framework.TestUtils;
import org.apache.qpid.util.ConversationFactory;
@@ -55,12 +52,12 @@ import java.util.concurrent.LinkedBlockingQueue;
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Find out what test clients are available. <td> {@link ConversationFactory}
- * <tr><td> Decorate available tests to run all available clients. <td> {@link InvitingTestDecorator}
+ * <tr><td> Decorate available tests to run all available clients. <td> {@link DistributedTestDecorator}
* <tr><td> Attach XML test result logger.
* <tr><td> Terminate the interop testing framework.
* </table>
*
- * @todo Shoud accumulate failures over all tests, and return with success or fail code based on all results. May need
+ * @todo Should accumulate failures over all tests, and return with success or fail code based on all results. May need
* to write a special TestResult to do this properly. At the moment only the last one used will be tested for
* errors, as the start method creates a fresh one for each test case run.
*
@@ -71,6 +68,9 @@ public class Coordinator extends TKTestRunner
/** Used for debugging. */
private static final Logger log = Logger.getLogger(Coordinator.class);
+ /** Used for reporting to the console. */
+ private static final Logger console = Logger.getLogger("CONSOLE");
+
/** Defines the possible distributed test engines available to run coordinated test cases with. */
public enum TestEngine
{
@@ -115,6 +115,9 @@ public class Coordinator extends TKTestRunner
/** Holds the coordinating test engine type to run the tests through. */
protected TestEngine engine;
+ /** Flag that indicates that all test clients should be terminated upon completion of the test cases. */
+ protected boolean terminate;
+
/**
* Creates an interop test coordinator on the specified broker and virtual host.
*
@@ -123,7 +126,7 @@ public class Coordinator extends TKTestRunner
* @param reportDir The directory to write out test results to.
* @param engine The distributed test engine type to run the tests with.
*/
- public Coordinator(String brokerUrl, String virtualHost, String reportDir, TestEngine engine)
+ public Coordinator(String brokerUrl, String virtualHost, String reportDir, TestEngine engine, boolean terminate)
{
log.debug("Coordinator(String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost + "): called");
@@ -132,6 +135,7 @@ public class Coordinator extends TKTestRunner
this.virtualHost = virtualHost;
this.reportDir = reportDir;
this.engine = engine;
+ this.terminate = terminate;
}
/**
@@ -152,65 +156,100 @@ public class Coordinator extends TKTestRunner
*/
public static void main(String[] args)
{
+ console.info("Qpid Distributed Test Coordinator.");
+
// Override the default broker url to be localhost:5672.
testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672");
- // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
- // and usage then exist if there are errors).
- // Any options and trailing name=value pairs are also injected into the test context properties object,
- // to override any defaults that may have been set up.
- Properties options =
- CommandLineParser.processCommandLine(args,
- new CommandLineParser(
- new String[][]
- {
- { "b", "The broker URL.", "broker", "false" },
- { "h", "The virtual host to use.", "virtual host", "false" },
- { "o", "The name of the directory to output test timings to.", "dir", "false" },
- {
- "e", "The test execution engine to use. Default is interop.", "engine", "interop",
- "^interop$|^fanout$", "true"
- }
- }), testContextProperties);
-
- // Extract the command line options.
- String brokerUrl = options.getProperty("b");
- String virtualHost = options.getProperty("h");
- String reportDir = options.getProperty("o");
- String testEngine = options.getProperty("e");
- TestEngine engine = "fanout".equals(testEngine) ? TestEngine.FANOUT : TestEngine.INTEROP;
- reportDir = (reportDir == null) ? "." : reportDir;
-
- // If broker or virtual host settings were specified as command line options, override the defaults in the
- // test context properties with them.
-
- // Scan for available test cases using a classpath scanner.
- // Hard code the test classes till the classpath scanner is fixed.
- Collection<Class<? extends InteropTestCase>> testCaseClasses = new ArrayList<Class<? extends InteropTestCase>>();
- // ClasspathScanner.getMatches(InteropTestCase.class, "^Test.*", true);
- Collections.addAll(testCaseClasses, InteropTestCase1DummyRun.class, InteropTestCase2BasicP2P.class,
- InteropTestCase3BasicPubSub.class);
-
- // Check that some test classes were actually found.
- if (testCaseClasses.isEmpty())
+ try
{
- throw new RuntimeException("No test classes implementing InteropTestCase were found on the class path.");
- }
+ // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
+ // and usage then exist if there are errors).
+ // Any options and trailing name=value pairs are also injected into the test context properties object,
+ // to override any defaults that may have been set up.
+ ParsedProperties options =
+ new ParsedProperties(CommandLineParser.processCommandLine(args,
+ new CommandLineParser(
+ new String[][]
+ {
+ { "b", "The broker URL.", "broker", "false" },
+ { "h", "The virtual host to use.", "virtual host", "false" },
+ { "o", "The name of the directory to output test timings to.", "dir", "false" },
+ {
+ "e", "The test execution engine to use. Default is interop.", "engine", "interop",
+ "^interop$|^fanout$", "true"
+ },
+ { "t", "Terminate test clients on completion of tests.", "flag", "false" }
+ }), testContextProperties));
+
+ // Extract the command line options.
+ String brokerUrl = options.getProperty("b");
+ String virtualHost = options.getProperty("h");
+ String reportDir = options.getProperty("o");
+ reportDir = (reportDir == null) ? "." : reportDir;
+ String testEngine = options.getProperty("e");
+ TestEngine engine = "fanout".equals(testEngine) ? TestEngine.FANOUT : TestEngine.INTEROP;
+ boolean terminate = options.getPropertyAsBoolean("t");
+
+ // If broker or virtual host settings were specified as command line options, override the defaults in the
+ // test context properties with them.
+
+ // Collection all of the test cases to be run.
+ Collection<Class<? extends DistributedTestCase>> testCaseClasses =
+ new ArrayList<Class<? extends DistributedTestCase>>();
+
+ // Scan for available test cases using a classpath scanner.
+ // ClasspathScanner.getMatches(InteropTestCase.class, "^Test.*", true);
+
+ // Hard code the test classes till the classpath scanner is fixed.
+ // Collections.addAll(testCaseClasses, InteropTestCase1DummyRun.class, InteropTestCase2BasicP2P.class,
+ // InteropTestCase3BasicPubSub.class);
+
+ // Parse all of the free arguments as test cases to run.
+ for (int i = 1; true; i++)
+ {
+ String nextFreeArg = options.getProperty(Integer.toString(i));
- // Extract the names of all the test classes, to pass to the start method.
- int i = 0;
- String[] testClassNames = new String[testCaseClasses.size()];
+ // Terminate the loop once all free arguments have been consumed.
+ if (nextFreeArg == null)
+ {
+ break;
+ }
- for (Class testClass : testCaseClasses)
- {
- testClassNames[i++] = testClass.getName();
- }
+ try
+ {
+ Class nextClass = Class.forName(nextFreeArg);
- // Create a coordinator and begin its test procedure.
- Coordinator coordinator = new Coordinator(brokerUrl, virtualHost, reportDir, engine);
+ if (DistributedTestCase.class.isAssignableFrom(nextClass))
+ {
+ testCaseClasses.add(nextClass);
+ console.info("Found distributed test case: " + nextFreeArg);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ console.info("Unable to instantiate the test case: " + nextFreeArg + ".");
+ }
+ }
+
+ // Check that some test classes were actually found.
+ if (testCaseClasses.isEmpty())
+ {
+ throw new RuntimeException("No test cases implementing InteropTestCase were specified on the command line.");
+ }
+
+ // Extract the names of all the test classes, to pass to the start method.
+ int i = 0;
+ String[] testClassNames = new String[testCaseClasses.size()];
+
+ for (Class testClass : testCaseClasses)
+ {
+ testClassNames[i++] = testClass.getName();
+ }
+
+ // Create a coordinator and begin its test procedure.
+ Coordinator coordinator = new Coordinator(brokerUrl, virtualHost, reportDir, engine, terminate);
- try
- {
TestResult testResult = coordinator.start(testClassNames);
// Return different error codes, depending on whether or not there were test failures.
@@ -225,8 +264,8 @@ public class Coordinator extends TKTestRunner
}
catch (Exception e)
{
- System.err.println(e.getMessage());
- log.error("Top level handler caught execption.", e);
+ log.debug("Top level handler caught execption.", e);
+ console.info(e.getMessage());
System.exit(EXCEPTION_EXIT);
}
}
@@ -280,11 +319,15 @@ public class Coordinator extends TKTestRunner
result = super.start(new String[] { testClassName });
}
- // At this point in time, all tests have completed. Broadcast the shutdown message.
- Message terminate = session.createMessage();
- terminate.setStringProperty("CONTROL_TYPE", "TERMINATE");
+ // At this point in time, all tests have completed. Broadcast the shutdown message, if the termination option
+ // was set on the command line.
+ if (terminate)
+ {
+ Message terminate = session.createMessage();
+ terminate.setStringProperty("CONTROL_TYPE", "TERMINATE");
- conversation.send(controlTopic, terminate);
+ conversation.send(controlTopic, terminate);
+ }
return result;
}
@@ -350,9 +393,9 @@ public class Coordinator extends TKTestRunner
Test nextTest = suite.testAt(i);
log.debug("suite.testAt(" + i + ") = " + nextTest);
- if (nextTest instanceof InteropTestCase)
+ if (nextTest instanceof DistributedTestCase)
{
- log.debug("nextTest is a InteropTestCase");
+ log.debug("nextTest is a DistributedTestCase");
}
}
@@ -383,7 +426,7 @@ public class Coordinator extends TKTestRunner
*
* @return An invititing test decorator, that invites all the enlisted clients to participate in tests, in pairs.
*/
- protected InvitingTestDecorator newTestDecorator(WrappedSuiteTestDecorator targetTest,
+ protected DistributedTestDecorator newTestDecorator(WrappedSuiteTestDecorator targetTest,
Set<TestClientDetails> enlistedClients, ConversationFactory conversationFactory, Connection connection)
{
switch (engine)
diff --git a/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java
new file mode 100644
index 0000000000..96b0d0c33f
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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.interop.coordinator;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+/**
+ * DistributedTestCase provides a base class implementation of the {@link org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer}, taking care of its
+ * more mundane aspects, such as recording the test pariticipants.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept notification of test case participants.
+ * <td> {@link org.apache.qpid.interop.coordinator.DistributedTestDecorator}
+ * <tr><td> Accept JMS Connection to carry out the coordination over.
+ * </table>
+ */
+public abstract class DistributedTestCase extends FrameworkBaseCase
+{
+ /** Used for debugging. */
+ private final Logger log = Logger.getLogger(DistributedTestCase.class);
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public DistributedTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Gets the test sequencer for this distributed test, cast as a {@link DistributedTestSequencer}, provided that it
+ * is one. If the test sequencer is not distributed, this returns null.
+ */
+ public DistributedTestSequencer getDistributedTestSequencer()
+ {
+ try
+ {
+ return (DistributedTestSequencer) testSequencer;
+ }
+ catch (ClassCastException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as known to the test
+ * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ * name "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ *
+ * @return The name of the corresponding interop test case.
+ */
+ public abstract String getTestCaseNameForTestMethod(String methodName);
+}
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java
index 1225d74fbf..e33a5c7228 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java
@@ -24,6 +24,7 @@ import junit.framework.TestResult;
import org.apache.log4j.Logger;
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
import org.apache.qpid.util.ConversationFactory;
import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
@@ -36,19 +37,24 @@ import javax.jms.Message;
import java.util.*;
/**
- * InvitingTestDecorator is a base class for writing test decorators that invite test clients to participate in
- * distributed test cases. It provides a helper method, {@link #signupClients(InteropTestCase)}, that broadcasts
- * an invitation and return the set of test clients that are available to particiapte in the test.
+ * DistributedTestDecorator is a base class for writing test decorators that invite test clients to participate in
+ * distributed test cases. It provides a helper method, {@link #signupClients}, that broadcasts an invitation and
+ * returns the set of test clients that are available to particiapte in the test.
+ *
+ * <p/>When used to wrap a {@link org.apache.qpid.test.framework.FrameworkBaseCase} test, it replaces the default
+ * {@link org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer} implementations with a suitable
+ * {@link org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer}. Concrete implementations
+ * can use this to configure the sending and receiving roles on the test.
*
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Broadcast test invitations and collect enlists. <td> {@link ConversationFactory}.
* </table>
*/
-public abstract class InvitingTestDecorator extends WrappedSuiteTestDecorator
+public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator
{
/** Used for debugging. */
- private static final Logger log = Logger.getLogger(InvitingTestDecorator.class);
+ private static final Logger log = Logger.getLogger(DistributedTestDecorator.class);
/** Holds the contact information for all test clients that are available and that may take part in the test. */
Set<TestClientDetails> allClients;
@@ -59,7 +65,7 @@ public abstract class InvitingTestDecorator extends WrappedSuiteTestDecorator
/** Holds the connection that the control conversation is held over. */
Connection connection;
- /** Holds the underlying {@link InteropTestCase}s that this decorator wraps. */
+ /** Holds the underlying {@link DistributedTestCase}s that this decorator wraps. */
WrappedSuiteTestDecorator testSuite;
/** Holds the control topic, on which test invitations are broadcast. */
@@ -73,12 +79,12 @@ public abstract class InvitingTestDecorator extends WrappedSuiteTestDecorator
* @param controlConversation The conversation helper for the control level, test coordination conversation.
* @param controlConnection The connection that the coordination messages are sent over.
*/
- public InvitingTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
+ public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
ConversationFactory controlConversation, Connection controlConnection)
{
super(suite);
- log.debug("public InvitingTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+ log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+ availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called");
testSuite = suite;
@@ -105,6 +111,14 @@ public abstract class InvitingTestDecorator extends WrappedSuiteTestDecorator
public abstract void run(TestResult testResult);
/**
+ * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase}
+ * tests.
+ *
+ * @return A distributed test sequencer.
+ */
+ public abstract DistributedTestSequencer getDistributedTestSequencer();
+
+ /**
* Broadcasts an invitation to participate in a coordinating test case to find out what clients are available to
* run the test case.
*
@@ -112,7 +126,7 @@ public abstract class InvitingTestDecorator extends WrappedSuiteTestDecorator
*
* @return A set of test clients that accepted the invitation.
*/
- protected Set<TestClientDetails> signupClients(InteropTestCase coordTest)
+ protected Set<TestClientDetails> signupClients(DistributedTestCase coordTest)
{
// Broadcast the invitation to find out what clients are available to test.
Set<TestClientDetails> enlists;
@@ -146,6 +160,6 @@ public abstract class InvitingTestDecorator extends WrappedSuiteTestDecorator
*/
public String toString()
{
- return "InvitingTestDecorator: [ testSuite = " + testSuite + " ]";
+ return "DistributedTestDecorator: [ testSuite = " + testSuite + " ]";
}
}
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java
index f7e38fb1ad..f7e38fb1ad 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java
index 5e3fb51b97..acace5bd7d 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java
@@ -25,6 +25,9 @@ import junit.framework.TestResult;
import org.apache.log4j.Logger;
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+import org.apache.qpid.interop.coordinator.sequencers.FanOutTestSequencer;
+import org.apache.qpid.interop.coordinator.sequencers.InteropTestSequencer;
import org.apache.qpid.util.ConversationFactory;
import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
@@ -39,24 +42,24 @@ import java.util.Iterator;
import java.util.Set;
/**
- * FanOutTestDecorator is an {@link InvitingTestDecorator} that runs one test client in the sender role, and the remainder
- * in the receiver role. It also has the capability to listen for new test cases joining the test beyond the initial start
+ * FanOutTestDecorator is an {@link DistributedTestDecorator} that runs one test client in the sender role, and the remainder
+ * in the receivers role. It also has the capability to listen for new test cases joining the test beyond the initial start
* point. This feature can be usefull when experimenting with adding more load, in the form of more test clients, to assess
* its impact on a running test.
*
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Execute coordinated test cases. <td> {@link InteropTestCase}
+ * <tr><td> Execute coordinated test cases. <td> {@link DistributedTestCase}
* <tr><td> Accept test clients joining a running test.
* </table>
*/
-public class FanOutTestDecorator extends InvitingTestDecorator implements MessageListener
+public class FanOutTestDecorator extends DistributedTestDecorator implements MessageListener
{
/** Used for debugging. */
private static final Logger log = Logger.getLogger(FanOutTestDecorator.class);
/** Holds the currently running test case. */
- InteropTestCase currentTest = null;
+ DistributedTestCase currentTest = null;
/**
* Creates a wrapped suite test decorator from another one.
@@ -71,7 +74,7 @@ public class FanOutTestDecorator extends InvitingTestDecorator implements Messag
{
super(suite, availableClients, controlConversation, controlConnection);
- log.debug("public InvitingTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+ log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+ availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called");
testSuite = suite;
@@ -110,7 +113,7 @@ public class FanOutTestDecorator extends InvitingTestDecorator implements Messag
// Run all of the test cases in the test suite.
for (Test test : tests)
{
- InteropTestCase coordTest = (InteropTestCase) test;
+ DistributedTestCase coordTest = (DistributedTestCase) test;
// Get all of the clients able to participate in the test.
Set<TestClientDetails> enlists = signupClients(coordTest);
@@ -121,24 +124,28 @@ public class FanOutTestDecorator extends InvitingTestDecorator implements Messag
throw new RuntimeException("No clients to test with");
}
- // Set up the first client in the sender role, and the remainder in the receiver role.
+ // Create a distributed test sequencer for the test.
+ DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+ // Set up the first client in the sender role, and the remainder in the receivers role.
Iterator<TestClientDetails> clients = enlists.iterator();
- coordTest.setSender(clients.next());
+ sequencer.setSender(clients.next());
while (clients.hasNext())
{
// Set the sending and receiving client details on the test case.
- coordTest.setReceiver(clients.next());
+ sequencer.setReceiver(clients.next());
}
// Pass down the connection to hold the coordinating conversation over.
- coordTest.setConversationFactory(conversationFactory);
+ sequencer.setConversationFactory(conversationFactory);
// If the current test case is a drop-in test, set it up as the currently running test for late joiners to
// add in to. Otherwise the current test field is set to null, to indicate that late joiners are not allowed.
currentTest = (coordTest instanceof DropInTest) ? coordTest : null;
// Execute the test case.
+ coordTest.setTestSequencer(sequencer);
coordTest.run(testResult);
currentTest = null;
@@ -146,9 +153,20 @@ public class FanOutTestDecorator extends InvitingTestDecorator implements Messag
}
/**
+ * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase}
+ * tests.
+ *
+ * @return A distributed test sequencer.
+ */
+ public DistributedTestSequencer getDistributedTestSequencer()
+ {
+ return new FanOutTestSequencer();
+ }
+
+ /**
* Listens to incoming messages on the control topic. If the messages are 'join' messages, signalling a new
* test client wishing to join the current test, then the new client will be added to the current test in the
- * receiver role.
+ * receivers role.
*
* @param message The incoming control message.
*/
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java
index 85d127110d..7dcc391650 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java
@@ -25,6 +25,8 @@ import junit.framework.TestResult;
import org.apache.log4j.Logger;
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+import org.apache.qpid.interop.coordinator.sequencers.InteropTestSequencer;
import org.apache.qpid.util.ConversationFactory;
import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
@@ -34,10 +36,10 @@ import javax.jms.Connection;
import java.util.*;
/**
- * InvitingTestDecorator is a test decorator, written to implement the interop test specification. Given a list
+ * DistributedTestDecorator is a test decorator, written to implement the interop test specification. Given a list
* of enlisted test clients, that are available to run interop tests, this decorator invites them to participate
* in each test in the wrapped test suite. Amongst all the clients that respond to the invite, all pairs are formed,
- * and each pairing (in both directions, but excluding the reflexive pairings) is split into a sender and receiver
+ * and each pairing (in both directions, but excluding the reflexive pairings) is split into a sender and receivers
* role and a test case run between them. Any enlisted combinations that do not accept a test invite are automatically
* failed.
*
@@ -45,11 +47,11 @@ import java.util.*;
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Broadcast test invitations and collect enlists. <td> {@link org.apache.qpid.util.ConversationFactory}.
* <tr><td> Output test failures for clients unwilling to run the test case. <td> {@link Coordinator}
- * <tr><td> Execute coordinated test cases. <td> {@link InteropTestCase}
+ * <tr><td> Execute distributed test cases. <td> {@link DistributedTestCase}
* <tr><td> Fail non participating pairings. <td> {@link OptOutTestCase}
* </table>
*/
-public class InteropTestDecorator extends InvitingTestDecorator
+public class InteropTestDecorator extends DistributedTestDecorator
{
/** Used for debugging. */
private static final Logger log = Logger.getLogger(InteropTestDecorator.class);
@@ -71,7 +73,7 @@ public class InteropTestDecorator extends InvitingTestDecorator
/**
* Broadcasts a test invitation and accetps enlisting from participating clients. The wrapped test case is
* then repeated for every combination of test clients (provided the wrapped test case extends
- * {@link InteropTestCase}.
+ * {@link DistributedTestCase}.
*
* <p/>Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime exceptions,
* resulting in the non-completion of the test run.
@@ -88,7 +90,7 @@ public class InteropTestDecorator extends InvitingTestDecorator
for (Test test : tests)
{
- InteropTestCase coordTest = (InteropTestCase) test;
+ DistributedTestCase coordTest = (DistributedTestCase) test;
// Broadcast the invitation to find out what clients are available to test.
Set<TestClientDetails> enlists = signupClients(coordTest);
@@ -102,9 +104,14 @@ public class InteropTestDecorator extends InvitingTestDecorator
for (List<TestClientDetails> failPair : failPairs)
{
- InteropTestCase failTest = new OptOutTestCase("testOptOut");
- failTest.setSender(failPair.get(0));
- failTest.setReceiver(failPair.get(1));
+ // Create a distributed test sequencer for the test.
+ DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+ // Create an automatic failure test for the opted out test pair.
+ DistributedTestCase failTest = new OptOutTestCase("testOptOut");
+ sequencer.setSender(failPair.get(0));
+ sequencer.setReceiver(failPair.get(1));
+ failTest.setTestSequencer(sequencer);
failTest.run(testResult);
}
@@ -114,20 +121,35 @@ public class InteropTestDecorator extends InvitingTestDecorator
for (List<TestClientDetails> enlistedPair : enlistedPairs)
{
- // Set the sending and receiving client details on the test case.
- coordTest.setSender(enlistedPair.get(0));
- coordTest.setReceiver(enlistedPair.get(1));
+ // Create a distributed test sequencer for the test.
+ DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+ // Set the sending and receiving client details on the test sequencer.
+ sequencer.setSender(enlistedPair.get(0));
+ sequencer.setReceiver(enlistedPair.get(1));
// Pass down the connection to hold the coordination conversation over.
- coordTest.setConversationFactory(conversationFactory);
+ sequencer.setConversationFactory(conversationFactory);
// Execute the test case.
+ coordTest.setTestSequencer(sequencer);
coordTest.run(testResult);
}
}
}
/**
+ * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase}
+ * tests.
+ *
+ * @return A distributed test sequencer.
+ */
+ public DistributedTestSequencer getDistributedTestSequencer()
+ {
+ return new InteropTestSequencer();
+ }
+
+ /**
* Produces all pairs of combinations of elements from two sets. The ordering of the elements in the pair is
* important, that is the pair <l, r> is distinct from <r, l>; both pairs are generated. For any element, i, in
* both the left and right sets, the reflexive pair <i, i> is not generated.
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java
index 4332aaf55c..f3673583e7 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java
@@ -22,17 +22,19 @@ package org.apache.qpid.interop.coordinator;
import junit.framework.Assert;
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+
/**
* An OptOutTestCase is a test case that automatically fails. It is used when a list of test clients has been generated
* from a compulsory invite, but only some of those clients have responded to a specific test case invite. The clients
- * that did not respond, are automatically given a fail for the test.
+ * that did not respond, may automatically be given a fail for some tests.
*
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Fail the test with a suitable reason.
* </table>
*/
-public class OptOutTestCase extends InteropTestCase
+public class OptOutTestCase extends DistributedTestCase
{
/**
* Creates a new coordinating test case with the specified name.
@@ -47,7 +49,10 @@ public class OptOutTestCase extends InteropTestCase
/** Generates an appropriate test failure assertion. */
public void testOptOut()
{
- Assert.fail("One of " + getSender() + " and " + getReceiver() + " opted out of the test.");
+ DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+ Assert.fail("One of " + sequencer.getSender() + " and " + getDistributedTestSequencer().getReceivers()
+ + " opted out of the test.");
}
/**
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java
index 742375b7bd..742375b7bd 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java
index 74c86b1d83..74c86b1d83 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java
diff --git a/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java
new file mode 100644
index 0000000000..405898f1e6
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.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.interop.coordinator.distributedcircuit;
+
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.Publisher;
+import org.apache.qpid.test.framework.Receiver;
+
+import java.util.List;
+
+/**
+ * DistributedCircuitImpl is a distributed implementation of the test {@link Circuit}. Many publishers and receivers
+ * accross multiple machines may be combined to form a single test circuit. The test circuit extracts reports from
+ * all of its publishers and receivers, and applies its assertions to these reports.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ * <tr><td> Start the circuit running.
+ * <tr><td> Close the circuit down.
+ * <tr><td> Take a reading of the circuits state.
+ * <tr><td> Apply assertions against the circuits state.
+ * <tr><td> Send test messages over the circuit.
+ * <tr><td> Perform the default test procedue on the circuit.
+ * </table>
+ */
+public class DistributedCircuitImpl implements Circuit
+{
+ /**
+ * Gets the interface on the publishing end of the circuit.
+ *
+ * @return The publishing end of the circuit.
+ */
+ public Publisher getPublisher()
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /**
+ * Gets the interface on the receiving end of the circuit.
+ *
+ * @return The receiving end of the circuit.
+ */
+ public Receiver getReceiver()
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /**
+ * Connects and starts the circuit. After this method is called the circuit is ready to send messages.
+ */
+ public void start()
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /**
+ * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+ * into a report, against which assertions may be checked.
+ */
+ public void check()
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /**
+ * Closes the circuit. All associated resources are closed.
+ */
+ public void close()
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /**
+ * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing
+ * this, to ensure that the circuit has gathered its state into a report to assert against.
+ *
+ * @param assertions The list of assertions to apply.
+ * @return Any assertions that failed.
+ */
+ public List<Assertion> applyAssertions(List<Assertion> assertions)
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /**
+ * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold.
+ *
+ * @param numMessages The number of messages to send using the default test procedure.
+ * @param assertions The list of assertions to apply.
+ * @return Any assertions that failed.
+ */
+ public List<Assertion> test(int numMessages, List<Assertion> assertions)
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java
new file mode 100644
index 0000000000..ad073014d0
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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.interop.coordinator.sequencers;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.util.ConversationFactory;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public abstract class BaseDistributedTestSequencer implements DistributedTestSequencer
+{
+ /** Used for debugging. */
+ private final Logger log = Logger.getLogger(DistributedTestCase.class);
+
+ /** Holds the contact details for the sending test client. */
+ protected TestClientDetails sender;
+
+ /** Holds the contact details for the receving test client. */
+ protected List<TestClientDetails> receivers = new LinkedList<TestClientDetails>();
+
+ /** Holds the conversation factory over which to coordinate the test. */
+ protected ConversationFactory conversationFactory;
+
+ /**
+ * Creates a test circuit for the test, configered by the test parameters specified.
+ *
+ * @param testProperties The test parameters.
+ * @return A test circuit.
+ */
+ public Circuit createCircuit(Properties testProperties)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Sets the sender test client to coordinate the test with.
+ *
+ * @param sender The contact details of the sending client in the test.
+ */
+ public void setSender(TestClientDetails sender)
+ {
+ log.debug("public void setSender(TestClientDetails sender = " + sender + "): called");
+
+ this.sender = sender;
+ }
+
+ /**
+ * Sets the receiving test client to coordinate the test with.
+ *
+ * @param receiver The contact details of the sending client in the test.
+ */
+ public void setReceiver(TestClientDetails receiver)
+ {
+ log.debug("public void setReceiver(TestClientDetails receivers = " + receiver + "): called");
+
+ this.receivers.add(receiver);
+ }
+
+ /**
+ * Supplies the sending test client.
+ *
+ * @return The sending test client.
+ */
+ public TestClientDetails getSender()
+ {
+ return sender;
+ }
+
+ /**
+ * Supplies the receiving test client.
+ *
+ * @return The receiving test client.
+ */
+ public List<TestClientDetails> getReceivers()
+ {
+ return receivers;
+ }
+
+ /**
+ * Accepts the conversation factory over which to hold the test coordinating conversation.
+ *
+ * @param conversationFactory The conversation factory to coordinate the test over.
+ */
+ public void setConversationFactory(ConversationFactory conversationFactory)
+ {
+ this.conversationFactory = conversationFactory;
+ }
+
+ /**
+ * Provides the conversation factory for providing the distributed test sequencing conversations over the test
+ * connection.
+ *
+ * @return The conversation factory to create test sequencing conversations with.
+ */
+ public ConversationFactory getConversationFactory()
+ {
+ return conversationFactory;
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java
new file mode 100644
index 0000000000..9b58107796
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java
@@ -0,0 +1,75 @@
+/*
+ *
+ * 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.interop.coordinator.sequencers;
+
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.util.ConversationFactory;
+
+import java.util.List;
+
+/**
+ * A DistributedTestSequencer is a test sequencer that coordinates activity amongst many
+ * {@link org.apache.qpid.interop.testclient.TestClient}s.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept notification of test case participants.
+ * <tr><td> Accept JMS Connection to carry out the coordination over.
+ * <tr><td> Coordinate a test sequence amongst participants. <td> {@link ConversationFactory}
+ * </table>
+ */
+public interface DistributedTestSequencer extends TestCaseSequencer
+{
+ /**
+ * Sets the sender test client to coordinate the test with.
+ *
+ * @param sender The contact details of the sending client in the test.
+ */
+ public void setSender(TestClientDetails sender);
+
+ /**
+ * Sets the receiving test client to coordinate the test with.
+ *
+ * @param receiver The contact details of the sending client in the test.
+ */
+ public void setReceiver(TestClientDetails receiver);
+
+ /**
+ * Supplies the sending test client.
+ *
+ * @return The sending test client.
+ */
+ public TestClientDetails getSender();
+
+ /**
+ * Supplies the receiving test client.
+ *
+ * @return The receiving test client.
+ */
+ public List<TestClientDetails> getReceivers();
+
+ /**
+ * Accepts the conversation factory over which to hold the test coordinating conversation.
+ *
+ * @param conversationFactory The conversation factory to coordinate the test over.
+ */
+ public void setConversationFactory(ConversationFactory conversationFactory);
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java
new file mode 100644
index 0000000000..5a41481e21
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java
@@ -0,0 +1,171 @@
+/*
+ *
+ * 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.interop.coordinator.sequencers;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class FanOutTestSequencer extends BaseDistributedTestSequencer
+{
+ /** Used for debugging. */
+ Logger log = Logger.getLogger(FanOutTestSequencer.class);
+
+ /**
+ * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ * begining the test, gathering the test reports from the participants, and checking for assertion failures against
+ * the test reports.
+ *
+ * @param testCircuit The test circuit.
+ * @param assertions The list of assertions to apply to the test circuit.
+ * @param testProperties The test case definition.
+ */
+ public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
+ {
+ log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
+
+ TestClientDetails sender = getSender();
+ List<TestClientDetails> receivers = getReceivers();
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ try
+ {
+ // Create a conversation on the sender clients private control rouete.
+ Session session = conversationFactory.getSession();
+ Destination senderControlTopic = session.createTopic(sender.privateControlKey);
+ ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
+
+ // Assign the sender role to the sending test client.
+ Message assignSender = conversationFactory.getSession().createMessage();
+ TestUtils.setPropertiesOnMessage(assignSender, testProperties);
+ assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignSender.setStringProperty("ROLE", "SENDER");
+ assignSender.setStringProperty("CLIENT_NAME", "Sustained_SENDER");
+
+ senderConversation.send(senderControlTopic, assignSender);
+
+ // Wait for the sender to confirm its role.
+ senderConversation.receive();
+
+ // Assign the receivers roles.
+ for (TestClientDetails receiver : receivers)
+ {
+ assignReceiverRole(receiver, testProperties, true);
+ }
+
+ // Start the test on the sender.
+ Message start = session.createMessage();
+ start.setStringProperty("CONTROL_TYPE", "START");
+
+ senderConversation.send(senderControlTopic, start);
+
+ // Wait for the test sender to return its report.
+ Message senderReport = senderConversation.receive();
+ TestUtils.pause(500);
+
+ // Ask the receivers for their reports.
+ Message statusRequest = session.createMessage();
+ statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
+
+ // Gather the reports from all of the receiving clients.
+
+ // Return all of the test reports, the senders report first.
+ // return new Message[] { senderReport };
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Unhandled JMSException.");
+ }
+ }
+
+ /**
+ * Creates a test circuit for the test, configered by the test parameters specified.
+ *
+ * @param testProperties The test parameters.
+ * @return A test circuit.
+ */
+ public Circuit createCircuit(ParsedProperties testProperties)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Assigns the receivers role to the specified test client that is to act as a receivers during the test. This method
+ * does not always wait for the receiving clients to confirm their role assignments. This is because this method
+ * may be called from an 'onMessage' method, when a client is joining the test at a later point in time, and it
+ * is not possible to do a synchronous receive during an 'onMessage' method. There is a flag to indicate whether
+ * or not to wait for role confirmations.
+ *
+ * @param receiver The test client to assign the receivers role to.
+ * @param testProperties The test parameters.
+ * @param confirm Indicates whether role confirmation should be waited for.
+ *
+ * @throws JMSException Any JMSExceptions occurring during the conversation are allowed to fall through.
+ */
+ protected void assignReceiverRole(TestClientDetails receiver, Properties testProperties, boolean confirm)
+ throws JMSException
+ {
+ log.info("assignReceiverRole(TestClientDetails receivers = " + receiver + ", Map<String, Object> testProperties = "
+ + testProperties + "): called");
+
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ // Create a conversation with the receiving test client.
+ Session session = conversationFactory.getSession();
+ Destination receiverControlTopic = session.createTopic(receiver.privateControlKey);
+ ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
+
+ // Assign the receivers role to the receiving client.
+ Message assignReceiver = session.createMessage();
+ TestUtils.setPropertiesOnMessage(assignReceiver, testProperties);
+ assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignReceiver.setStringProperty("ROLE", "RECEIVER");
+ assignReceiver.setStringProperty("CLIENT_NAME", receiver.clientName);
+
+ receiverConversation.send(receiverControlTopic, assignReceiver);
+
+ // Wait for the role confirmation to come back.
+ if (confirm)
+ {
+ receiverConversation.receive();
+ }
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java
new file mode 100644
index 0000000000..0230bf4d77
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java
@@ -0,0 +1,137 @@
+/*
+ *
+ * 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.interop.coordinator.sequencers;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class InteropTestSequencer extends BaseDistributedTestSequencer
+{
+ /** Used for debugging. */
+ Logger log = Logger.getLogger(InteropTestSequencer.class);
+
+ /**
+ * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ * begining the test, gathering the test reports from the participants, and checking for assertion failures against
+ * the test reports.
+ *
+ * @param testCircuit The test circuit.
+ * @param assertions The list of assertions to apply to the test circuit.
+ * @param testProperties The test case definition.
+ */
+ public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
+ {
+ log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
+
+ TestClientDetails sender = getSender();
+ List<TestClientDetails> receivers = getReceivers();
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ try
+ {
+ Session session = conversationFactory.getSession();
+ Destination senderControlTopic = session.createTopic(sender.privateControlKey);
+ Destination receiverControlTopic = session.createTopic(receivers.get(0).privateControlKey);
+
+ ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
+ ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
+
+ // Assign the sender role to the sending test client.
+ Message assignSender = conversationFactory.getSession().createMessage();
+ TestUtils.setPropertiesOnMessage(assignSender, testProperties);
+ assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignSender.setStringProperty("ROLE", "SENDER");
+
+ senderConversation.send(senderControlTopic, assignSender);
+
+ // Assign the receivers role the receiving client.
+ Message assignReceiver = session.createMessage();
+ TestUtils.setPropertiesOnMessage(assignReceiver, testProperties);
+ assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignReceiver.setStringProperty("ROLE", "RECEIVER");
+
+ receiverConversation.send(receiverControlTopic, assignReceiver);
+
+ // Wait for the senders and receivers to confirm their roles.
+ senderConversation.receive();
+ receiverConversation.receive();
+
+ // Start the test.
+ Message start = session.createMessage();
+ start.setStringProperty("CONTROL_TYPE", "START");
+
+ senderConversation.send(senderControlTopic, start);
+
+ // Wait for the test sender to return its report.
+ Message senderReport = senderConversation.receive();
+ TestUtils.pause(500);
+
+ // Ask the receivers for its report.
+ Message statusRequest = session.createMessage();
+ statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
+
+ receiverConversation.send(receiverControlTopic, statusRequest);
+
+ // Wait for the receivers to send its report.
+ Message receiverReport = receiverConversation.receive();
+
+ // return new Message[] { senderReport, receiverReport };
+
+ // Apply assertions.
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("JMSException not handled.");
+ }
+ }
+
+ /**
+ * Creates a test circuit for the test, configered by the test parameters specified.
+ *
+ * @param testProperties The test parameters.
+ * @return A test circuit.
+ */
+ public Circuit createCircuit(ParsedProperties testProperties)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java
new file mode 100644
index 0000000000..94105f30a8
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.interop.coordinator.sequencers;
+
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * A TestCaseSequence is responsibile for creating test circuits appropriate to the context that a test case is
+ * running in, and providing an implementation of a standard test procedure over a test circuit.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * </table>
+ */
+public interface TestCaseSequencer
+{
+ /**
+ * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ * begining the test, gathering the test reports from the participants, and checking for assertion failures against
+ * the test reports.
+ *
+ * @param testCircuit The test circuit.
+ * @param assertions The list of assertions to apply to the test circuit.
+ * @param testProperties The test case definition.
+ */
+ public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties);
+
+ /**
+ * Creates a test circuit for the test, configered by the test parameters specified.
+ *
+ * @param testProperties The test parameters.
+ *
+ * @return A test circuit.
+ */
+ public Circuit createCircuit(ParsedProperties testProperties);
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java
index c2b7a2094f..6dd0a08198 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java
@@ -20,8 +20,8 @@
*/
package org.apache.qpid.server.exchange;
+import org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer;
import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.CircuitImpl;
import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.MessagingTestConfigProperties;
import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
@@ -67,6 +67,16 @@ public class ImmediateMessageTest extends FrameworkBaseCase
/** Used to read the tests configurable properties through. */
ParsedProperties testProps;
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public ImmediateMessageTest(String name)
+ {
+ super(name);
+ }
+
/** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
public void test_QPID_517_ImmediateOkNoTxP2P()
{
@@ -74,10 +84,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ // Run the default test sequence over the test circuit checking for no errors.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
@@ -87,10 +97,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
@@ -100,13 +110,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
}
/** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
@@ -116,13 +127,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
}
/** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
@@ -132,14 +144,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
// Send one message and get a linked no route exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
/** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
@@ -149,14 +161,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ // Send one message and get a linked no route exception.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
/** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
@@ -166,10 +178,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
@@ -179,10 +191,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
@@ -195,13 +207,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
// Use durable subscriptions, so that the route remains open with no subscribers.
testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
}
/** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
@@ -214,13 +227,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
// Use durable subscriptions, so that the route remains open with no subscribers.
testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
}
/** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
@@ -230,14 +244,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
// Send one message and get a linked no route exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
/** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
@@ -247,14 +261,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
// Send one message and get a linked no route exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
protected void setUp() throws Exception
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java
index 66695b93dc..987a458121 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java
@@ -20,8 +20,8 @@
*/
package org.apache.qpid.server.exchange;
+import org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer;
import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.CircuitImpl;
import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.MessagingTestConfigProperties;
import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
@@ -67,6 +67,16 @@ public class MandatoryMessageTest extends FrameworkBaseCase
/** Used to read the tests configurable properties through. */
ParsedProperties testProps;
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public MandatoryMessageTest(String name)
+ {
+ super(name);
+ }
+
/** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */
public void test_QPID_508_MandatoryOkNoTxP2P()
{
@@ -74,10 +84,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ // Run the default test sequence over the test circuit checking for no errors.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
@@ -87,10 +97,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ // Run the default test sequence over the test circuit checking for no errors.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/**
@@ -103,13 +113,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/**
@@ -122,13 +133,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
@@ -138,14 +150,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ // Send one message and get a linked no route exception.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
/** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
@@ -155,14 +167,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ // Send one message and get a linked no route exception.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
/** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */
@@ -172,10 +184,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ // Run the default test sequence over the test circuit checking for no errors.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
@@ -185,10 +197,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ // Run the default test sequence over the test circuit checking for no errors.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/**
@@ -204,13 +216,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
// Use durable subscriptions, so that the route remains open with no subscribers.
testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/**
@@ -226,13 +239,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
// Use durable subscriptions, so that the route remains open with no subscribers.
testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
// Disconnect the consumer.
testCircuit.getReceiver().getConsumer().close();
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
}
/** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
@@ -242,14 +256,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ // Send one message and get a linked no route exception.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
/** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
@@ -259,14 +273,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase
testProps.setProperty(TRANSACTED_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
// collect its messages).
testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
- Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ // Send one message and get a linked no route exception.
+ TestCaseSequencer sequencer = getTestSequencer();
+ Circuit testCircuit = sequencer.createCircuit(testProps);
+ sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
}
protected void setUp() throws Exception
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
index 542adf4708..ebbffd8a71 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
@@ -24,7 +24,6 @@ package org.apache.qpid.server.exchange;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.util.TestApplicationRegistry;
import org.apache.qpid.server.util.NullApplicationRegistry;
import org.apache.qpid.client.*;
import org.apache.qpid.client.transport.TransportConnection;
@@ -127,8 +126,8 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
con.start();
TextMessage tm = (TextMessage) consumer.receive(1000L);
- assertTrue("No message routed to receiver", tm != null);
- assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg3".equals(tm.getText()));
+ assertTrue("No message routed to receivers", tm != null);
+ assertTrue("Wrong message routed to receivers: " + tm.getText(), "msg3".equals(tm.getText()));
try
{
@@ -194,8 +193,8 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
con.start();
TextMessage tm = (TextMessage) consumer.receive(1000L);
- assertTrue("No message routed to receiver", tm != null);
- assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg1".equals(tm.getText()));
+ assertTrue("No message routed to receivers", tm != null);
+ assertTrue("Wrong message routed to receivers: " + tm.getText(), "msg1".equals(tm.getText()));
try
{
@@ -260,8 +259,8 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
con.start();
TextMessage tm = (TextMessage) consumer.receive(1000L);
- assertTrue("No message routed to receiver", tm != null);
- assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg1".equals(tm.getText()));
+ assertTrue("No message routed to receivers", tm != null);
+ assertTrue("Wrong message routed to receivers: " + tm.getText(), "msg1".equals(tm.getText()));
try
{
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTestManual.java b/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTestManual.java
index 5abbbd2aae..d01284cb8a 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTestManual.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTestManual.java
@@ -1,39 +1,41 @@
/*
- * 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
+ * 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
*
- * 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.
+ * 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 org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.AMQException;
+import org.apache.log4j.Logger;
+
import org.apache.qpid.AMQChannelClosedException;
import org.apache.qpid.AMQConnectionClosedException;
-import org.apache.qpid.util.CommandLineParser;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
import org.apache.qpid.url.URLSyntaxException;
-import org.apache.log4j.Logger;
+import org.apache.qpid.util.CommandLineParser;
-import javax.jms.Session;
import javax.jms.JMSException;
-import javax.jms.Queue;
import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
import javax.jms.TextMessage;
+
import java.io.IOException;
import java.util.Properties;
@@ -41,7 +43,6 @@ public class PersistentTestManual
{
private static final Logger _logger = Logger.getLogger(PersistentTestManual.class);
-
private static final String QUEUE = "direct://amq.direct//PersistentTest-Queue2?durable='true',exclusive='true'";
protected AMQConnection _connection;
@@ -89,7 +90,7 @@ public class PersistentTestManual
public void test() throws AMQException, URLSyntaxException
{
- //Create the Durable Queue
+ // Create the Durable Queue
try
{
_session.createConsumer(_session.createQueue(QUEUE)).close();
@@ -121,16 +122,17 @@ public class PersistentTestManual
System.out.println("Continuing....");
}
- //Test queue is still there.
- AMQConnection connection = new AMQConnection(_brokerDetails, _username, _password, "DifferentClientID", _virtualpath);
+ // Test queue is still there.
+ AMQConnection connection =
+ new AMQConnection(_brokerDetails, _username, _password, "DifferentClientID", _virtualpath);
AMQSession session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
try
{
session.createConsumer(session.createQueue(QUEUE));
- _logger.error("Create consumer succeeded." +
- " This shouldn't be allowed as this means the queue didn't exist when it should");
+ _logger.error("Create consumer succeeded."
+ + " This shouldn't be allowed as this means the queue didn't exist when it should");
connection.close();
@@ -189,6 +191,7 @@ public class PersistentTestManual
{
//
}
+
System.exit(0);
}
@@ -196,7 +199,7 @@ public class PersistentTestManual
{
String TEST_TEXT = "init";
- //Create a new session to send producer
+ // Create a new session to send producer
Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue q = session.createQueue(QUEUE);
@@ -204,10 +207,9 @@ public class PersistentTestManual
producer.send(session.createTextMessage(TEST_TEXT));
- //create a new consumer on the original session
+ // create a new consumer on the original session
TextMessage m = (TextMessage) _session.createConsumer(q).receive();
-
if ((m != null) && m.getText().equals(TEST_TEXT))
{
return true;
@@ -216,6 +218,7 @@ public class PersistentTestManual
{
_logger.error("Incorrect values returned from Queue Test:" + m);
System.exit(0);
+
return false;
}
}
@@ -259,8 +262,8 @@ public class PersistentTestManual
{
PersistentTestManual test;
- Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][]{}));
-
+ Properties options =
+ CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
test = new PersistentTestManual(options);
try
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java b/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java
index 74c14ee6c5..a041c0b838 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java
@@ -24,7 +24,7 @@ import java.util.List;
/**
* A Circuit is the basic test unit against which test cases are to be written. A circuit consists of two 'ends', an
- * instigating 'publisher' end and a more passive 'receiver' end.
+ * instigating 'publisher' end and a more passive 'receivers' end.
*
* <p/>Once created, the life-cycle of a circuit may be controlled by {@link #start()}ing it, or {@link #close()}ing it.
* Once started, the circuit is ready to send messages over. Once closed the circuit can no longer be used.
@@ -97,10 +97,10 @@ public interface Circuit
*/
public List<Assertion> applyAssertions(List<Assertion> assertions);
- /**
+ /*
* Sends a message on the test circuit. The exact nature of the message sent is controlled by the test parameters.
*/
- public void send();
+ // public void send();
/**
* Runs the default test procedure against the circuit, and checks that all of the specified assertions hold.
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java
index 70bd16353c..0bcf2e5036 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.test.framework;
-import junit.framework.Assert;
-
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.test.framework.MessageMonitor;
@@ -49,6 +47,9 @@ import java.util.concurrent.atomic.AtomicLong;
* <tr><td> Perform the default test procedure on the circuit.
* <tr><td> Provide access to connection and session exception monitors <td> {@link ExceptionMonitor}
* </table>
+ *
+ * @todo Add ability to create routes with no consumers active on them. Immediate/Mandatory tests are closing consumers
+ * themsleves to create this scenario. Should make it part of the test configuration.
*/
public class CircuitImpl implements Circuit
{
@@ -74,12 +75,12 @@ public class CircuitImpl implements Circuit
private ExceptionMonitor exceptionMonitor;
/**
- * Creates a test circuit using the specified test parameters. The publisher, receiver, connection and
+ * Creates a test circuit using the specified test parameters. The publisher, receivers, connection and
* connection monitor must already have been created, to assemble the circuit.
*
* @param testProps The test parameters.
* @param publisher The test publisher.
- * @param receiver The test receiver.
+ * @param receiver The test receivers.
* @param connection The connection.
* @param connectionExceptionMonitor The connection exception monitor.
*/
@@ -93,7 +94,7 @@ public class CircuitImpl implements Circuit
this.connectionExceptionMonitor = connectionExceptionMonitor;
this.exceptionMonitor = new ExceptionMonitor();
- // Set this as the parent circuit on the publisher and receiver.
+ // Set this as the parent circuit on the publisher and receivers.
publisher.setCircuit(this);
receiver.setCircuit(this);
}
@@ -107,9 +108,11 @@ public class CircuitImpl implements Circuit
*/
public static Circuit createCircuit(ParsedProperties testProps)
{
- // Create a standard publisher/receiver test client pair on a shared connection, individual sessions.
+ // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
try
{
+ // ParsedProperties testProps = new ParsedProperties(testProps);
+
// Get a unique offset to append to destination names to make them unique to the connection.
long uniqueId = uniqueDestsId.incrementAndGet();
@@ -211,7 +214,7 @@ public class CircuitImpl implements Circuit
}
catch (JMSException e)
{
- throw new RuntimeException("Could not create publisher/receiver pair due to a JMSException.", e);
+ throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
}
}
@@ -348,7 +351,7 @@ public class CircuitImpl implements Circuit
// Apply all of the requested assertions, keeping record of any that fail.
List<Assertion> failures = applyAssertions(assertions);
- // Clean up the publisher/receiver/session/connections.
+ // Clean up the publisher/receivers/session/connections.
close();
// Return any failed assertions to the caller.
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
index 9ce44305ad..0c24836b27 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
@@ -25,11 +25,18 @@ import junit.framework.TestCase;
import org.apache.log4j.NDC;
import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.Properties;
/**
* FrameworkBaseCase provides a starting point for writing test cases against the test framework. Its main purpose is
@@ -45,6 +52,42 @@ import java.util.List;
*/
public class FrameworkBaseCase extends TestCase
{
+ /** Holds the test sequencer to create and run test circuits with. */
+ protected TestCaseSequencer testSequencer = new DefaultTestSequencer();
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public FrameworkBaseCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Returns the test case sequencer that provides test circuit, and test sequence implementations. The sequencer
+ * that this base case returns by default is suitable for running a test circuit with both circuit ends colocated
+ * on the same JVM.
+ *
+ * @return The test case sequencer.
+ */
+ protected TestCaseSequencer getTestSequencer()
+ {
+ return testSequencer;
+ }
+
+ /**
+ * Overrides the default test sequencer. Test decorators can use this to supply distributed test sequencers or other
+ * test sequencer specializations.
+ *
+ * @param sequencer The new test sequencer.
+ */
+ public void setTestSequencer(TestCaseSequencer sequencer)
+ {
+ this.testSequencer = sequencer;
+ }
+
/**
* Creates a list of assertions.
*
@@ -133,4 +176,35 @@ public class FrameworkBaseCase extends TestCase
NDC.pop();
}
}
+
+ /**
+ * DefaultTestSequencer is a test sequencer that creates test circuits with publishing and receiving ends rooted
+ * on the same JVM.
+ */
+ public class DefaultTestSequencer implements TestCaseSequencer
+ {
+ /**
+ * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ * begining the test and gathering the test reports from the participants.
+ *
+ * @param testCircuit The test circuit.
+ * @param assertions The list of assertions to apply to the test circuit.
+ * @param testProperties The test case definition.
+ */
+ public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
+ {
+ assertNoFailures(testCircuit.test(1, assertions));
+ }
+
+ /**
+ * Creates a test circuit for the test, configered by the test parameters specified.
+ *
+ * @param testProperties The test parameters.
+ * @return A test circuit.
+ */
+ public Circuit createCircuit(ParsedProperties testProperties)
+ {
+ return CircuitImpl.createCircuit(testProperties);
+ }
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java b/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java
index 62229f3c72..3cc4a92886 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java
@@ -48,7 +48,7 @@ import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
* <tr><td> destinationCount <td> 1 <td> The number of receivers listening to the pings.
* <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
* <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
- * <tr><td> uniqueDests <td> true <td> Whether each receiver only listens to one ping destination or all.
+ * <tr><td> uniqueDests <td> true <td> Whether each receivers only listens to one ping destination or all.
* <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
* <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
* 0 - SESSION_TRANSACTED
@@ -81,12 +81,6 @@ public class MessagingTestConfigProperties
/** Defines the class to use as the initial context factory by default. */
public static final String INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
- /** 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";
@@ -125,16 +119,16 @@ public class MessagingTestConfigProperties
/** Holds the default value of the publisher consumer flag. */
public static final boolean PUBLISHER_CONSUMER_BIND_DEFAULT = false;
- /** Holds the name of the property to get the bind receiver procuder flag from. */
+ /** Holds the name of the property to get the bind receivers procuder flag from. */
public static final String RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind";
- /** Holds the default value of the receiver producer flag. */
+ /** Holds the default value of the receivers producer flag. */
public static final boolean RECEIVER_PRODUCER_BIND_DEFAULT = false;
- /** Holds the name of the property to get the bind receiver procuder flag from. */
+ /** Holds the name of the property to get the bind receivers procuder flag from. */
public static final String RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind";
- /** Holds the default value of the receiver consumer flag. */
+ /** Holds the default value of the receivers consumer flag. */
public static final boolean RECEIVER_CONSUMER_BIND_DEFAULT = true;
/** Holds the name of the property to get the destination name root from. */
@@ -275,7 +269,7 @@ public class MessagingTestConfigProperties
static
{
defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
- defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_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);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java b/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java
index a79e29ef67..6e01a7ea4f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java
@@ -22,27 +22,27 @@ package org.apache.qpid.test.framework;
/**
* A Receiver is a {@link CircuitEnd} that represents one end of a test circuit. Its main purpose is to
- * provide assertions that can be applied to test the behaviour of the receiver.
+ * provide assertions that can be applied to test the behaviour of the receivers.
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities
- * <tr><td> Provide assertion that the receiver received no exceptions.
- * <tr><td> Provide assertion that the receiver received all test messages sent to it.
+ * <tr><td> Provide assertion that the receivers received no exceptions.
+ * <tr><td> Provide assertion that the receivers received all test messages sent to it.
* </table>
*/
public interface Receiver extends CircuitEnd
{
/**
- * Provides an assertion that the receiver encountered no exceptions.
+ * Provides an assertion that the receivers encountered no exceptions.
*
- * @return An assertion that the receiver encountered no exceptions.
+ * @return An assertion that the receivers encountered no exceptions.
*/
public Assertion noExceptionsAssertion();
/**
- * Provides an assertion that the receiver got all messages that were sent to it.
+ * Provides an assertion that the receivers got all messages that were sent to it.
*
- * @return An assertion that the receiver got all messages that were sent to it.
+ * @return An assertion that the receivers got all messages that were sent to it.
*/
public Assertion allMessagesAssertion();
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java
index 06ca8e8cc3..ce783ed9e0 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java
@@ -32,8 +32,8 @@ import javax.jms.Session;
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Provide a message producer for sending messages.
* <tr><td> Provide a message consumer for receiving messages.
- * <tr><td> Provide assertion that the receiver received no exceptions.
- * <tr><td> Provide assertion that the receiver received all test messages sent to it.
+ * <tr><td> Provide assertion that the receivers received no exceptions.
+ * <tr><td> Provide assertion that the receivers received all test messages sent to it.
* </table>
*/
public class ReceiverImpl extends CircuitEndBase implements Receiver
@@ -54,9 +54,9 @@ public class ReceiverImpl extends CircuitEndBase implements Receiver
}
/**
- * Provides an assertion that the receiver encountered no exceptions.
+ * Provides an assertion that the receivers encountered no exceptions.
*
- * @return An assertion that the receiver encountered no exceptions.
+ * @return An assertion that the receivers encountered no exceptions.
*/
public Assertion noExceptionsAssertion()
{
@@ -64,9 +64,9 @@ public class ReceiverImpl extends CircuitEndBase implements Receiver
}
/**
- * Provides an assertion that the receiver got all messages that were sent to it.
+ * Provides an assertion that the receivers got all messages that were sent to it.
*
- * @return An assertion that the receiver got all messages that were sent to it.
+ * @return An assertion that the receivers got all messages that were sent to it.
*/
public Assertion allMessagesAssertion()
{
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java
index c3d68ce66c..8b3e72ef08 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.test.framework;
+import org.apache.log4j.Logger;
+
import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
@@ -27,10 +29,14 @@ import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
+import javax.jms.Message;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
+import java.util.Properties;
+import java.util.Map;
+
/**
* TestUtils provides static helper methods that are usefull for writing tests against QPid.
*
@@ -42,18 +48,34 @@ import javax.naming.NamingException;
*/
public class TestUtils
{
+ /** Used for debugging. */
+ private static Logger log = Logger.getLogger(TestUtils.class);
+
/**
- * Establishes a JMS connection using a properties file and qpids built in JNDI implementation. This is a simple
- * convenience method for code that does anticipate handling connection failures. All exceptions that indicate
- * that the connection has failed, are wrapped as rutime exceptions, preumably handled by a top level failure
+ * Establishes a JMS connection using a set of properties and qpids built in JNDI implementation. This is a simple
+ * convenience method for code that does not anticipate handling connection failures. All exceptions that indicate
+ * that the connection has failed, are wrapped as rutime exceptions, presumably handled by a top level failure
* handler.
*
+ * <p/>This utility makes use of the following test parameters from {@link MessagingTestConfigProperties} to control
+ * the connection creation:
+ *
+ * <p/><table>
+ * <tr><td> {@link MessagingTestConfigProperties#USERNAME_PROPNAME} <td> The username.
+ * <tr><td> {@link MessagingTestConfigProperties#PASSWORD_PROPNAME} <td> The password.
+ * <tr><td> {@link MessagingTestConfigProperties#VIRTUAL_HOST_PROPNAME} <td> The virtual host name.
+ * <tr><td> {@link MessagingTestConfigProperties#BROKER_PROPNAME} <td> The broker URL.
+ * <tr><td> {@link MessagingTestConfigProperties#CONNECTION_NAME} <td> The broker name in the initial context.
+ *
* @param messagingProps Connection properties as defined in {@link MessagingTestConfigProperties}.
*
* @return A JMS conneciton.
*/
public static Connection createConnection(ParsedProperties messagingProps)
{
+ log.debug("public static Connection createConnection(ParsedProperties messagingProps = " + messagingProps
+ + "): called");
+
try
{
// Extract the configured connection properties from the test configuration.
@@ -62,12 +84,14 @@ public class TestUtils
String virtualHost = messagingProps.getProperty(VIRTUAL_HOST_PROPNAME);
String brokerUrl = messagingProps.getProperty(BROKER_PROPNAME);
- // Set up the broker connection url.
+ // Create the broker connection url.
String connectionString =
- "amqp://" + conUsername + ":" + conPassword + "/" + ((virtualHost != null) ? virtualHost : "")
+ "amqp://" + conUsername + ":" + conPassword + "@clientid/" + ((virtualHost != null) ? virtualHost : "")
+ "?brokerlist='" + brokerUrl + "'";
- // messagingProps.setProperty(CONNECTION_PROPNAME, connectionString);
+ // Create properties to create the initial context from, and inject the connection factory configuration
+ // for the defined connection name into it.
+ messagingProps.setProperty("connectionfactory." + CONNECTION_NAME, connectionString);
Context ctx = new InitialContext(messagingProps);
@@ -108,4 +132,25 @@ public class TestUtils
throw new RuntimeException("Failed to generate the requested pause length.", e);
}
}
+
+ /**
+ * Sets properties of different types on a JMS Message.
+ *
+ * @param message The message to set properties on.
+ * @param properties The property name/value pairs to set.
+ *
+ * @throws javax.jms.JMSException All underlying JMSExceptions are allowed to fall through.
+ *
+ * @todo Move this helper method somewhere else. For example, TestUtils.
+ */
+ public static void setPropertiesOnMessage(Message message, Map<Object, Object> properties) throws JMSException
+ {
+ for (Map.Entry<Object, Object> entry : properties.entrySet())
+ {
+ String name = entry.getKey().toString();
+ Object value = entry.getValue();
+
+ message.setObjectProperty(name, value);
+ }
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/util/ClasspathScanner.java b/java/systests/src/main/java/org/apache/qpid/util/ClasspathScanner.java
new file mode 100644
index 0000000000..bad49060ca
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/util/ClasspathScanner.java
@@ -0,0 +1,234 @@
+/*
+ *
+ * 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.util;
+
+import java.io.File;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+
+/**
+ * An ClasspathScanner scans the classpath for classes that implement an interface or extend a base class and have names
+ * that match a regular expression.
+ *
+ * <p/>In order to test whether a class implements an interface or extends a class, the class must be loaded (unless
+ * the class files were to be scanned directly). Using this collector can cause problems when it scans the classpath,
+ * because loading classes will initialize their statics, which in turn may cause undesired side effects. For this
+ * reason, the collector should always be used with a regular expression, through which the class file names are
+ * filtered, and only those that pass this filter will be tested. For example, if you define tests in classes that
+ * end with the keyword "Test" then use the regular expression "Test$" to match this.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Find all classes matching type and name pattern on the classpath.
+ * </table>
+ *
+ * @todo Add logic to scan jars as well as directories.
+ */
+public class ClasspathScanner
+{
+ private static final Logger log = Logger.getLogger(ClasspathScanner.class);
+
+ /**
+ * Scans the classpath and returns all classes that extend a specified class and match a specified name.
+ * There is an flag that can be used to indicate that only Java Beans will be matched (that is, only those classes
+ * that have a default constructor).
+ *
+ * @param matchingClass The class or interface to match.
+ * @param matchingRegexp The regular expression to match against the class name.
+ * @param beanOnly Flag to indicate that onyl classes with default constructors should be matched.
+ *
+ * @return All the classes that match this collector.
+ */
+ public static <T> Collection<Class<? extends T>> getMatches(Class<T> matchingClass, String matchingRegexp,
+ boolean beanOnly)
+ {
+ log.debug("public static <T> Collection<Class<? extends T>> getMatches(Class<T> matchingClass = " + matchingClass
+ + ", String matchingRegexp = " + matchingRegexp + ", boolean beanOnly = " + beanOnly + "): called");
+
+ // Build a compiled regular expression from the pattern to match.
+ Pattern matchPattern = Pattern.compile(matchingRegexp);
+
+ String classPath = System.getProperty("java.class.path");
+ Map<String, Class<? extends T>> result = new HashMap<String, Class<? extends T>>();
+
+ log.debug("classPath = " + classPath);
+
+ // Find matching classes starting from all roots in the classpath.
+ for (String path : splitClassPath(classPath))
+ {
+ gatherFiles(new File(path), "", result, matchPattern, matchingClass);
+ }
+
+ return result.values();
+ }
+
+ /**
+ * Finds all matching classes rooted at a given location in the file system. If location is a directory it
+ * is recursively examined.
+ *
+ * @param classRoot The root of the current point in the file system being examined.
+ * @param classFileName The name of the current file or directory to examine.
+ * @param result The accumulated mapping from class names to classes that match the scan.
+ *
+ * @todo Recursion ok as file system depth is not likely to exhaust the stack. Might be better to replace with
+ * iteration.
+ */
+ private static <T> void gatherFiles(File classRoot, String classFileName, Map<String, Class<? extends T>> result,
+ Pattern matchPattern, Class<? extends T> matchClass)
+ {
+ log.debug("private static <T> void gatherFiles(File classRoot = " + classRoot + ", String classFileName = "
+ + classFileName + ", Map<String, Class<? extends T>> result, Pattern matchPattern = " + matchPattern
+ + ", Class<? extends T> matchClass = " + matchClass + "): called");
+
+ File thisRoot = new File(classRoot, classFileName);
+
+ // If the current location is a file, check if it is a matching class.
+ if (thisRoot.isFile())
+ {
+ // Check that the file has a matching name.
+ if (matchesName(thisRoot.getName(), matchPattern))
+ {
+ String className = classNameFromFile(thisRoot.getName());
+
+ // Check that the class has matching type.
+ try
+ {
+ Class<?> candidateClass = Class.forName(className);
+
+ Class matchedClass = matchesClass(candidateClass, matchClass);
+
+ if (matchedClass != null)
+ {
+ result.put(className, matchedClass);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // Ignore this. The matching class could not be loaded.
+ log.debug("Got ClassNotFoundException, ignoring.", e);
+ }
+ }
+
+ return;
+ }
+ // Otherwise the current location is a directory, so examine all of its contents.
+ else
+ {
+ String[] contents = thisRoot.list();
+
+ if (contents != null)
+ {
+ for (String content : contents)
+ {
+ gatherFiles(classRoot, classFileName + File.separatorChar + content, result, matchPattern, matchClass);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the specified class file name corresponds to a class with name matching the specified regular expression.
+ *
+ * @param classFileName The class file name.
+ * @param matchPattern The regular expression pattern to match.
+ *
+ * @return <tt>true</tt> if the class name matches, <tt>false</tt> otherwise.
+ */
+ private static boolean matchesName(String classFileName, Pattern matchPattern)
+ {
+ String className = classNameFromFile(classFileName);
+ Matcher matcher = matchPattern.matcher(className);
+
+ return matcher.matches();
+ }
+
+ /**
+ * Checks if the specified class to compare extends the base class being scanned for.
+ *
+ * @param matchingClass The base class to match against.
+ * @param toMatch The class to match against the base class.
+ *
+ * @return The class to check, cast as an instance of the class to match if the class extends the base class, or
+ * <tt>null</tt> otherwise.
+ */
+ private static <T> Class<? extends T> matchesClass(Class<?> matchingClass, Class<? extends T> toMatch)
+ {
+ try
+ {
+ return matchingClass.asSubclass(toMatch);
+ }
+ catch (ClassCastException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Takes a classpath (which is a series of paths) and splits it into its component paths.
+ *
+ * @param classPath The classpath to split.
+ *
+ * @return A list of the component paths that make up the class path.
+ */
+ private static List<String> splitClassPath(String classPath)
+ {
+ List<String> result = new LinkedList<String>();
+ String separator = System.getProperty("path.separator");
+ StringTokenizer tokenizer = new StringTokenizer(classPath, separator);
+
+ while (tokenizer.hasMoreTokens())
+ {
+ result.add(tokenizer.nextToken());
+ }
+
+ return result;
+ }
+
+ /**
+ * Translates from the filename of a class to its fully qualified classname. Files are named using forward slash
+ * seperators and end in ".class", whereas fully qualified class names use "." sperators and no ".class" ending.
+ *
+ * @param classFileName The filename of the class to translate to a class name.
+ *
+ * @return The fully qualified class name.
+ */
+ private static String classNameFromFile(String classFileName)
+ {
+ log.debug("private static String classNameFromFile(String classFileName = " + classFileName + "): called");
+
+ // Remove the .class ending.
+ String s = classFileName.substring(0, classFileName.length() - ".class".length());
+
+ // Turn / seperators in . seperators.
+ String s2 = s.replace(File.separatorChar, '.');
+
+ // Knock off any leading . caused by a leading /.
+ if (s2.startsWith("."))
+ {
+ return s2.substring(1);
+ }
+
+ return s2;
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java b/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java
new file mode 100644
index 0000000000..0090bec3d0
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java
@@ -0,0 +1,479 @@
+/*
+ *
+ * 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.util;
+
+import org.apache.log4j.Logger;
+
+import javax.jms.*;
+
+import java.util.*;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * A conversation helper, uses a message correlation id pattern to match up sent and received messages as a conversation
+ * over JMS messaging. Incoming message traffic is divided up by correlation id. Each id has a queue (behaviour dependant
+ * on the queue implementation). Clients of this de-multiplexer can wait on messages, defined by message correlation ids.
+ *
+ * <p/>One use of this is as a conversation synchronizer where multiple threads are carrying out conversations over a
+ * multiplexed messaging route. This can be usefull, as JMS sessions are not multi-threaded. Setting up the conversation
+ * with synchronous queues will allow these threads to be written in a synchronous style, but with their execution order
+ * governed by the asynchronous message flow. For example, something like the following code could run a multi-threaded
+ * conversation (the conversation methods can be called many times in parallel):
+ *
+ * <p/><pre>
+ * class Initiator
+ * {
+ * ConversationHelper conversation = new ConversationHelper(connection, null,
+ * java.util.concurrent.LinkedBlockingQueue.class);
+ *
+ * initiateConversation()
+ * {
+ * try {
+ * // Exchange greetings.
+ * conversation.send(sendDestination, conversation.getSession().createTextMessage("Hello."));
+ * Message greeting = conversation.receive();
+ *
+ * // Exchange goodbyes.
+ * conversation.send(conversation.getSession().createTextMessage("Goodbye."));
+ * Message goodbye = conversation.receive();
+ * } finally {
+ * conversation.end();
+ * }
+ * }
+ * }
+ *
+ * class Responder
+ * {
+ * ConversationHelper conversation = new ConversationHelper(connection, receiveDestination,
+ * java.util.concurrent.LinkedBlockingQueue.class);
+ *
+ * respondToConversation()
+ * {
+ * try {
+ * // Exchange greetings.
+ * Message greeting = conversation.receive();
+ * conversation.send(conversation.getSession().createTextMessage("Hello."));
+ *
+ * // Exchange goodbyes.
+ * Message goodbye = conversation.receive();
+ * conversation.send(conversation.getSession().createTextMessage("Goodbye."));
+ * } finally {
+ * conversation.end();
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * <p/>Conversation correlation id's are generated on a per thread basis.
+ *
+ * <p/>The same session is shared amongst all conversations. Calls to send are therefore synchronized because JMS
+ * sessions are not multi-threaded.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><th> Associate messages to an ongoing conversation using correlation ids.
+ * <tr><td> Auto manage sessions for conversations.
+ * <tr><td> Store messages not in a conversation in dead letter box.
+ * </table>
+ */
+public class ConversationFactory
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(ConversationFactory.class);
+
+ /** Holds a map from correlation id's to queues. */
+ private Map<Long, BlockingQueue<Message>> idsToQueues = new HashMap<Long, BlockingQueue<Message>>();
+
+ /** Holds the connection over which the conversation is conducted. */
+ private Connection connection;
+
+ /** Holds the session over which the conversation is conduxted. */
+ private Session session;
+
+ /** The message consumer for incoming messages. */
+ MessageConsumer consumer;
+
+ /** The message producer for outgoing messages. */
+ MessageProducer producer;
+
+ /** The well-known or temporary destination to receive replies on. */
+ Destination receiveDestination;
+
+ /** Holds the queue implementation class for the reply queue. */
+ Class<? extends BlockingQueue> queueClass;
+
+ /** Used to hold any replies that are received outside of the context of a conversation. */
+ BlockingQueue<Message> deadLetterBox = new LinkedBlockingQueue<Message>();
+
+ /* Used to hold conversation state on a per thread basis. */
+ /*
+ ThreadLocal<Conversation> threadLocals =
+ new ThreadLocal<Conversation>()
+ {
+ protected Conversation initialValue()
+ {
+ Conversation settings = new Conversation();
+ settings.conversationId = conversationIdGenerator.getAndIncrement();
+
+ return settings;
+ }
+ };
+ */
+
+ /** Generates new coversation id's as needed. */
+ AtomicLong conversationIdGenerator = new AtomicLong();
+
+ /**
+ * Creates a conversation helper on the specified connection with the default sending destination, and listening
+ * to the specified receiving destination.
+ *
+ * @param connection The connection to build the conversation helper on.
+ * @param receiveDestination The destination to listen to for incoming messages. This may be null to use a temporary
+ * queue.
+ * @param queueClass The queue implementation class.
+ *
+ * @throws JMSException All underlying JMSExceptions are allowed to fall through.
+ */
+ public ConversationFactory(Connection connection, Destination receiveDestination,
+ Class<? extends BlockingQueue> queueClass) throws JMSException
+ {
+ log.debug("public ConversationFactory(Connection connection, Destination receiveDestination = " + receiveDestination
+ + ", Class<? extends BlockingQueue> queueClass = " + queueClass + "): called");
+
+ this.connection = connection;
+ this.queueClass = queueClass;
+
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Check if a well-known receive destination has been provided, or use a temporary queue if not.
+ this.receiveDestination = (receiveDestination != null) ? receiveDestination : session.createTemporaryQueue();
+
+ consumer = session.createConsumer(receiveDestination);
+ producer = session.createProducer(null);
+
+ consumer.setMessageListener(new Receiver());
+ }
+
+ /**
+ * Creates a new conversation context.
+ *
+ * @return A new conversation context.
+ */
+ public Conversation startConversation()
+ {
+ log.debug("public Conversation startConversation(): called");
+
+ Conversation conversation = new Conversation();
+ conversation.conversationId = conversationIdGenerator.getAndIncrement();
+
+ return conversation;
+ }
+
+ /**
+ * Ensures that the reply queue for a conversation exists.
+ *
+ * @param conversationId The conversation correlation id.
+ */
+ private void initQueueForId(long conversationId)
+ {
+ if (!idsToQueues.containsKey(conversationId))
+ {
+ idsToQueues.put(conversationId, ReflectionUtils.<BlockingQueue>newInstance(queueClass));
+ }
+ }
+
+ /**
+ * Clears the dead letter box, returning all messages that were in it.
+ *
+ * @return All messages in the dead letter box.
+ */
+ public Collection<Message> emptyDeadLetterBox()
+ {
+ log.debug("public Collection<Message> emptyDeadLetterBox(): called");
+
+ Collection<Message> result = new ArrayList<Message>();
+ deadLetterBox.drainTo(result);
+
+ return result;
+ }
+
+ /**
+ * Gets the session over which the conversation is conducted.
+ *
+ * @return The session over which the conversation is conducted.
+ */
+ public Session getSession()
+ {
+ // Conversation settings = threadLocals.get();
+
+ return session;
+ }
+
+ /**
+ * Used to hold a conversation context. This consists of a correlating id for the conversation, and a reply
+ * destination automatically updated to the last received reply-to destination.
+ */
+ public class Conversation
+ {
+ /** Holds the correlation id for the context. */
+ long conversationId;
+
+ /**
+ * Holds the send destination for the context. This will automatically be updated to the most recently received
+ * reply-to destination.
+ */
+ Destination sendDestination;
+
+ /**
+ * Sends a message to the default sending location. The correlation id of the message will be assigned by this
+ * method, overriding any previously set value.
+ *
+ * @param sendDestination The destination to send to. This may be null to use the last received reply-to
+ * destination.
+ * @param message The message to send.
+ *
+ * @throws JMSException All undelying JMSExceptions are allowed to fall through. This will also be thrown if no
+ * send destination is specified and there is no most recent reply-to destination available
+ * to use.
+ */
+ public void send(Destination sendDestination, Message message) throws JMSException
+ {
+ log.debug("public void send(Destination sendDestination = " + sendDestination + ", Message message = " + message
+ + "): called");
+
+ // Conversation settings = threadLocals.get();
+ // long conversationId = conversationId;
+ message.setJMSCorrelationID(Long.toString(conversationId));
+ message.setJMSReplyTo(receiveDestination);
+
+ // Ensure that the reply queue for this conversation exists.
+ initQueueForId(conversationId);
+
+ // Check if an overriding send to destination has been set or use the last reply-to if not.
+ Destination sendTo = null;
+
+ if (sendDestination != null)
+ {
+ sendTo = sendDestination;
+ }
+ else if (sendDestination != null)
+ {
+ sendTo = sendDestination;
+ }
+ else
+ {
+ throw new JMSException("The send destination was specified, and no most recent reply-to available to use.");
+ }
+
+ // Send the message.
+ synchronized (this)
+ {
+ producer.send(sendTo, message);
+ }
+ }
+
+ /**
+ * Gets the next message in an ongoing conversation. This method may block until such a message is received.
+ *
+ * @return The next incoming message in the conversation.
+ *
+ * @throws JMSException All undelying JMSExceptions are allowed to fall through. Thrown if the received message
+ * did not have its reply-to destination set up.
+ */
+ public Message receive() throws JMSException
+ {
+ log.debug("public Message receive(): called");
+
+ // Conversation settings = threadLocals.get();
+ // long conversationId = settings.conversationId;
+
+ // Ensure that the reply queue for this conversation exists.
+ initQueueForId(conversationId);
+
+ BlockingQueue<Message> queue = idsToQueues.get(conversationId);
+
+ try
+ {
+ Message result = queue.take();
+
+ // Keep the reply-to destination to send replies to.
+ sendDestination = result.getJMSReplyTo();
+
+ return result;
+ }
+ catch (InterruptedException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Gets many messages in an ongoing conversation. If a limit is specified, then once that many messages are
+ * received they will be returned. If a timeout is specified, then all messages up to the limit, received within
+ * that timespan will be returned. At least one of the message count or timeout should be set to a value of
+ * 1 or greater.
+ *
+ * @param num The number of messages to receive, or all if this is less than 1.
+ * @param timeout The timeout in milliseconds to receive the messages in, or forever if this is less than 1.
+ *
+ * @return All messages received within the count limit and the timeout.
+ *
+ * @throws JMSException All undelying JMSExceptions are allowed to fall through.
+ */
+ public Collection<Message> receiveAll(int num, long timeout) throws JMSException
+ {
+ log.debug("public Collection<Message> receiveAll(int num = " + num + ", long timeout = " + timeout
+ + "): called");
+
+ // Check that a timeout or message count was set.
+ if ((num < 1) && (timeout < 1))
+ {
+ throw new IllegalArgumentException("At least one of message count (num) or timeout must be set.");
+ }
+
+ // Ensure that the reply queue for this conversation exists.
+ initQueueForId(conversationId);
+ BlockingQueue<Message> queue = idsToQueues.get(conversationId);
+
+ // Used to collect the received messages in.
+ Collection<Message> result = new ArrayList<Message>();
+
+ // Used to indicate when the timeout or message count has expired.
+ boolean receiveMore = true;
+
+ int messageCount = 0;
+
+ // Receive messages until the timeout or message count expires.
+ do
+ {
+ try
+ {
+ Message next = null;
+
+ // Try to receive the message with a timeout if one has been set.
+ if (timeout > 0)
+ {
+ next = queue.poll(timeout, TimeUnit.MILLISECONDS);
+
+ // Check if the timeout expired, and stop receiving if so.
+ if (next == null)
+ {
+ receiveMore = false;
+ }
+ }
+ // Receive the message without a timeout.
+ else
+ {
+ next = queue.take();
+ }
+
+ // Increment the message count if a message was received.
+ messageCount += (next != null) ? 1 : 0;
+
+ // Check if all the requested messages were received, and stop receiving if so.
+ if ((num > 0) && (messageCount >= num))
+ {
+ receiveMore = false;
+ }
+
+ // Keep the reply-to destination to send replies to.
+ sendDestination = (next != null) ? next.getJMSReplyTo() : sendDestination;
+
+ if (next != null)
+ {
+ result.add(next);
+ }
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the threads interrupted status.
+ Thread.currentThread().interrupt();
+
+ // Stop receiving but return the messages received so far.
+ receiveMore = false;
+ }
+ }
+ while (receiveMore);
+
+ return result;
+ }
+
+ /**
+ * Completes the conversation. Any correlation id's pertaining to the conversation are no longer valid, and any
+ * incoming messages using them will go to the dead letter box.
+ */
+ public void end()
+ {
+ log.debug("public void end(): called");
+
+ // Ensure that the thread local for the current thread is cleaned up.
+ // Conversation settings = threadLocals.get();
+ // long conversationId = settings.conversationId;
+ // threadLocals.remove();
+
+ // Ensure that its queue is removed from the queue map.
+ BlockingQueue<Message> queue = idsToQueues.remove(conversationId);
+
+ // Move any outstanding messages on the threads conversation id into the dead letter box.
+ queue.drainTo(deadLetterBox);
+ }
+ }
+
+ /**
+ * Implements the message listener for this conversation handler.
+ */
+ protected class Receiver implements MessageListener
+ {
+ /**
+ * Handles all incoming messages in the ongoing conversations. These messages are split up by correaltion id
+ * and placed into queues.
+ *
+ * @param message The incoming message.
+ */
+ public void onMessage(Message message)
+ {
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ try
+ {
+ Long conversationId = Long.parseLong(message.getJMSCorrelationID());
+
+ // Find the converstaion queue to place the message on. If there is no conversation for the message id,
+ // the the dead letter box queue is used.
+ BlockingQueue<Message> queue = idsToQueues.get(conversationId);
+ queue = (queue == null) ? deadLetterBox : queue;
+
+ queue.put(message);
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (InterruptedException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}