summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ritchie <ritchiem@apache.org>2007-11-26 16:09:16 +0000
committerMartin Ritchie <ritchiem@apache.org>2007-11-26 16:09:16 +0000
commitcbc1a21d02c341b18e063452e6354e17ec8280be (patch)
tree5a6ce1af3cf2059781ab66a1b6c43e0e7fc82089
parente24bd58a2898749df9098a9d1d9c5b773e35b34e (diff)
downloadqpid-python-cbc1a21d02c341b18e063452e6354e17ec8280be.tar.gz
Merged revisions 597919-598104,598106-598323 via svnmerge from
https://svn.apache.org/repos/asf/incubator/qpid/branches/M2.1 ........ r598233 | rupertlssmith | 2007-11-26 11:38:27 +0000 (Mon, 26 Nov 2007) | 1 line Updated test framework to seperate JMS and AMQP specific test cases. Added configurable test decorators so that in vm connection can be injected at run time. ........ r598287 | rupertlssmith | 2007-11-26 14:28:46 +0000 (Mon, 26 Nov 2007) | 1 line Added tk test runner invocation to run framework tests on every build. ........ git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2.1.1@598328 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java (renamed from java/perftests/src/main/java/org/apache/qpid/perftests/QpidTestThroughputPerf.java)18
-rw-r--r--java/pom.xml20
-rw-r--r--java/systests/pom.xml52
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java54
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java11
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java51
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java109
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java168
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java315
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java268
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java112
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java40
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java48
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java35
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java47
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java17
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java60
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java (renamed from java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java)64
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java133
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java181
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java60
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java54
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java83
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java92
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java9
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java12
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java (renamed from java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java)61
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/testcases/MandatoryMessageTest.java (renamed from java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java)63
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java132
-rw-r--r--java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java2
36 files changed, 1901 insertions, 498 deletions
diff --git a/java/perftests/src/main/java/org/apache/qpid/perftests/QpidTestThroughputPerf.java b/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java
index 760d1c84a4..887479c032 100644
--- a/java/perftests/src/main/java/org/apache/qpid/perftests/QpidTestThroughputPerf.java
+++ b/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.perftests;
+package org.apache.qpid.test.testcases;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -40,9 +40,8 @@ import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
import java.util.LinkedList;
/**
- * QpidTestThroughputPerf runs a test over a {@link Circuit} controlled by the test parameters. It logs timings of
- * the time required to receive samples consisting of batches of messages. As the time samples is taken over a reasonable
- * sized message batch, it measures message throughput.
+ * MessageThroughputPerf runs a test over a {@link Circuit} controlled by the test parameters. It logs timings of
+ * the time required to receive samples consisting of batches of messages.
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
@@ -51,11 +50,14 @@ import java.util.LinkedList;
*
* @todo Check that all of the messages were sent. Check that the receiving end got the same number of messages as
* the publishing end.
+ *
+ * @todo Set this up to run with zero sized tests. Size zero means send forever. Continuous sending to be interrupted
+ * by completion of the test duration, or shutdown hook when the user presses Ctrl-C.
*/
-public class QpidTestThroughputPerf extends FrameworkBaseCase implements TimingControllerAware, TestThreadAware
+public class MessageThroughputPerf extends FrameworkBaseCase implements TimingControllerAware, TestThreadAware
{
/** Used for debugging. */
- private static final Logger log = Logger.getLogger(QpidTestThroughputPerf.class);
+ private static final Logger log = Logger.getLogger(MessageThroughputPerf.class);
/** Holds the timing controller, used to log test timings from self-timed tests. */
private TimingController timingController;
@@ -68,7 +70,7 @@ public class QpidTestThroughputPerf extends FrameworkBaseCase implements TimingC
*
* @param name The test case name.
*/
- public QpidTestThroughputPerf(String name)
+ public MessageThroughputPerf(String name)
{
super(name);
}
@@ -163,7 +165,7 @@ public class QpidTestThroughputPerf extends FrameworkBaseCase implements TimingC
// Build a new test suite
TestSuite suite = new TestSuite("Qpid Throughput Performance Tests");
- suite.addTest(new QpidTestThroughputPerf("testThroughput"));
+ suite.addTest(new MessageThroughputPerf("testThroughput"));
return suite;
}
diff --git a/java/pom.xml b/java/pom.xml
index 5efec51a60..42c539e320 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -399,7 +399,7 @@ under the License.
<plugin>
<groupId>uk.co.thebadgerset</groupId>
<artifactId>junit-toolkit-maven-plugin</artifactId>
- <version>0.6.1</version>
+ <version>0.7-SNAPSHOT</version>
</plugin>
@@ -547,7 +547,7 @@ under the License.
<dependency>
<groupId>uk.co.thebadgerset</groupId>
<artifactId>junit-toolkit</artifactId>
- <version>0.6.1</version>
+ <version>0.7-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
@@ -696,6 +696,14 @@ under the License.
<enabled>false</enabled>
</releases>
</repository>
+
+ <repository>
+ <id>junittoolkit.snapshots</id>
+ <url>http://junit-toolkit.svn.sourceforge.net/svnroot/junit-toolkit/snapshots/</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
</repositories>
<pluginRepositories>
@@ -717,6 +725,14 @@ under the License.
</snapshots>
</pluginRepository>
+ <pluginRepository>
+ <id>junittoolkit.plugin.snapshots</id>
+ <url>http://junit-toolkit.svn.sourceforge.net/svnroot/junit-toolkit/snapshots/</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+
</pluginRepositories>
<profiles>
diff --git a/java/systests/pom.xml b/java/systests/pom.xml
index 4b3dc40517..dc462e3925 100644
--- a/java/systests/pom.xml
+++ b/java/systests/pom.xml
@@ -82,9 +82,61 @@
<includes>
<include>**/*Test.class</include>
</includes>
+ <excludes>
+ <exclude>**/testcases/ImmediateMessageTest.class</exclude>
+ <exclude>**/testcases/MandatoryMessageTest.class</exclude>
+ <exclude>**/testcases/RollbackTest.class</exclude>
+ </excludes>
</configuration>
</plugin>
+ <!-- Runs the framework based tests against an in-vm broker. -->
+ <plugin>
+ <groupId>uk.co.thebadgerset</groupId>
+ <artifactId>junit-toolkit-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>framework_tests</id>
+ <phase>test</phase>
+
+ <configuration>
+ <systemproperties>
+ <property>
+ <name>log4j.configuration</name>
+ <value>${log4j.configuration}</value>
+ </property>
+ </systemproperties>
+
+ <testrunner>uk.co.thebadgerset.junit.extensions.TKTestRunner</testrunner>
+
+ <testrunneroptions>
+ <option>-X:decorators "org.apache.qpid.test.framework.qpid.InVMBrokerDecorator:org.apache.qpid.test.framework.qpid.AMQPFeatureDecorator"</option>
+ <option>-o</option>
+ <option>--csv</option>
+ </testrunneroptions>
+
+ <testrunnerproperties>
+ <property>
+ <name>notApplicableAssertion</name>
+ <value>warn</value>
+ </property>
+ </testrunnerproperties>
+
+ <commands>
+ <Immediate-Message-Test>-n Immediate-Test -s[1] org.apache.qpid.test.testcases.ImmediateMessageTest</Immediate-Message-Test>
+ <Mandatory-Message-Test>-n Mandatory-Test -s[1] org.apache.qpid.test.testcases.MandatoryMessageTest</Mandatory-Message-Test>
+ <Rollback-Test>-n Rollback-Test -s[1] org.apache.qpid.test.testcases.RollbackTest</Rollback-Test>
+ </commands>
+
+ </configuration>
+
+ <goals>
+ <goal>tktest</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
</plugins>
<!-- Include source files in built jar -->
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java b/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java
new file mode 100644
index 0000000000..a8f79ad59d
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+/**
+ * An AMQPPublisher represents the status of the publishing side of a test circuit that exposes AMQP specific features.
+ * Its provides additional assertions not available through the plain JMS {@link Publisher} interface.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Provide assertion that the publishers received a no consumers error code on every message.
+ * <tr><td> Provide assertion that the publishers received a no route error code on every message.
+ * </table>
+ */
+public interface AMQPPublisher extends Publisher
+{
+ /**
+ * Provides an assertion that the publisher got a no consumers exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no consumers exception on every message.
+ */
+ Assertion noConsumersAssertion(ParsedProperties testProps);
+
+ /**
+ * Provides an assertion that the publisher got a no rout exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no rout exception on every message.
+ */
+ Assertion noRouteAssertion(ParsedProperties testProps);
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java
index 251b216c45..b11650021c 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java
@@ -51,11 +51,14 @@ public class CircuitEndBase implements CircuitEnd
ExceptionMonitor exceptionMonitor;
/**
- * Creates a circuit end point on the specified producer, consumer and controlSession.
+ * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ * for messages and exceptions received by the circuit end.
*
- * @param producer The message producer for the circuit end point.
- * @param consumer The message consumer for the circuit end point.
- * @param session The controlSession for the circuit end point.
+ * @param producer The message producer for the circuit end point.
+ * @param consumer The message consumer for the circuit end point.
+ * @param session The controlSession for the circuit end point.
+ * @param messageMonitor The monitor to notify of all messages received by the circuit end.
+ * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end.
*/
public CircuitEndBase(MessageProducer producer, MessageConsumer consumer, Session session, MessageMonitor messageMonitor,
ExceptionMonitor exceptionMonitor)
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java b/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java
index 9f1207202e..e8f5f7c53b 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java
@@ -36,7 +36,7 @@ import java.util.List;
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Record all exceptions received. <td> {@link ExceptionListener}
+ * <tr><td> Record all exceptions received.
* </table>
*/
public class ExceptionMonitor implements ExceptionListener
@@ -45,7 +45,7 @@ public class ExceptionMonitor implements ExceptionListener
private final Logger log = Logger.getLogger(ExceptionMonitor.class);
/** Holds the received exceptions. */
- List<JMSException> exceptions = new ArrayList<JMSException>();
+ List<Exception> exceptions = new ArrayList<Exception>();
/**
* Receives incoming exceptions.
@@ -82,6 +82,8 @@ public class ExceptionMonitor implements ExceptionListener
/**
* Checks that exactly one exception, with a linked cause of the specified type, has been received.
*
+ * @param aClass The type of the linked cause.
+ *
* @return <tt>true</tt> if exactly one exception, with a linked cause of the specified type, been received,
* <tt>false</tt> otherwise.
*/
@@ -89,13 +91,18 @@ public class ExceptionMonitor implements ExceptionListener
{
if (exceptions.size() == 1)
{
- JMSException e = exceptions.get(0);
-
- Exception linkedCause = e.getLinkedException();
+ Exception e = exceptions.get(0);
- if ((linkedCause != null) && aClass.isInstance(linkedCause))
+ if (e instanceof JMSException)
{
- return true;
+ JMSException jmse = (JMSException) e;
+
+ Exception linkedCause = jmse.getLinkedException();
+
+ if ((linkedCause != null) && aClass.isInstance(linkedCause))
+ {
+ return true;
+ }
}
}
@@ -103,6 +110,32 @@ public class ExceptionMonitor implements ExceptionListener
}
/**
+ * Checks that at least one exception of the the specified type, has been received.
+ *
+ * @param exceptionClass The type of the exception.
+ *
+ * @return <tt>true</tt> if at least one exception of the specified type has been received, <tt>false</tt> otherwise.
+ */
+ public synchronized boolean assertExceptionOfType(Class exceptionClass)
+ {
+ // Start by assuming that the exception has no been received.
+ boolean passed = false;
+
+ // Scan all the exceptions for a match.
+ for (Exception e : exceptions)
+ {
+ if (exceptionClass.isInstance(e))
+ {
+ passed = true;
+
+ break;
+ }
+ }
+
+ return passed;
+ }
+
+ /**
* Reports the number of exceptions held by this monitor.
*
* @return The number of exceptions held by this monitor.
@@ -117,7 +150,7 @@ public class ExceptionMonitor implements ExceptionListener
*/
public synchronized void reset()
{
- exceptions = new ArrayList<JMSException>();
+ exceptions = new ArrayList<Exception>();
}
/**
@@ -130,7 +163,7 @@ public class ExceptionMonitor implements ExceptionListener
{
String result = "ExceptionMonitor: holds " + exceptions.size() + " exceptions.\n\n";
- for (JMSException ex : exceptions)
+ for (Exception ex : exceptions)
{
result += getStackTrace(ex) + "\n";
}
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 77bb7a5c52..3e80d48eb3 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
@@ -20,23 +20,15 @@
*/
package org.apache.qpid.test.framework;
-import junit.framework.TestCase;
-
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-import org.apache.qpid.util.ConversationFactory;
import uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
-import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
import java.util.ArrayList;
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
@@ -56,7 +48,7 @@ public class FrameworkBaseCase extends AsymptoticTestCase
private static final Logger log = Logger.getLogger(FrameworkBaseCase.class);
/** Holds the test sequencer to create and run test circuits with. */
- protected CircuitFactory circuitFactory = new DefaultCircuitFactory();
+ protected CircuitFactory circuitFactory = new LocalCircuitFactory();
/**
* Creates a new test case with the specified name.
@@ -116,7 +108,7 @@ public class FrameworkBaseCase extends AsymptoticTestCase
*
* @param asserts The list of failed assertions.
*/
- protected void assertNoFailures(List<Assertion> asserts)
+ protected static void assertNoFailures(List<Assertion> asserts)
{
log.debug("protected void assertNoFailures(List<Assertion> asserts = " + asserts + "): called");
@@ -140,7 +132,7 @@ public class FrameworkBaseCase extends AsymptoticTestCase
*
* @return The error message.
*/
- protected String assertionsToString(List<Assertion> asserts)
+ protected static String assertionsToString(List<Assertion> asserts)
{
String errorMessage = "";
@@ -160,9 +152,6 @@ public class FrameworkBaseCase extends AsymptoticTestCase
protected void setUp() throws Exception
{
NDC.push(getName());
-
- // Ensure that the in-vm broker is created.
- TransportConnection.createVMBroker(1);
}
/**
@@ -170,16 +159,7 @@ public class FrameworkBaseCase extends AsymptoticTestCase
*/
protected void tearDown()
{
- try
- {
- // Ensure that the in-vm broker is cleaned up so that the next test starts afresh.
- TransportConnection.killVMBroker(1);
- ApplicationRegistry.remove(1);
- }
- finally
- {
- NDC.pop();
- }
+ NDC.pop();
}
/**
@@ -196,85 +176,4 @@ public class FrameworkBaseCase extends AsymptoticTestCase
{
return methodName;
}
-
- /**
- * DefaultCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted
- * on the same JVM.
- */
- public class DefaultCircuitFactory implements CircuitFactory
- {
- /**
- * 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 LocalCircuitImpl.createCircuit(testProperties);
- }
-
- /**
- * 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)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * 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)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Supplies the sending test client.
- *
- * @return The sending test client.
- */
- public TestClientDetails getSender()
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Supplies the receiving test client.
- *
- * @return The receiving test client.
- */
- public List<TestClientDetails> getReceivers()
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * 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)
- {
- throw new RuntimeException("Not implemented.");
- }
- }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java
new file mode 100644
index 0000000000..dac826fd5e
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java
@@ -0,0 +1,168 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.test.framework.localcircuit.LocalAMQPPublisherImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+/**
+ * LocalAMQPCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted
+ * on the same JVM, allowing AMQP/Qpid specific options to be applied to the circuit.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * <tr><td> Construct test circuits the support AMQP specific options.
+ * </table>
+ */
+public class LocalAMQPCircuitFactory extends LocalCircuitFactory
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(LocalAMQPCircuitFactory.class);
+
+ /**
+ * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the publishing side of a test circuit.
+ *
+ * @throws javax.jms.JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageProducer producer =
+ props.getPublisherProducerBind()
+ ? ((props.getImmediate() | props.getMandatory())
+ ? ((AMQSession) session).createProducer(destination, props.getMandatory(), props.getImmediate())
+ : session.createProducer(destination)) : null;
+
+ MessageConsumer consumer =
+ props.getPublisherConsumerBind()
+ ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ connection.setExceptionListener(exceptionMonitor);
+
+ if (!props.getPublisherConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /**
+ * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the receiving side of a test circuit.
+ *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ MessageProducer producer =
+ props.getReceiverProducerBind()
+ ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageConsumer consumer =
+ props.getReceiverConsumerBind()
+ ? ((props.getDurableSubscription() && props.getPubsub())
+ ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+ : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ if (!props.getReceiverConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+ }
+
+ /**
+ * Creates a local {@link Publisher} from a {@link CircuitEnd}. The publisher implementation provides AMQP
+ * specific assertion methods, for testing beyond JMS.
+ *
+ * @param publisherEnd The publishing circuit end.
+ *
+ * @return A {@link Receiver}.
+ */
+ protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+ {
+ return new LocalAMQPPublisherImpl(publisherEnd);
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
new file mode 100644
index 0000000000..0744522535
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
@@ -0,0 +1,315 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalReceiverImpl;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * LocalCircuitFactory is a circuit factory that creates test circuits with publishing and receiving ends rooted
+ * on the same JVM. The ends of the circuit are presented as {@link Publisher} and {@link Receiver} interfaces, which
+ * in turn provide methods to apply assertions to the circuit. The creation of the circuit ends, and the presentation
+ * of the ends as publisher/receiver interfaces, are designed to be overriden, so that circuits and assertions that
+ * use messaging features not available in JMS can be written. This provides an extension point for writing tests
+ * against proprietary features of JMS implementations.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * </table>
+ */
+public class LocalCircuitFactory implements CircuitFactory
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(LocalCircuitFactory.class);
+
+ /** Used to create unique destination names for each test. */
+ protected static AtomicLong uniqueDestsId = new AtomicLong();
+
+ /**
+ * 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)
+ {
+ FrameworkBaseCase.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)
+ {
+ Circuit result;
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+ // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
+ try
+ {
+ // Get a unique offset to append to destination names to make them unique to the connection.
+ long uniqueId = uniqueDestsId.incrementAndGet();
+
+ // Set up the connection.
+ Connection connection = TestUtils.createConnection(testProperties);
+
+ // Add the connection exception listener to assert on exception conditions with.
+ // ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ // connection.setExceptionListener(exceptionMonitor);
+
+ // Set up the publisher.
+ CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, props, uniqueId);
+
+ // Set up the receiver.
+ CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, props, uniqueId);
+
+ // Start listening for incoming messages.
+ connection.start();
+
+ // Package everything up.
+ LocalPublisherImpl publisher = createPublisherFromCircuitEnd(publisherEnd);
+ LocalReceiverImpl receiver = createReceiverFromCircuitEnd(receiverEnd);
+
+ result = new LocalCircuitImpl(testProperties, publisher, receiver, connection, publisher.getExceptionMonitor());
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
+ }
+
+ return result;
+ }
+
+ /**
+ * Creates a local {@link Receiver} from a {@link CircuitEnd}. Sub-classes may override this to provide more
+ * specialized receivers if necessary.
+ *
+ * @param receiverEnd The receiving circuit end.
+ *
+ * @return A {@link Receiver}.
+ */
+ protected LocalReceiverImpl createReceiverFromCircuitEnd(CircuitEndBase receiverEnd)
+ {
+ return new LocalReceiverImpl(receiverEnd);
+ }
+
+ /**
+ * Creates a local {@link Publisher} from a {@link CircuitEnd}. Sub-classes may override this to provide more
+ * specialized receivers if necessary.
+ *
+ * @param publisherEnd The publishing circuit end.
+ *
+ * @return A {@link Receiver}.
+ */
+ protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+ {
+ return new LocalPublisherImpl(publisherEnd);
+ }
+
+ /**
+ * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the publishing side of a test circuit.
+ *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (props.getImmediate() || props.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageProducer producer = props.getPublisherProducerBind() ? session.createProducer(destination) : null;
+
+ MessageConsumer consumer =
+ props.getPublisherConsumerBind()
+ ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ connection.setExceptionListener(exceptionMonitor);
+
+ if (!props.getPublisherConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /**
+ * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the receiving side of a test circuit.
+ *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (props.getImmediate() || props.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ MessageProducer producer =
+ props.getReceiverProducerBind()
+ ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageConsumer consumer =
+ props.getReceiverConsumerBind()
+ ? ((props.getDurableSubscription() && props.getPubsub())
+ ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+ : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ if (!props.getReceiverConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+ }
+
+ /**
+ * 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)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * 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)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Supplies the sending test client.
+ *
+ * @return The sending test client.
+ */
+ public TestClientDetails getSender()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Supplies the receiving test client.
+ *
+ * @return The receiving test client.
+ */
+ public List<TestClientDetails> getReceivers()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * 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)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+}
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 f6664a78d9..2c0f39d54c 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
@@ -20,10 +20,10 @@
*/
package org.apache.qpid.test.framework;
-import org.apache.qpid.jms.Session;
-
import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+import javax.jms.Session;
+
import java.util.Properties;
/**
@@ -181,10 +181,16 @@ public class MessagingTestConfigProperties extends ParsedProperties
public static final boolean PERSISTENT_MODE_DEFAULT = false;
/** Holds the name of the property to get the test transactional mode from. */
- public static final String TRANSACTED_PROPNAME = "transacted";
+ public static final String TRANSACTED_PUBLISHER_PROPNAME = "transactedPublisher";
+
+ /** Holds the transactional mode to use for the test. */
+ public static final boolean TRANSACTED_PUBLISHER_DEFAULT = false;
+
+ /** Holds the name of the property to get the test transactional mode from. */
+ public static final String TRANSACTED_RECEIVER_PROPNAME = "transactedReceiver";
/** Holds the transactional mode to use for the test. */
- public static final boolean TRANSACTED_DEFAULT = false;
+ public static final boolean TRANSACTED_RECEIVER_DEFAULT = false;
/** Holds the name of the property to set the no local flag from. */
public static final String NO_LOCAL_PROPNAME = "noLocal";
@@ -204,7 +210,7 @@ public class MessagingTestConfigProperties extends ParsedProperties
/** Defines the default value of the durable subscriptions flag. */
public static final boolean DURABLE_SUBSCRIPTION_DEFAULT = false;
- // ====================== Qpid Options and Flags ================================
+ // ====================== Qpid/AMQP Options and Flags ================================
/** Holds the name of the property to set the exclusive flag from. */
public static final String EXCLUSIVE_PROPNAME = "exclusive";
@@ -230,7 +236,7 @@ public class MessagingTestConfigProperties extends ParsedProperties
/** Default value for the durable destinations flag. */
public static final boolean DURABLE_DESTS_DEFAULT = false;
- /** Holds the name of the proeprty to set the prefetch size from. */
+ /** Holds the name of the property to set the prefetch size from. */
public static final String PREFETCH_PROPNAME = "prefetch";
/** Defines the default prefetch size to use when consuming messages. */
@@ -274,6 +280,26 @@ public class MessagingTestConfigProperties extends ParsedProperties
/** Defines the default maximum quantity of pending message data to allow producers to hold. */
public static final int MAX_PENDING_DEFAULT = 0;
+ /** Holds the name of the property to get the publisher rollback flag from. */
+ public static final String ROLLBACK_PUBLISHER_PROPNAME = "rollbackPublisher";
+
+ /** Holds the default publisher roll back setting. */
+ public static final boolean ROLLBACK_PUBLISHER_DEFAULT = false;
+
+ /** Holds the name of the property to get the publisher rollback flag from. */
+ public static final String ROLLBACK_RECEIVER_PROPNAME = "rollbackReceiver";
+
+ /** Holds the default publisher roll back setting. */
+ public static final boolean ROLLBACK_RECEIVER_DEFAULT = false;
+
+ // ====================== Options that control the bahviour of the test framework. =========================
+
+ /** Holds the name of the property to get the behavioural mode of not applicable assertions. */
+ public static final String NOT_APPLICABLE_ASSERTION_PROPNAME = "notApplicableAssertion";
+
+ /** Holds the default behavioral mode of not applicable assertions, which is logging them as a warning. */
+ public static final String NOT_APPLICABLE_ASSERTION_DEFAULT = "warn";
+
/** Holds the name of the property to get the verbose mode proeprty from. */
public static final String VERBOSE_PROPNAME = "verbose";
@@ -286,8 +312,11 @@ public class MessagingTestConfigProperties extends ParsedProperties
static
{
defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
- // defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_DEFAULT);
- defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+ defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
+ defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+ defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
+ defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+
defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT);
@@ -296,28 +325,33 @@ public class MessagingTestConfigProperties extends ParsedProperties
defaults.setPropertyIfNull(RECEIVER_CONSUMER_ACTIVE_PROPNAME, RECEIVER_CONSUMER_ACTIVE_DEFAULT);
defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT);
defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
- defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
- defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT);
- defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
- defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
- defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
- defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
- defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
- defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
- defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
- defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
- defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
- defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
- defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
+
+ defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_PUBLISHER_PROPNAME, TRANSACTED_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_RECEIVER_PROPNAME, TRANSACTED_RECEIVER_DEFAULT);
+ defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
- defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
- defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT);
- defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
+
defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT);
+
+ defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+ defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
+ defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
+ defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
+ defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
+ defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_PUBLISHER_PROPNAME, ROLLBACK_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_RECEIVER_PROPNAME, ROLLBACK_RECEIVER_DEFAULT);
+
+ defaults.setPropertyIfNull(NOT_APPLICABLE_ASSERTION_PROPNAME, NOT_APPLICABLE_ASSERTION_DEFAULT);
+ defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
}
/**
@@ -338,148 +372,314 @@ public class MessagingTestConfigProperties extends ParsedProperties
super(properties);
}
+ /**
+ * The size of test messages to send.
+ *
+ * @return The size of test messages to send.
+ */
public int getMessageSize()
{
return getPropertyAsInteger(MESSAGE_SIZE_PROPNAME);
}
+ /**
+ * Flag to indicate that the publishing producer should be set up to publish to a destination.
+ *
+ * @return Flag to indicate that the publishing producer should be set up to publish to a destination.
+ */
public boolean getPublisherProducerBind()
{
return getPropertyAsBoolean(PUBLISHER_PRODUCER_BIND_PROPNAME);
}
+ /**
+ * Flag to indicate that the publishing consumer should be set up to receive from a destination.
+ *
+ * @return Flag to indicate that the publishing consumer should be set up to receive from a destination.
+ */
public boolean getPublisherConsumerBind()
{
return getPropertyAsBoolean(PUBLISHER_CONSUMER_BIND_PROPNAME);
}
+ /**
+ * Flag to indicate that the receiving producer should be set up to publish to a destination.
+ *
+ * @return Flag to indicate that the receiving producer should be set up to publish to a destination.
+ */
public boolean getReceiverProducerBind()
{
return getPropertyAsBoolean(RECEIVER_PRODUCER_BIND_PROPNAME);
}
+ /**
+ * Flag to indicate that the receiving consumer should be set up to receive from a destination.
+ *
+ * @return Flag to indicate that the receiving consumer should be set up to receive from a destination.
+ */
public boolean getReceiverConsumerBind()
{
return getPropertyAsBoolean(RECEIVER_CONSUMER_BIND_PROPNAME);
}
+ /**
+ * Flag to indicate that the publishing consumer should be created and actively listening.
+ *
+ * @return Flag to indicate that the publishing consumer should be created.
+ */
public boolean getPublisherConsumerActive()
{
return getPropertyAsBoolean(PUBLISHER_CONSUMER_ACTIVE_PROPNAME);
}
+ /**
+ * Flag to indicate that the receiving consumers should be created and actively listening.
+ *
+ * @return Flag to indicate that the receiving consumers should be created and actively listening.
+ */
public boolean getReceiverConsumerActive()
{
return getPropertyAsBoolean(RECEIVER_CONSUMER_ACTIVE_PROPNAME);
}
+ /**
+ * A root to create all test destination names from.
+ *
+ * @return A root to create all test destination names from.
+ */
public String getSendDestinationNameRoot()
{
return getProperty(SEND_DESTINATION_NAME_ROOT_PROPNAME);
}
+ /**
+ * A root to create all receiving destination names from.
+ *
+ * @return A root to create all receiving destination names from.
+ */
public String getReceiveDestinationNameRoot()
{
return getProperty(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME);
}
+ /**
+ * Flag to indicate that persistent messages should be used.
+ *
+ * @return Flag to indicate that persistent messages should be used.
+ */
public boolean getPersistentMode()
{
return getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME);
}
- public boolean getTransacted()
+ /**
+ * Flag to indicate that transactional messages should be sent by the publisher.
+ *
+ * @return Flag to indicate that transactional messages should be sent by the publisher.
+ */
+ public boolean getPublisherTransacted()
{
- return getPropertyAsBoolean(TRANSACTED_PROPNAME);
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
}
- public String getBroker()
+ /**
+ * Flag to indicate that transactional receives should be used by the receiver.
+ *
+ * @return Flag to indicate that transactional receives should be used by the receiver.
+ */
+ public boolean getReceiverTransacted()
{
- return getProperty(BROKER_PROPNAME);
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
}
+ /**
+ * The name of the virtual host to run all tests over.
+ *
+ * @return The name of the virtual host to run all tests over.
+ */
public String getVirtualHost()
{
return getProperty(VIRTUAL_HOST_PROPNAME);
}
+ /**
+ * Limiting rate for each sender in messages per second, or zero for unlimited.
+ *
+ * @return Limiting rate for each sender in messages per second, or zero for unlimited.
+ */
public String getRate()
{
return getProperty(RATE_PROPNAME);
}
+ /**
+ * Flag to indicate that test messages should be received publish/subscribe style by all receivers.
+ *
+ * @return Flag to indicate that test messages should be received publish/subscribe style by all receivers.
+ */
public boolean getPubsub()
{
return getPropertyAsBoolean(PUBSUB_PROPNAME);
}
+ /**
+ * The username credentials to run tests with.
+ *
+ * @return The username credentials to run tests with.
+ */
public String getUsername()
{
return getProperty(USERNAME_PROPNAME);
}
+ /**
+ * The password credentials to run tests with.
+ *
+ * @return The password credentials to run tests with.
+ */
public String getPassword()
{
return getProperty(PASSWORD_PROPNAME);
}
- public int getDestinationCount()
- {
- return getPropertyAsInteger(DESTINATION_COUNT_PROPNAME);
- }
-
+ /**
+ * The timeout duration to fail tests on, should they receive no messages within it.
+ *
+ * @return The timeout duration to fail tests on, should they receive no messages within it.
+ */
public long getTimeout()
{
return getPropertyAsLong(TIMEOUT_PROPNAME);
}
+ /**
+ * The number of messages to batch into each transaction in transational tests.
+ *
+ * @return The number of messages to batch into each transaction in transational tests.
+ */
public int getTxBatchSize()
{
return getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME);
}
+ /**
+ * Flag to indicate that tests should use durable destinations.
+ *
+ * @return Flag to indicate that tests should use durable destinations.
+ */
public boolean getDurableDests()
{
return getPropertyAsBoolean(DURABLE_DESTS_PROPNAME);
}
+ /**
+ * The ack mode for message receivers to use.
+ *
+ * @return The ack mode for message receivers to use.
+ */
public int getAckMode()
{
return getPropertyAsInteger(ACK_MODE_PROPNAME);
}
+ /**
+ * Flag to indicate that tests should use durable subscriptions.
+ *
+ * @return Flag to indicate that tests should use durable subscriptions.
+ */
public boolean getDurableSubscription()
{
return getPropertyAsBoolean(DURABLE_SUBSCRIPTION_PROPNAME);
}
+ /**
+ * The maximum amount of in-flight data, in bytes, that tests should send at any time.
+ *
+ * @return The maximum amount of in-flight data, in bytes, that tests should send at any time.
+ */
public int getMaxPending()
{
return getPropertyAsInteger(MAX_PENDING_PROPNAME);
}
- public int getPrefecth()
+ /**
+ * The size of the prefetch queue to use.
+ *
+ * @return The size of the prefetch queue to use.
+ */
+ public int getPrefetch()
{
return getPropertyAsInteger(PREFETCH_PROPNAME);
}
+ /**
+ * Flag to indicate that subscriptions should be no-local.
+ *
+ * @return Flag to indicate that subscriptions should be no-local.
+ */
public boolean getNoLocal()
{
return getPropertyAsBoolean(NO_LOCAL_PROPNAME);
}
+ /**
+ * Flag to indicate that subscriptions should be exclusive.
+ *
+ * @return Flag to indicate that subscriptions should be exclusive.
+ */
public boolean getExclusive()
{
return getPropertyAsBoolean(EXCLUSIVE_PROPNAME);
}
+ /**
+ * Flag to indicate that messages must be delivered immediately.
+ *
+ * @return Flag to indicate that messages must be delivered immediately.
+ */
public boolean getImmediate()
{
return getPropertyAsBoolean(IMMEDIATE_PROPNAME);
}
+ /**
+ * Flag to indicate that messages must be routable.
+ *
+ * @return Flag to indicate that messages must be routable.
+ */
public boolean getMandatory()
{
return getPropertyAsBoolean(MANDATORY_PROPNAME);
}
+
+ /**
+ * Gets the value of a flag to indicate that the publisher should rollback all messages sent.
+ *
+ * @return A flag to indicate that the publisher should rollback all messages sent.
+ */
+ public boolean getRollbackPublisher()
+ {
+ return getPropertyAsBoolean(ROLLBACK_PUBLISHER_PROPNAME);
+ }
+
+ /**
+ * Gets the value of a flag to indicate that the receiver should rollback all messages received, then receive them
+ * again.
+ *
+ * @return A flag to indicate that the publisher should rollback all messages received.
+ */
+ public boolean getRollbackReceiver()
+ {
+ return getPropertyAsBoolean(ROLLBACK_RECEIVER_PROPNAME);
+ }
+
+ /**
+ * Gets the behavioural mode of not applicable assertions. Should be one of 'quiet', 'warn' or 'fail'.
+ *
+ * @return The behavioural mode of not applicable assertions.
+ */
+ public String getNotApplicableAssertionMode()
+ {
+ return getProperty(NOT_APPLICABLE_ASSERTION_PROPNAME);
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java b/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java
new file mode 100644
index 0000000000..c9bba54c51
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java
@@ -0,0 +1,112 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+/**
+ * NotApplicableAssertion is a messaging assertion that can be used when an assertion requested by a test-case is not
+ * applicable to the testing scenario. For example an assertion may relate to AMQP functionality, but a test case may be
+ * being run over a non-AMQP JMS implementation, in which case the request to create the assertion may return this
+ * instead of the proper assertion. The test framework is configurable to quietly drop these assertions, log them
+ * as warnings to the console, or raise them as test failures.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Quitely pass.
+ * <tr><td> Log a warning.
+ * <tr><td> Raise a test failure.
+ * </table>
+ */
+public class NotApplicableAssertion implements Assertion
+{
+ /** Used for logging to the console. */
+ private static final Logger console = Logger.getLogger("CONSOLE." + NotApplicableAssertion.class.getName());
+
+ /** The possible behavioural modes of this assertion. */
+ private enum Mode
+ {
+ /** Quietly ignore the assertion by passing. */
+ Quiet,
+
+ /** Ignore the assertion by passing but log a warning about it. */
+ Warn,
+
+ /** Fail the assertion. */
+ Fail;
+ }
+
+ /** The behavioural mode of the assertion. */
+ private Mode mode;
+
+ /**
+ * Creates an assertion that is driven by the value of the 'notApplicableAssertion' property of the test
+ * configuration. Its value should match one of 'quiet', 'warn' or 'fail' and if it does not it is automatically
+ * read as 'fail'.
+ *
+ * @param testProperties The test configuration properties.
+ */
+ public NotApplicableAssertion(ParsedProperties testProperties)
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+ String modeName = props.getNotApplicableAssertionMode();
+
+ if ("quiet".equals(modeName))
+ {
+ mode = Mode.Quiet;
+ }
+ else if ("warn".equals(modeName))
+ {
+ mode = Mode.Warn;
+ }
+ else
+ {
+ mode = Mode.Fail;
+ }
+ }
+
+ /**
+ * Applies the assertion.
+ *
+ * @return <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails.
+ */
+ public boolean apply()
+ {
+ switch (mode)
+ {
+ case Quiet:
+ return true;
+
+ case Warn:
+ console.warn("Warning: Not applicable assertion being ignored.");
+
+ return true;
+
+ case Fail:
+ default:
+ return false;
+ }
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java b/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java
index df35579533..418776b5cb 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java
@@ -20,37 +20,55 @@
*/
package org.apache.qpid.test.framework;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
/**
- * A Publisher is a {@link CircuitEnd} that represents the status of the publishing side of a test circuit. Its main
- * purpose is to provide assertions that can be applied to test the behaviour of the publishers.
+ * A Publisher represents the status of the publishing side of a test circuit. Its main purpose is to provide assertions
+ * that can be applied to test the behaviour of the publishers.
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities
* <tr><td> Provide assertion that the publishers received no exceptions.
- * <tr><td> Provide assertion that the publishers received a no consumers error code on every message.
- * <tr><td> Provide assertion that the publishers received a no route error code on every message.
* </table>
+ *
+ * @todo There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ * warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ * I am tempted to go with the dropping/warning/error approach, that would imply that it makes sense to pull
+ * the assertions back from AMQPPublisher to here.
*/
public interface Publisher
{
+ // Assertions that are meaningfull to AMQP and to JMS.
+
/**
* Provides an assertion that the publisher encountered no exceptions.
*
+ * @param testProps The test configuration properties.
+ *
* @return An assertion that the publisher encountered no exceptions.
*/
- public Assertion noExceptionsAssertion();
+ public Assertion noExceptionsAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to AMQP.
/**
- * Provides an assertion that the publisher got a no consumers exception on every message.
+ * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ *
+ * @param testProps The test configuration properties.
*
- * @return An assertion that the publisher got a no consumers exception on every message.
+ * @return An assertion that the AMQP channel was forcibly closed by an error condition.
*/
- public Assertion noConsumersAssertion();
+ public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to Java/JMS.
/**
- * Provides an assertion that the publisher got a no rout exception on every message.
+ * Provides an assertion that the publisher got a given exception during the test.
+ *
+ * @param testProps The test configuration properties.
+ * @param exceptionClass The exception class to check for.
*
- * @return An assertion that the publisher got a no rout exception on every message.
+ * @return An assertion that the publisher got a given exception during the test.
*/
- public Assertion noRouteAssertion();
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
}
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 e01b272d5a..4fd4ffeb48 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
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.test.framework;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
/**
* A Receiver is a {@link CircuitEnd} that represents the status of the receiving side of a test circuit. Its main
* purpose is to provide assertions that can be applied to check the behaviour of the receivers.
@@ -29,20 +31,62 @@ package org.apache.qpid.test.framework;
* <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>
+ *
+ * @todo There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ * warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ * I am tempted to go with the dropping/warning/error approach.
*/
public interface Receiver
{
+ // Assertions that are meaningfull to AMQP and to JMS.
+
/**
* Provides an assertion that the receivers encountered no exceptions.
*
+ * @param testProps The test configuration properties.
+ *
* @return An assertion that the receivers encountered no exceptions.
*/
- public Assertion noExceptionsAssertion();
+ public Assertion noExceptionsAssertion(ParsedProperties testProps);
/**
* Provides an assertion that the receivers got all messages that were sent to it.
*
+ * @param testProps The test configuration properties.
+ *
* @return An assertion that the receivers got all messages that were sent to it.
*/
- public Assertion allMessagesAssertion();
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps);
+
+ /**
+ * Provides an assertion that the receivers got none of the messages that were sent to it.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the receivers got none of the messages that were sent to it.
+ */
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to AMQP.
+
+ /**
+ * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the AMQP channel was forcibly closed by an error condition.
+ */
+ public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to Java/JMS.
+
+ /**
+ * Provides an assertion that the receiver got a given exception during the test.
+ *
+ * @param testProps The test configuration properties.
+ * @param exceptionClass The exception class to check for.
+ *
+ * @return An assertion that the receiver got a given exception during the test.
+ */
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
}
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 569eac425c..6ad6185ece 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
@@ -32,7 +32,6 @@ import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Map;
-import java.util.Properties;
/**
* TestUtils provides static helper methods that are usefull for writing tests against QPid.
@@ -40,7 +39,9 @@ import java.util.Properties;
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Create connections from test properties. <td> {@link MessagingTestConfigProperties}
+ * <tr><td> Create test messages.
* <tr><td> Inject a short pause in a test.
+ * <tr><td> Serialize properties into a message.
* </table>
*/
public class TestUtils
@@ -48,7 +49,8 @@ public class TestUtils
/** Used for debugging. */
private static Logger log = Logger.getLogger(TestUtils.class);
- private static byte[] MESSAGE_DATA_BYTES =
+ /** Some dummy data to stuff all test messages with. */
+ private static final byte[] MESSAGE_DATA_BYTES =
"Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- "
.getBytes();
@@ -118,7 +120,7 @@ public class TestUtils
*
* @return A bytes message, of the specified size, filled with dummy data.
*
- *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through.
*/
public static Message createTestMessageOfSize(Session session, int size) throws JMSException
{
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java
index b04ab0f9b0..86bddaf10d 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchFailureException.java
@@ -21,8 +21,8 @@
package org.apache.qpid.test.framework.clocksynch;
/**
- * ClockSynchFailureException represents failure of a {@link ClockSynchronizer} to achieve synchronization. This could
- * be because a reference signal is not available, or because a desired accurracy cannot be attained, for example.
+ * ClockSynchFailureException represents failure of a {@link ClockSynchronizer} to achieve synchronization. For example,
+ * this could be because a reference signal is not available, or because a desired accurracy cannot be attained.
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java
index d0fd16d715..610f4b75c3 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/clocksynch/ClockSynchronizer.java
@@ -32,7 +32,7 @@ package org.apache.qpid.test.framework.clocksynch;
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Trigger a clock synchronziation.
+ * <tr><td> Trigger a clock synchronization.
* <tr><td> Compute a clock delta to apply to the local clock.
* <tr><td> Estimate the error in the synchronzation.
* </table>
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java
index 9e3054964c..693fd854c7 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java
@@ -23,10 +23,17 @@ package org.apache.qpid.test.framework.distributedcircuit;
import org.apache.qpid.test.framework.Assertion;
import org.apache.qpid.test.framework.Publisher;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
/**
+ * DistributedPublisherImpl represents the status of the publishing side of a test circuit. Its main purpose is to
+ * provide assertions that can be applied to verify the behaviour of a non-local publisher.
+ *
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
+ * <tr><td> Provide assertion that the publishers received no exceptions.
+ * <tr><td> Provide assertion that the publishers received a no consumers error code on every message.
+ * <tr><td> Provide assertion that the publishers received a no route error code on every message.
* </table>
*/
public class DistributedPublisherImpl implements Publisher
@@ -35,8 +42,9 @@ public class DistributedPublisherImpl implements Publisher
* Provides an assertion that the publisher encountered no exceptions.
*
* @return An assertion that the publisher encountered no exceptions.
+ * @param testProps
*/
- public Assertion noExceptionsAssertion()
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
{
throw new RuntimeException("Not implemented.");
}
@@ -60,4 +68,27 @@ public class DistributedPublisherImpl implements Publisher
{
throw new RuntimeException("Not implemented.");
}
+
+ /**
+ * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ *
+ * @param testProps The test configuration properties.
+ * @return An assertion that the AMQP channel was forcibly closed by an error condition.
+ */
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Provides an assertion that the publisher got a given exception during the test.
+ *
+ * @param testProps The test configuration properties.
+ * @param exceptionClass The exception class to check for.
+ * @return An assertion that the publisher got a given exception during the test.
+ */
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java
index 4a77906448..14782ee5e2 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java
@@ -23,10 +23,16 @@ package org.apache.qpid.test.framework.distributedcircuit;
import org.apache.qpid.test.framework.Assertion;
import org.apache.qpid.test.framework.Receiver;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
/**
+ * DistributedReceiverImpl represents the status of the receiving side of a test circuit. Its main purpose is to
+ * provide assertions that can be applied to verify the behaviour of a non-local receiver.
+ *
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
+ * <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 DistributedReceiverImpl implements Receiver
@@ -35,8 +41,9 @@ public class DistributedReceiverImpl implements Receiver
* Provides an assertion that the receivers encountered no exceptions.
*
* @return An assertion that the receivers encountered no exceptions.
+ * @param testProps
*/
- public Assertion noExceptionsAssertion()
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
{
throw new RuntimeException("Not implemented.");
}
@@ -45,8 +52,42 @@ public class DistributedReceiverImpl implements Receiver
* Provides an assertion that the receivers got all messages that were sent to it.
*
* @return An assertion that the receivers got all messages that were sent to it.
+ * @param testProps
+ */
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Provides an assertion that the receivers got none of the messages that were sent to it.
+ *
+ * @return An assertion that the receivers got none of the messages that were sent to it.
+ * @param testProps
+ */
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ *
+ * @param testProps The test configuration properties.
+ * @return An assertion that the AMQP channel was forcibly closed by an error condition.
+ */
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Provides an assertion that the receiver got a given exception during the test.
+ *
+ * @param testProps
+ *@param exceptionClass The exception class to check for. @return An assertion that the receiver got a given exception during the test.
*/
- public Assertion allMessagesAssertion()
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass)
{
throw new RuntimeException("Not implemented.");
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java
index 621d16ec9b..845b0a39f6 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java
@@ -24,7 +24,6 @@ import org.apache.log4j.Logger;
import org.apache.qpid.test.framework.*;
import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
-import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
@@ -48,7 +47,15 @@ import javax.jms.*;
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
+ * <tr><td> Provide a message producer for sending messages.
+ * <td> {@link CircuitEnd}, {@link LocalCircuitFactory}, {@link TestUtils}
+ * <tr><td> Provide a message consumer for receiving messages.
+ * <td> {@link CircuitEnd}, {@link LocalCircuitFactory}, {@link TestUtils}
+ * <tr><td> Supply the name of the test case that this implements.
+ * <tr><td> Accept/Reject invites based on test parameters. <td> {@link MessagingTestConfigProperties}
+ * <tr><td> Adapt to assigned roles. <td> {@link TestClientControlledTest.Roles}
+ * <tr><td> Perform test case actions. <td> {@link MessageMonitor}
+ * <tr><td> Generate test reports. <td> {@link MessageMonitor}
* </table>
*/
public class TestClientCircuitEnd implements CircuitEnd, TestClientControlledTest
@@ -145,13 +152,15 @@ public class TestClientCircuitEnd implements CircuitEnd, TestClientControlledTes
connection = TestUtils.createConnection(testProps);
// Create a circuit end that matches the assigned role and test parameters.
+ LocalCircuitFactory circuitFactory = new LocalCircuitFactory();
+
switch (role)
{
// Check if the sender role is being assigned, and set up a message producer if so.
case SENDER:
// Set up the publisher.
- circuitEnd = LocalCircuitImpl.createPublisherCircuitEnd(connection, testProps, 0L);
+ circuitEnd = circuitFactory.createPublisherCircuitEnd(connection, testProps, 0L);
// Create a custom message monitor that will be updated on every message sent.
messageMonitor = new MessageMonitor();
@@ -162,7 +171,7 @@ public class TestClientCircuitEnd implements CircuitEnd, TestClientControlledTes
case RECEIVER:
// Set up the receiver.
- circuitEnd = LocalCircuitImpl.createReceiverCircuitEnd(connection, testProps, 0L);
+ circuitEnd = circuitFactory.createReceiverCircuitEnd(connection, testProps, 0L);
// Use the message monitor from the consumer for stats.
messageMonitor = getMessageMonitor();
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java
index 90a44e3b6b..1be2f338f7 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java
@@ -33,7 +33,6 @@ import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.TestUtils;
import org.apache.qpid.test.framework.clocksynch.UDPClockReference;
import org.apache.qpid.util.ConversationFactory;
-import org.apache.qpid.util.PrettyPrintingUtils;
import uk.co.thebadgerset.junit.extensions.TKTestRunner;
import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
@@ -56,7 +55,7 @@ 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 DistributedTestDecorator}
+ * <tr><td> Decorate available tests to run on all available clients. <td> {@link DistributedTestDecorator}
* <tr><td> Attach XML test result logger.
* <tr><td> Terminate the interop testing framework.
* </table>
@@ -64,8 +63,6 @@ import java.util.concurrent.LinkedBlockingQueue;
* @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.
- *
- * @todo Remove hard coding of test cases and put on command line instead.
*/
public class Coordinator extends TKTestRunner
{
@@ -119,27 +116,29 @@ public class Coordinator extends TKTestRunner
/**
* Creates an interop test coordinator on the specified broker and virtual host.
*
- * @param repetitions The number of times to repeat the test, or test batch size.
- * @param duration The length of time to run the tests for. -1 means no duration has been set.
- * @param threads The concurrency levels to ramp up to.
- * @param delay A delay in milliseconds between test runs.
- * @param params The sets of 'size' parameters to pass to test.
- * @param testCaseName The name of the test case to run.
- * @param reportDir The directory to output the test results to.
- * @param runName The name of the test run; used to name the output file.
- * @param verbose Whether to print comments during test run.
- * @param brokerUrl The URL of the broker to connect to.
- * @param virtualHost The virtual host to run all tests on. Optional, may be <tt>null</tt>.
- * @param engine The distributed test engine type to run the tests with.
- * @param terminate <tt>true</tt> if test client nodes should be terminated at the end of the tests.
- * @param csv <tt>true</tt> if the CSV results listener should be attached.
- * @param xml <tt>true</tt> if the XML results listener should be attached.
+ * @param repetitions The number of times to repeat the test, or test batch size.
+ * @param duration The length of time to run the tests for. -1 means no duration has been set.
+ * @param threads The concurrency levels to ramp up to.
+ * @param delay A delay in milliseconds between test runs.
+ * @param params The sets of 'size' parameters to pass to test.
+ * @param testCaseName The name of the test case to run.
+ * @param reportDir The directory to output the test results to.
+ * @param runName The name of the test run; used to name the output file.
+ * @param verbose Whether to print comments during test run.
+ * @param brokerUrl The URL of the broker to connect to.
+ * @param virtualHost The virtual host to run all tests on. Optional, may be <tt>null</tt>.
+ * @param engine The distributed test engine type to run the tests with.
+ * @param terminate <tt>true</tt> if test client nodes should be terminated at the end of the tests.
+ * @param csv <tt>true</tt> if the CSV results listener should be attached.
+ * @param xml <tt>true</tt> if the XML results listener should be attached.
+ * @param decoratorFactories List of factories for user specified decorators.
*/
public Coordinator(Integer repetitions, Long duration, int[] threads, int delay, int[] params, String testCaseName,
String reportDir, String runName, boolean verbose, String brokerUrl, String virtualHost, TestEngine engine,
- boolean terminate, boolean csv, boolean xml)
+ boolean terminate, boolean csv, boolean xml, List<TestDecoratorFactory> decoratorFactories)
{
- super(repetitions, duration, threads, delay, params, testCaseName, reportDir, runName, csv, xml, verbose);
+ super(repetitions, duration, threads, delay, params, testCaseName, reportDir, runName, csv, xml, verbose,
+ decoratorFactories);
log.debug("public Coordinator(Integer repetitions = " + repetitions + " , Long duration = " + duration
+ ", int[] threads = " + Arrays.toString(threads) + ", int delay = " + delay + ", int[] params = "
@@ -221,7 +220,11 @@ public class Coordinator extends TKTestRunner
},
{ "s", "The size parameter to run tests with.", "size", "false", MathUtils.SEQUENCE_REGEXP },
{ "v", "Verbose mode.", null, "false" },
- { "n", "A name for this test run, used to name the output file.", "name", "true" }
+ { "n", "A name for this test run, used to name the output file.", "name", "true" },
+ {
+ "X:decorators", "A list of additional test decorators to wrap the tests in.",
+ "\"class.name[:class.name]*\"", "false"
+ }
}), testContextProperties));
// Extract the command line options.
@@ -234,13 +237,13 @@ public class Coordinator extends TKTestRunner
boolean terminate = options.getPropertyAsBoolean("t");
boolean csvResults = options.getPropertyAsBoolean("-csv");
boolean xmlResults = options.getPropertyAsBoolean("-xml");
-
String threadsString = options.getProperty("c");
Integer repetitions = options.getPropertyAsInteger("r");
String durationString = options.getProperty("d");
String paramsString = options.getProperty("s");
boolean verbose = options.getPropertyAsBoolean("v");
String testRunName = options.getProperty("n");
+ String decorators = options.getProperty("X:decorators");
int[] threads = (threadsString == null) ? null : MathUtils.parseSequence(threadsString);
int[] params = (paramsString == null) ? null : MathUtils.parseSequence(paramsString);
@@ -253,6 +256,9 @@ public class Coordinator extends TKTestRunner
Collection<Class<? extends FrameworkBaseCase>> testCaseClasses =
new ArrayList<Class<? extends FrameworkBaseCase>>();
+ // Create a list of test decorator factories for use specified decorators to be applied.
+ List<TestDecoratorFactory> decoratorFactories = parseDecorators(decorators);
+
// Scan for available test cases using a classpath scanner.
// ClasspathScanner.getMatches(DistributedTestCase.class, "^Test.*", true);
@@ -306,7 +312,7 @@ public class Coordinator extends TKTestRunner
// Create a coordinator and begin its test procedure.
Coordinator coordinator =
new Coordinator(repetitions, duration, threads, 0, params, null, reportDir, testRunName, verbose, brokerUrl,
- virtualHost, engine, terminate, csvResults, xmlResults);
+ virtualHost, engine, terminate, csvResults, xmlResults, decoratorFactories);
TestResult testResult = coordinator.start(testClassNames);
@@ -339,8 +345,7 @@ public class Coordinator extends TKTestRunner
*/
public TestResult start(String[] testClassNames) throws Exception
{
- log.debug("public TestResult start(String[] testClassNames = " + PrettyPrintingUtils.printArray(testClassNames)
- + ": called");
+ log.debug("public TestResult start(String[] testClassNames = " + Arrays.toString(testClassNames) + ": called");
// Connect to the broker.
connection = TestUtils.createConnection(TestContextProperties.getInstance());
@@ -494,6 +499,9 @@ public class Coordinator extends TKTestRunner
log.debug("Wrapped with a WrappedSuiteTestDecorator.");
}
+ // Apply any optional user specified decorators.
+ targetTest = applyOptionalUserDecorators(targetTest);
+
// Wrap the tests in a suitable distributed test decorator, to perform the invite/test cycle.
targetTest = newTestDecorator(targetTest, enlistedClients, conversationFactory, connection);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java
index 918f0f9177..00285ab37e 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java
@@ -50,7 +50,7 @@ import java.util.*;
* <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 distributed test cases. <td> {@link FrameworkBaseCase}
- * <tr><td> Fail non participating pairings. <td> {@link OptOutTestCase}
+ * <tr><td> Fail non-participating pairings. <td> {@link OptOutTestCase}
* </table>
*/
public class InteropTestDecorator extends DistributedTestDecorator
diff --git a/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
index 8f0ef193ef..b011e52ca7 100644
--- a/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
@@ -23,17 +23,14 @@ package org.apache.qpid.test.framework.distributedtesting;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
-import org.apache.qpid.interop.clienttestcases.*;
-import org.apache.qpid.sustained.SustainedClientTestCase;
import org.apache.qpid.test.framework.MessagingTestConfigProperties;
import org.apache.qpid.test.framework.TestUtils;
import org.apache.qpid.test.framework.clocksynch.ClockSynchThread;
-import org.apache.qpid.test.framework.clocksynch.ClockSynchronizer;
import org.apache.qpid.test.framework.clocksynch.UDPClockSynchronizer;
-import org.apache.qpid.test.framework.distributedcircuit.TestClientCircuitEnd;
+import org.apache.qpid.util.ReflectionUtils;
+import org.apache.qpid.util.ReflectionUtilsException;
import uk.co.thebadgerset.junit.extensions.SleepThrottle;
-import uk.co.thebadgerset.junit.extensions.Throttle;
import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
@@ -46,7 +43,7 @@ import java.util.*;
* (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). A test client is an agent that
* reacts to control message sequences send by the test {@link Coordinator}.
*
- * <p/><table><caption>Messages Handled by SustainedTestClient</caption>
+ * <p/><table><caption>Messages Handled by TestClient</caption>
* <tr><th> Message <th> Action
* <tr><td> Invite(compulsory) <td> Reply with Enlist.
* <tr><td> Invite(test case) <td> Reply with Enlist if test case available.
@@ -115,19 +112,19 @@ public class TestClient implements MessageListener
* Creates a new interop test client, listenting to the specified broker and virtual host, with the specified client
* identifying name.
*
- * @param brokerUrl The url of the broker to connect to.
- * @param virtualHost The virtual host to conect to.
+ * @param pBrokerUrl The url of the broker to connect to.
+ * @param pVirtualHost The virtual host to conect to.
* @param clientName The client name to use.
* @param join Flag to indicate that this client should attempt to join running tests.
*/
- public TestClient(String brokerUrl, String virtualHost, String clientName, boolean join)
+ public TestClient(String pBrokerUrl, String pVirtualHost, String clientName, boolean join)
{
- log.debug("public TestClient(String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost
+ log.debug("public TestClient(String pBrokerUrl = " + pBrokerUrl + ", String pVirtualHost = " + pVirtualHost
+ ", String clientName = " + clientName + ", boolean join = " + join + "): called");
// Retain the connection parameters.
- this.brokerUrl = brokerUrl;
- this.virtualHost = virtualHost;
+ brokerUrl = pBrokerUrl;
+ virtualHost = pVirtualHost;
this.clientName = clientName;
this.join = join;
}
@@ -186,9 +183,12 @@ public class TestClient implements MessageListener
Collection<Class<? extends TestClientControlledTest>> testCaseClasses =
new ArrayList<Class<? extends TestClientControlledTest>>();
// ClasspathScanner.getMatches(TestClientControlledTest.class, "^TestCase.*", true);
- Collections.addAll(testCaseClasses, TestCase1DummyRun.class, TestCase2BasicP2P.class, TestCase3BasicPubSub.class,
- TestCase4P2PMessageSize.class, TestCase5PubSubMessageSize.class, SustainedClientTestCase.class,
- TestClientCircuitEnd.class);
+ testCaseClasses.addAll(loadTestCases("org.apache.qpid.interop.clienttestcases.TestCase1DummyRun",
+ "org.apache.qpid.interop.clienttestcases.TestCase2BasicP2P",
+ "org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub",
+ "org.apache.qpid.interop.clienttestcases.TestCase4P2PMessageSize",
+ "org.apache.qpid.interop.clienttestcases.TestCase5PubSubMessageSize",
+ "org.apache.qpid.test.framework.distributedcircuit.TestClientCircuitEnd"));
try
{
@@ -203,6 +203,40 @@ public class TestClient implements MessageListener
}
/**
+ * Parses a list of class names, and loads them if they are available on the class path.
+ *
+ * @param classNames The names of the classes to load.
+ *
+ * @return A list of the loaded test case classes.
+ */
+ public static List<Class<? extends TestClientControlledTest>> loadTestCases(String... classNames)
+ {
+ List<Class<? extends TestClientControlledTest>> testCases =
+ new LinkedList<Class<? extends TestClientControlledTest>>();
+
+ for (String className : classNames)
+ {
+ try
+ {
+ Class<?> cls = ReflectionUtils.forName(className);
+ testCases.add((Class<? extends TestClientControlledTest>) cls);
+ }
+ catch (ReflectionUtilsException e)
+ {
+ // Ignore, class could not be found, so test not available.
+ console.warn("Requested class " + className + " cannot be found, ignoring it.");
+ }
+ catch (ClassCastException e)
+ {
+ // Ignore, class was not of correct type to be a test case.
+ console.warn("Requested class " + className + " is not an instance of TestClientControlledTest.");
+ }
+ }
+
+ return testCases;
+ }
+
+ /**
* Starts the interop test client running. This causes it to start listening for incoming test invites.
*
* @param testCaseClasses The classes of the available test cases. The test case names from these are used to
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java
new file mode 100644
index 0000000000..44a807ed6d
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.localcircuit;
+
+import org.apache.qpid.client.AMQNoConsumersException;
+import org.apache.qpid.client.AMQNoRouteException;
+import org.apache.qpid.test.framework.*;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+/**
+ * LocalAMQPPublisherImpl is an extension of {@link LocalPublisherImpl} that adds AMQP specific features. Specifically
+ * extra assertions for AMQP features not available through generic JMS.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class LocalAMQPPublisherImpl extends LocalPublisherImpl implements AMQPPublisher
+{
+ /**
+ * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ * for messages and exceptions received by the circuit end.
+ *
+ * @param producer The message producer for the circuit end point.
+ * @param consumer The message consumer for the circuit end point.
+ * @param session The controlSession for the circuit end point.
+ * @param messageMonitor The monitor to notify of all messages received by the circuit end.
+ * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end.
+ */
+ public LocalAMQPPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session,
+ MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
+ {
+ super(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /**
+ * Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation.
+ *
+ * @param end The circuit end base implementation to take producers and consumers from.
+ */
+ public LocalAMQPPublisherImpl(CircuitEndBase end)
+ {
+ super(end);
+ }
+
+ /**
+ * Provides an assertion that the publisher got a no consumers exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no consumers exception on every message.
+ */
+ public Assertion noConsumersAssertion(ParsedProperties testProps)
+ {
+ return new AssertionBase()
+ {
+ public boolean apply()
+ {
+ boolean passed = true;
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoConsumersException.class))
+ {
+ passed = false;
+
+ addError("Was expecting linked exception type " + AMQNoConsumersException.class.getName()
+ + " on the connection.\n");
+ addError((connectionExceptionMonitor.size() > 0)
+ ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+ : "Got no exceptions on the connection.");
+ }
+
+ return passed;
+ }
+ };
+ }
+
+ /**
+ * Provides an assertion that the publisher got a no rout exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no rout exception on every message.
+ */
+ public Assertion noRouteAssertion(ParsedProperties testProps)
+ {
+ return new AssertionBase()
+ {
+ public boolean apply()
+ {
+ boolean passed = true;
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoRouteException.class))
+ {
+ passed = false;
+
+ addError("Was expecting linked exception type " + AMQNoRouteException.class.getName()
+ + " on the connection.\n");
+ addError((connectionExceptionMonitor.size() > 0)
+ ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+ : "Got no exceptions on the connection.");
+ }
+
+ return passed;
+ }
+ };
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java
index 010669a7c2..9c6220d97f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java
@@ -22,7 +22,6 @@ package org.apache.qpid.test.framework.localcircuit;
import org.apache.log4j.Logger;
-import org.apache.qpid.client.AMQSession;
import org.apache.qpid.test.framework.*;
import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
@@ -31,7 +30,6 @@ import javax.jms.*;
import java.util.LinkedList;
import java.util.List;
-import java.util.concurrent.atomic.AtomicLong;
/**
* LocalCircuitImpl provides an implementation of the test circuit. This is a local only circuit implementation that
@@ -47,7 +45,7 @@ import java.util.concurrent.atomic.AtomicLong;
* <tr><td> Apply assertions against the circuits state. <td> {@link Assertion}
* <tr><td> Send test messages over the circuit.
* <tr><td> Perform the default test procedure on the circuit.
- * <tr><td> Provide access to connection and controlSession exception monitors <td> {@link ExceptionMonitor}
+ * <tr><td> Provide access to connection and controlSession exception monitors. <td> {@link ExceptionMonitor}
* </table>
*/
public class LocalCircuitImpl implements Circuit
@@ -55,9 +53,6 @@ public class LocalCircuitImpl implements Circuit
/** Used for debugging. */
private static final Logger log = Logger.getLogger(LocalCircuitImpl.class);
- /** Used to create unique destination names for each test. */
- private static AtomicLong uniqueDestsId = new AtomicLong();
-
/** Holds the test configuration for the circuit. */
private ParsedProperties testProps;
@@ -86,7 +81,7 @@ public class LocalCircuitImpl implements Circuit
* @param connection The connection.
* @param connectionExceptionMonitor The connection exception monitor.
*/
- protected LocalCircuitImpl(ParsedProperties testProps, LocalPublisherImpl publisher, LocalReceiverImpl receiver,
+ public LocalCircuitImpl(ParsedProperties testProps, LocalPublisherImpl publisher, LocalReceiverImpl receiver,
Connection connection, ExceptionMonitor connectionExceptionMonitor)
{
this.testProps = testProps;
@@ -102,159 +97,6 @@ public class LocalCircuitImpl implements Circuit
}
/**
- * Creates a local test circuit from the specified test parameters.
- *
- * @param testProps The test parameters.
- *
- * @return A connected and ready to start, test circuit.
- */
- public static Circuit createCircuit(ParsedProperties testProps)
- {
- // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
- try
- {
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
-
- // Get a unique offset to append to destination names to make them unique to the connection.
- long uniqueId = uniqueDestsId.incrementAndGet();
-
- // Set up the connection.
- Connection connection = TestUtils.createConnection(testProps);
-
- // Add the connection exception listener to assert on exception conditions with.
- // ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
- // connection.setExceptionListener(exceptionMonitor);
-
- // Set up the publisher.
- CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, props, uniqueId);
-
- // Set up the receiver.
- CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, props, uniqueId);
-
- // Start listening for incoming messages.
- connection.start();
-
- // Package everything up.
- LocalPublisherImpl publisher = new LocalPublisherImpl(publisherEnd);
- LocalReceiverImpl receiver = new LocalReceiverImpl(receiverEnd);
-
- return new LocalCircuitImpl(testProps, publisher, receiver, connection, publisher.getExceptionMonitor());
- }
- catch (JMSException e)
- {
- throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
- }
- }
-
- /**
- * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
- *
- * @param connection The connection to build the circuit end on.
- * @param testProps The test parameters to configure the circuit end construction.
- * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
- *
- * @return A circuit end suitable for the publishing side of a test circuit.
- *
- * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
- */
- public static CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
- throws JMSException
- {
- log.debug(
- "public static CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
- + uniqueId + "): called");
-
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
-
- Session session = connection.createSession(props.getTransacted(), props.getAckMode());
-
- Destination destination =
- props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
- : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
-
- MessageProducer producer =
- props.getPublisherProducerBind()
- ? ((props.getImmediate() | props.getMandatory())
- ? ((AMQSession) session).createProducer(destination, props.getMandatory(), props.getImmediate())
- : session.createProducer(destination)) : null;
-
- MessageConsumer consumer =
- props.getPublisherConsumerBind()
- ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
-
- MessageMonitor messageMonitor = new MessageMonitor();
-
- if (consumer != null)
- {
- consumer.setMessageListener(messageMonitor);
- }
-
- ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
- connection.setExceptionListener(exceptionMonitor);
-
- if (!props.getPublisherConsumerActive() && (consumer != null))
- {
- consumer.close();
- }
-
- return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
- }
-
- /**
- * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
- *
- * @param connection The connection to build the circuit end on.
- * @param testProps The test parameters to configure the circuit end construction.
- * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
- *
- * @return A circuit end suitable for the receiving side of a test circuit.
- *
- * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
- */
- public static CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
- throws JMSException
- {
- log.debug(
- "public static CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
- + uniqueId + "): called");
-
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
-
- Session session = connection.createSession(props.getTransacted(), props.getAckMode());
-
- MessageProducer producer =
- props.getReceiverProducerBind()
- ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
-
- Destination destination =
- props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
- : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
-
- MessageConsumer consumer =
- props.getReceiverConsumerBind()
- ? ((props.getDurableSubscription() && props.getPubsub())
- ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
- : null;
-
- MessageMonitor messageMonitor = new MessageMonitor();
-
- if (consumer != null)
- {
- consumer.setMessageListener(messageMonitor);
- }
-
- if (!props.getReceiverConsumerActive() && (consumer != null))
- {
- consumer.close();
- }
-
- return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
- }
-
- /**
* Gets the interface on the publishing end of the circuit.
*
* @return The publishing end of the circuit.
@@ -351,16 +193,24 @@ public class LocalCircuitImpl implements Circuit
*/
protected void send()
{
- boolean transactional = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.TRANSACTED_PROPNAME);
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
- // Send an immediate message through the publisher and ensure that it results in a JMSException.
+ boolean transactional = props.getPublisherTransacted();
+ boolean rollback = props.getRollbackPublisher();
+
+ // Send a message through the publisher and log any exceptions raised.
try
{
CircuitEnd end = getLocalPublisherCircuitEnd();
end.send(createTestMessage(end));
- if (transactional)
+ if (rollback)
+ {
+ end.getSession().rollback();
+ }
+ else if (transactional)
{
end.getSession().commit();
}
@@ -427,7 +277,10 @@ public class LocalCircuitImpl implements Circuit
*/
private Message createTestMessage(CircuitEnd client) throws JMSException
{
- return client.getSession().createTextMessage("Hello");
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ return TestUtils.createTestMessageOfSize(client.getSession(), props.getMessageSize());
}
/**
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java
index 93a137dffa..bd15839e41 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java
@@ -20,10 +20,10 @@
*/
package org.apache.qpid.test.framework.localcircuit;
-import org.apache.qpid.client.AMQNoConsumersException;
-import org.apache.qpid.client.AMQNoRouteException;
import org.apache.qpid.test.framework.*;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
@@ -31,7 +31,7 @@ import javax.jms.Session;
/**
* Provides an implementation of the {@link Publisher} interface and wraps a single message producer and consumer on
* a single controlSession, as a {@link CircuitEnd}. A local publisher also acts as a circuit end, because for a locally
- * located circuit the assertions may be applied directly, there does not need to be any inter process messaging
+ * located circuit the assertions may be applied directly, there does not need to be any inter-process messaging
* between the publisher and its single circuit end, in order to ascertain its status.
*
* <p/><table id="crc"><caption>CRC Card</caption>
@@ -46,14 +46,17 @@ import javax.jms.Session;
public class LocalPublisherImpl extends CircuitEndBase implements Publisher
{
/** Holds a reference to the containing circuit. */
- private LocalCircuitImpl circuit;
+ protected LocalCircuitImpl circuit;
/**
- * Creates a circuit end point on the specified producer, consumer and controlSession.
+ * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ * for messages and exceptions received by the circuit end.
*
* @param producer The message producer for the circuit end point.
* @param consumer The message consumer for the circuit end point.
* @param session The controlSession for the circuit end point.
+ * @param messageMonitor The monitor to notify of all messages received by the circuit end.
+ * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end.
*/
public LocalPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session,
MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
@@ -74,9 +77,11 @@ public class LocalPublisherImpl extends CircuitEndBase implements Publisher
/**
* Provides an assertion that the publisher encountered no exceptions.
*
+ * @param testProps
+ *
* @return An assertion that the publisher encountered no exceptions.
*/
- public Assertion noExceptionsAssertion()
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
{
return new AssertionBase()
{
@@ -109,41 +114,26 @@ public class LocalPublisherImpl extends CircuitEndBase implements Publisher
}
/**
- * Provides an assertion that the publisher got a no consumers exception on every message.
+ * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ *
+ * @param testProps The test configuration properties.
*
- * @return An assertion that the publisher got a no consumers exception on every message.
+ * @return An assertion that the AMQP channel was forcibly closed by an error condition.
*/
- public Assertion noConsumersAssertion()
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
{
- return new AssertionBase()
- {
- public boolean apply()
- {
- boolean passed = true;
- ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
-
- if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoConsumersException.class))
- {
- passed = false;
-
- addError("Was expecting linked exception type " + AMQNoConsumersException.class.getName()
- + " on the connection.\n");
- addError((connectionExceptionMonitor.size() > 0)
- ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
- : "Got no exceptions on the connection.");
- }
-
- return passed;
- }
- };
+ return new NotApplicableAssertion(testProps);
}
/**
- * Provides an assertion that the publisher got a no rout exception on every message.
+ * Provides an assertion that the publisher got a given exception during the test.
+ *
+ * @param testProps The test configuration properties.
+ * @param exceptionClass The exception class to check for.
*
- * @return An assertion that the publisher got a no rout exception on every message.
+ * @return An assertion that the publisher got a given exception during the test.
*/
- public Assertion noRouteAssertion()
+ public Assertion exceptionAssertion(ParsedProperties testProps, final Class<? extends Exception> exceptionClass)
{
return new AssertionBase()
{
@@ -152,11 +142,11 @@ public class LocalPublisherImpl extends CircuitEndBase implements Publisher
boolean passed = true;
ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
- if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoRouteException.class))
+ if (!connectionExceptionMonitor.assertExceptionOfType(exceptionClass))
{
passed = false;
- addError("Was expecting linked exception type " + AMQNoRouteException.class.getName()
+ addError("Was expecting linked exception type " + exceptionClass.getName()
+ " on the connection.\n");
addError((connectionExceptionMonitor.size() > 0)
? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java
index 1b5acf92de..9a86c00a1b 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java
@@ -22,6 +22,8 @@ package org.apache.qpid.test.framework.localcircuit;
import org.apache.qpid.test.framework.*;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
@@ -46,11 +48,14 @@ public class LocalReceiverImpl extends CircuitEndBase implements Receiver
private LocalCircuitImpl circuit;
/**
- * Creates a circuit end point on the specified producer, consumer and controlSession.
+ * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ * for messages and exceptions received by the circuit end.
*
* @param producer The message producer for the circuit end point.
* @param consumer The message consumer for the circuit end point.
* @param session The controlSession for the circuit end point.
+ * @param messageMonitor The monitor to notify of all messages received by the circuit end.
+ * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end.
*/
public LocalReceiverImpl(MessageProducer producer, MessageConsumer consumer, Session session,
MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
@@ -71,21 +76,60 @@ public class LocalReceiverImpl extends CircuitEndBase implements Receiver
/**
* Provides an assertion that the receivers encountered no exceptions.
*
+ * @param testProps The test configuration properties.
+ *
* @return An assertion that the receivers encountered no exceptions.
*/
- public Assertion noExceptionsAssertion()
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /**
+ * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the AMQP channel was forcibly closed by an error condition.
+ */
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
{
- return null;
+ return new NotApplicableAssertion(testProps);
}
/**
* Provides an assertion that the receivers got all messages that were sent to it.
*
+ * @param testProps The test configuration properties.
+ *
* @return An assertion that the receivers got all messages that were sent to it.
*/
- public Assertion allMessagesAssertion()
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /**
+ * Provides an assertion that the receivers got none of the messages that were sent to it.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the receivers got none of the messages that were sent to it.
+ */
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /**
+ * Provides an assertion that the receiver got a given exception during the test.
+ *
+ * @param testProps The test configuration properties.
+ * @param exceptionClass The exception class to check for. @return An assertion that the receiver got a given exception during the test.
+ */
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass)
{
- return null;
+ return new NotApplicableAssertion(testProps);
}
/**
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java
new file mode 100644
index 0000000000..cb487a315b
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java
@@ -0,0 +1,83 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.LocalAMQPCircuitFactory;
+
+import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * AMQPFeatureDecorator applies decorations to {@link FrameworkBaseCase} tests, so that they may use Qpid/AMQP specific
+ * features, not available through JMS. For example, the immediate and mandatory flags. This decorator replaces the
+ * standard test circuit factory on the base class with one that allows these features to be used.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Substitute the circuit factory with an AMQP/Qpid specific one.
+ * </table>
+ *
+ * @todo This wrapper substitutes in a LocalAMQPCircuitFactory, which is fine for local tests. For distributed tests
+ * the Fanout or Interop factories are substituted in by their decorators instead. These actually use
+ * distributed circuit static create methods to build the circuits, which should actually be changed to a factory,
+ * so that static methods do not need to be used. The distributed circuit creater delegates the circuit
+ * construction to remote test nodes. This decorator should not be used with distributed tests, or should be made
+ * aware of them, in which case it might ensure that an AMQP feature (implied already by other properties) flag
+ * is passed out to the remote test nodes, and provide a mechansim for them to decorate their circuit creation
+ * with AMQP features too. Add factory substituion/decoration mechansim for test clients, here or in a seperate
+ * class.
+ */
+public class AMQPFeatureDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test test decorator from another one.
+ *
+ * @param test The test test.
+ */
+ public AMQPFeatureDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with a LocalAMQPCircuitFactory.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ for (Test test : getAllUnderlyingTests())
+ {
+ FrameworkBaseCase frameworkTest = (FrameworkBaseCase) test;
+ frameworkTest.setCircuitFactory(new LocalAMQPCircuitFactory());
+ }
+
+ // Run the test.
+ test.run(testResult);
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java
new file mode 100644
index 0000000000..8b21ec1144
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * InVMBrokerDecorator is a test decorator, that is activated when running tests against an in-vm broker only. Its
+ * purpose is to automatically create, and close and delete an in-vm broker, during the set-up and tear-down of
+ * each test case. This decorator may only be used in conjunction with tests that extend {@link FrameworkBaseCase}.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create/Destroy an in-vm broker on every test run.
+ * </table>
+ *
+ * @todo May need to add a more fine grained injection point for the in-vm broker management, as this may act at the
+ * suite level, rather than the individual test level.
+ */
+public class InVMBrokerDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test suite decorator from another one.
+ *
+ * @param test The test suite.
+ */
+ public InVMBrokerDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with in-vm broker management.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ /*for (Test test : getAllUnderlyingTests())
+ {
+ FrameworkBaseCase frameworkTest = (FrameworkBaseCase) test;
+ }*/
+
+ // Ensure that the in-vm broker is created.
+ try
+ {
+ TransportConnection.createVMBroker(1);
+ }
+ catch (AMQVMBrokerCreationException e)
+ {
+ throw new RuntimeException("In-VM broker creation failed: " + e.getMessage(), e);
+ }
+
+ // Run the test.
+ test.run(testResult);
+
+ // Ensure that the in-vm broker is cleaned up so that the next test starts afresh.
+ TransportConnection.killVMBroker(1);
+ ApplicationRegistry.remove(1);
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java
index 555071760e..d323563582 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java
@@ -31,13 +31,20 @@ import java.util.List;
import java.util.Properties;
/**
+ * BaseCircuitFactory provides some functionality common to all {@link CircuitFactory}s, such as the details of
+ * all {@link org.apache.qpid.test.framework.distributedtesting.TestClient}s that make up the end-points of
+ * the circuits that the factory creates, and an active {@link ConversationFactory} that can be used to generate
+ * control conversations with those circuit end-points.
+ *
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
+ * <tr><td> Hold the details of the sending and receiving end-points to create circuits from.
+ * <tr><td> Provide a conversation factory to create control conversations with the end-points.
* </table>
*/
public abstract class BaseCircuitFactory implements CircuitFactory
{
+
/** Used for debugging. */
private final Logger log = Logger.getLogger(BaseCircuitFactory.class);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java
index 82caa20d79..ade96427ac 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java
@@ -35,7 +35,7 @@ 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
+ * A CircuitFactory 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>
@@ -43,12 +43,6 @@ import java.util.Properties;
* <tr><td> Provide a standard test procedure over a test circuit.
* <tr><td> Construct test circuits appropriate to a tests context.
* </table>
- *
- * @todo The sequence test method is deprecated, in favour of using test circuits instead. This interface might be
- * better renamed to somethign like CircuitFactory, also the split between this interface and
- * DistributedTestSequencer could be removed and DistributedTestCase functionality merged into FrameworkBaseCase.
- * This is so that any test case written on top of the framework base case can be distributed, without having
- * to extend a different base test class.
*/
public interface CircuitFactory
{
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java
index 673b47df03..ff4ee741ad 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java
@@ -46,7 +46,7 @@ import java.util.Properties;
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
+ * <tr><td> Create distributed circuits from one to many test nodes, for fanout style testing.
* </table>
*
* @todo Adapt this to be an n*m topology circuit factory. Need to add circuit topology definitions to the test
@@ -57,7 +57,7 @@ import java.util.Properties;
*
* @todo The createCircuit methods on this and InteropCircuitFactory are going to be identical. This is because the
* partitioning into senders and receivers is already done by the test decorators. Either eliminate these factories
- * as unnesesary, or move the partitioning functionaility into the factories, in which case the test decorators
+ * as unnesesary, or move the partitioning functionality into the factories, in which case the test decorators
* can probably be merged or eliminated. There is confusion over the placement of responsibilities between the
* factories and the test decorators... although the test decorators may well do more than just circuit creation
* in the future. For example, there may have to be a special decorator for test repetition that does one circuit
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java
index 35bcf78b72..4c56a68d8f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java
@@ -41,10 +41,20 @@ import java.util.List;
import java.util.Properties;
/**
+ * InteropCircuitFactory is a circuit factory that creates distributed test circuits. Given a set of participating
+ * test client nodes, it assigns one node to the SENDER role and one the RECEIVER role.
+ *
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
+ * <tr><td> Create distributed circuits from pairs of test nodes, for interop style testing.
* </table>
+ *
+ * @todo The partitioning of a set of nodes into sender and receiver roles is actually done by the interop test
+ * decorator. See the todo comment in FanOutCircuitFactory about merging the factories with the decorators, or
+ * more carefully dividing up responsibilities between them.
+ *
+ * @todo The squenceTest code is deprecated, but currently still used by the interop tests. It will be removed once it
+ * have been fully replaced by the default test procedure.
*/
public class InteropCircuitFactory extends BaseCircuitFactory
{
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java
index 9b5c9c3d00..e82a7927b6 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java
@@ -18,8 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.server.exchange;
+package org.apache.qpid.test.testcases;
+import org.apache.qpid.test.framework.AMQPPublisher;
import org.apache.qpid.test.framework.Circuit;
import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.MessagingTestConfigProperties;
@@ -81,35 +82,35 @@ public class ImmediateMessageTest extends FrameworkBaseCase
public void test_QPID_517_ImmediateOkNoTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Run the default test sequence over the test circuit checking for no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps))));
}
/** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
public void test_QPID_517_ImmediateOkTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Send one message with no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps))));
}
/** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Disconnect the consumer.
@@ -119,14 +120,15 @@ public class ImmediateMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
}
/** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Disconnect the consumer.
@@ -136,14 +138,15 @@ public class ImmediateMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
}
/** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
public void test_QPID_517_ImmediateFailsNoRouteNoTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -154,14 +157,15 @@ public class ImmediateMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
}
/** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
public void test_QPID_517_ImmediateFailsNoRouteTxP2P()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -172,42 +176,45 @@ public class ImmediateMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
}
/** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
public void test_QPID_517_ImmediateOkNoTxPubSub()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Send one message with no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
public void test_QPID_517_ImmediateOkTxPubSub()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Send one message with no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxPubSub()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Use durable subscriptions, so that the route remains open with no subscribers.
@@ -220,14 +227,15 @@ public class ImmediateMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
}
/** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxPubSub()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Use durable subscriptions, so that the route remains open with no subscribers.
@@ -240,14 +248,15 @@ public class ImmediateMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
}
/** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
public void test_QPID_517_ImmediateFailsNoRouteNoTxPubSub()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -258,14 +267,15 @@ public class ImmediateMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
}
/** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
public void test_QPID_517_ImmediateFailsNoRouteTxPubSub()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -276,7 +286,8 @@ public class ImmediateMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) 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/test/testcases/MandatoryMessageTest.java
index df99d044d2..7391bf23d2 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/testcases/MandatoryMessageTest.java
@@ -18,8 +18,9 @@
* under the License.
*
*/
-package org.apache.qpid.server.exchange;
+package org.apache.qpid.test.testcases;
+import org.apache.qpid.test.framework.AMQPPublisher;
import org.apache.qpid.test.framework.Circuit;
import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.MessagingTestConfigProperties;
@@ -81,28 +82,30 @@ public class MandatoryMessageTest extends FrameworkBaseCase
public void test_QPID_508_MandatoryOkNoTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Run the default test sequence over the test circuit checking for no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
public void test_QPID_508_MandatoryOkTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Run the default test sequence over the test circuit checking for no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/**
@@ -112,7 +115,7 @@ public class MandatoryMessageTest extends FrameworkBaseCase
public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Disconnect the consumer.
@@ -122,7 +125,8 @@ public class MandatoryMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/**
@@ -132,7 +136,7 @@ public class MandatoryMessageTest extends FrameworkBaseCase
public void test_QPID_517_MandatoryOkConsumerDisconnectedTxP2P()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, false);
// Disconnect the consumer.
@@ -142,14 +146,15 @@ public class MandatoryMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
public void test_QPID_508_MandatoryFailsNoRouteNoTxP2P()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -160,14 +165,15 @@ public class MandatoryMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
}
/** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
public void test_QPID_508_MandatoryFailsNoRouteTxP2P()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -178,35 +184,38 @@ public class MandatoryMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
}
/** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */
public void test_QPID_508_MandatoryOkNoTxPubSub()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Run the default test sequence over the test circuit checking for no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
public void test_QPID_508_MandatoryOkTxPubSub()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Run the default test sequence over the test circuit checking for no errors.
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/**
@@ -216,7 +225,7 @@ public class MandatoryMessageTest extends FrameworkBaseCase
public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxPubSub()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Use durable subscriptions, so that the route remains open with no subscribers.
@@ -229,7 +238,8 @@ public class MandatoryMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/**
@@ -239,7 +249,7 @@ public class MandatoryMessageTest extends FrameworkBaseCase
public void test_QPID_517_MandatoryOkConsumerDisconnectedTxPubSub()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
testProps.setProperty(PUBSUB_PROPNAME, true);
// Use durable subscriptions, so that the route remains open with no subscribers.
@@ -252,14 +262,15 @@ public class MandatoryMessageTest extends FrameworkBaseCase
Circuit testCircuit = circuitFactory.createCircuit(testProps);
// Send one message with no errors.
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
}
/** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
public void test_QPID_508_MandatoryFailsNoRouteNoTxPubSub()
{
// Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PROPNAME, false);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -270,14 +281,15 @@ public class MandatoryMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
}
/** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
public void test_QPID_508_MandatoryFailsNoRouteTxPubSub()
{
// Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PROPNAME, true);
+ testProps.setProperty(TRANSACTED_PUBLISHER_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 receivers to
@@ -288,7 +300,8 @@ public class MandatoryMessageTest extends FrameworkBaseCase
CircuitFactory circuitFactory = getCircuitFactory();
Circuit testCircuit = circuitFactory.createCircuit(testProps);
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
}
protected void setUp() throws Exception
diff --git a/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java b/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java
new file mode 100644
index 0000000000..163a6a67f6
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java
@@ -0,0 +1,132 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+/**
+ * RollbackTest tests the rollback ability of transactional messaging.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check messages sent but rolled back are never received.
+ * <tr><td> Check messages received but rolled back are redelivered on subsequent receives.
+ * <tr><td> Attempting to rollback outside of a transaction results in an IllegalStateException.
+ * </table>
+ */
+public class RollbackTest 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 RollbackTest(String name)
+ {
+ super(name);
+ }
+
+ /** Check messages sent but rolled back are never received. */
+ public void testRolledbackMessageNotDelivered()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(ROLLBACK_PUBLISHER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps),
+ testCircuit.getReceiver().noMessagesReceivedAssertion(testProps))));
+ }
+
+ /** Check messages received but rolled back are redelivered on subsequent receives. */
+ public void testRolledbackMessagesSubsequentlyReceived()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_RECEIVER_PROPNAME, true);
+ testProps.setProperty(ROLLBACK_RECEIVER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps),
+ testCircuit.getReceiver().allMessagesReceivedAssertion(testProps))));
+ }
+
+ /** Attempting to rollback outside of a transaction results in an IllegalStateException. */
+ public void testRollbackUnavailableOutsideTransactionPublisher()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(ROLLBACK_PUBLISHER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().channelClosedAssertion(testProps))));
+ }
+
+ /** Attempting to rollback outside of a transaction results in an IllegalStateException. */
+ public void testRollbackUnavailableOutsideTransactionReceiver()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_RECEIVER_PROPNAME, false);
+ testProps.setProperty(ROLLBACK_RECEIVER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getReceiver().channelClosedAssertion(testProps))));
+ }
+
+ /**
+ * Sets up all tests to have an active outward route and consumer by default.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /** Bind the receivers consumer by default. */
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, true);
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, true);
+ }
+}
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
index a325e7025e..d1ba96dc71 100644
--- a/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java
@@ -92,7 +92,7 @@ import java.util.concurrent.atomic.AtomicLong;
*
* <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> 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>