From 6b54ebb02e87cc4cc0a7bcd1d9d820c463f76e7f Mon Sep 17 00:00:00 2001 From: Rupert Smith Date: Wed, 1 Aug 2007 16:19:31 +0000 Subject: Extensive refactoring of the distributed test framework. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2@561855 13f79535-47bb-0310-9956-ffa450edef68 --- .../interop/clienttestcases/TestCase1DummyRun.java | 12 +- .../interop/clienttestcases/TestCase2BasicP2P.java | 18 +- .../clienttestcases/TestCase3BasicPubSub.java | 16 +- .../qpid/interop/testcases/CircuitTestCase.java | 101 ----- .../testcases/InteropTestCase1DummyRun.java | 8 +- .../testcases/InteropTestCase2BasicP2P.java | 8 +- .../testcases/InteropTestCase3BasicPubSub.java | 8 +- .../qpid/sustained/SustainedClientTestCase.java | 13 +- .../apache/qpid/sustained/SustainedTestCase.java | 8 +- .../distributedtesting/InteropClientTestCase.java | 101 ----- .../framework/distributedtesting/TestClient.java | 119 ++++-- java/perftests/jar-with-dependencies.xml | 73 ++-- java/perftests/pom.xml | 31 +- .../apache/qpid/requestreply/PingPongBouncer.java | 10 +- .../apache/qpid/requestreply/PingPongProducer.java | 14 +- .../qpid/perftests/QpidTestThroughputPerf.java | 170 ++++++++ java/systests/etc/bin/testclients.sh | 23 ++ .../qpid/server/exchange/ImmediateMessageTest.java | 107 ++--- .../qpid/server/exchange/MandatoryMessageTest.java | 107 ++--- .../org/apache/qpid/test/framework/CircuitEnd.java | 14 + .../apache/qpid/test/framework/CircuitEndBase.java | 38 +- .../qpid/test/framework/ExceptionMonitor.java | 7 + .../qpid/test/framework/FrameworkBaseCase.java | 101 ++++- .../test/framework/FrameworkClientBaseCase.java | 11 + .../apache/qpid/test/framework/MessageMonitor.java | 65 ++- .../framework/MessagingTestConfigProperties.java | 188 ++++++++- .../org/apache/qpid/test/framework/Publisher.java | 12 +- .../org/apache/qpid/test/framework/Receiver.java | 6 +- .../distributedcircuit/DistributedCircuitImpl.java | 377 ++++++++++++++++- .../DistributedPublisherImpl.java | 63 +++ .../DistributedReceiverImpl.java | 53 +++ .../distributedcircuit/TestClientCircuitEnd.java | 315 ++++++++++++++ .../framework/distributedtesting/Coordinator.java | 179 ++++++-- .../distributedtesting/DistributedTestCase.java | 81 ---- .../DistributedTestDecorator.java | 18 +- .../distributedtesting/FanOutTestDecorator.java | 31 +- .../distributedtesting/InteropTestDecorator.java | 43 +- .../distributedtesting/OptOutTestCase.java | 9 +- .../TestClientControlledTest.java | 108 +++++ .../test/framework/listeners/XMLTestListener.java | 19 +- .../test/framework/localcircuit/CircuitImpl.java | 394 ------------------ .../framework/localcircuit/LocalCircuitImpl.java | 452 +++++++++++++++++++++ .../framework/localcircuit/LocalPublisherImpl.java | 180 ++++++++ .../framework/localcircuit/LocalReceiverImpl.java | 100 +++++ .../test/framework/localcircuit/PublisherImpl.java | 162 -------- .../test/framework/localcircuit/ReceiverImpl.java | 90 ---- .../framework/sequencers/BaseCircuitFactory.java | 128 ++++++ .../sequencers/BaseDistributedTestSequencer.java | 129 ------ .../test/framework/sequencers/CircuitFactory.java | 111 +++++ .../sequencers/DistributedTestSequencer.java | 75 ---- .../framework/sequencers/FanOutCircuitFactory.java | 201 +++++++++ .../framework/sequencers/FanOutTestSequencer.java | 171 -------- .../sequencers/InteropCircuitFactory.java | 146 +++++++ .../framework/sequencers/InteropTestSequencer.java | 137 ------- .../framework/sequencers/TestCaseSequencer.java | 66 --- .../org/apache/qpid/util/ConversationFactory.java | 8 +- 56 files changed, 3387 insertions(+), 1848 deletions(-) delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/CircuitTestCase.java delete mode 100644 java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropClientTestCase.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/perftests/QpidTestThroughputPerf.java create mode 100644 java/systests/etc/bin/testclients.sh create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkClientBaseCase.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestCase.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/CircuitImpl.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/PublisherImpl.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/ReceiverImpl.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseDistributedTestSequencer.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/DistributedTestSequencer.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutTestSequencer.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropTestSequencer.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/TestCaseSequencer.java (limited to 'java') diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java index b119d13a3d..45bbfcd148 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java @@ -22,7 +22,7 @@ package org.apache.qpid.interop.clienttestcases; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.distributedtesting.InteropClientTestCase; +import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest; import javax.jms.JMSException; import javax.jms.Message; @@ -41,7 +41,7 @@ import javax.jms.Session; * Generate test reports. * */ -public class TestCase1DummyRun implements InteropClientTestCase +public class TestCase1DummyRun implements TestClientControlledTest { /** Used for debugging. */ private static final Logger log = Logger.getLogger(TestCase1DummyRun.class); @@ -94,8 +94,10 @@ public class TestCase1DummyRun implements InteropClientTestCase /** * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. + * + * @param numMessages The number of test messages to send. */ - public void start() + public void start(int numMessages) { log.debug("public void start(): called"); @@ -105,7 +107,7 @@ public class TestCase1DummyRun implements InteropClientTestCase /** * Gets a report on the actions performed by the test case in its assigned role. * - * @param session The session to create the report message in. + * @param session The controlSession to create the report message in. * * @return The report message. * @@ -113,7 +115,7 @@ public class TestCase1DummyRun implements InteropClientTestCase */ public Message getReport(Session session) throws JMSException { - log.debug("public Message getReport(Session session): called"); + log.debug("public Message getReport(Session controlSession): called"); // Generate a dummy report, the coordinator expects a report but doesn't care what it is. return session.createTextMessage("Dummy Run, Ok."); diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java index 080bd846ee..1d30ff7ca6 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java @@ -22,9 +22,9 @@ package org.apache.qpid.interop.clienttestcases; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.distributedtesting.InteropClientTestCase; -import org.apache.qpid.test.framework.distributedtesting.TestClient; import org.apache.qpid.test.framework.TestUtils; +import org.apache.qpid.test.framework.distributedtesting.TestClient; +import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest; import javax.jms.*; @@ -41,7 +41,7 @@ import javax.jms.*; * Generate test reports. * */ -public class TestCase2BasicP2P implements InteropClientTestCase +public class TestCase2BasicP2P implements TestClientControlledTest, MessageListener { /** Used for debugging. */ private static final Logger log = Logger.getLogger(TestCase2BasicP2P.class); @@ -58,7 +58,7 @@ public class TestCase2BasicP2P implements InteropClientTestCase /** The connection to send the test messages on. */ private Connection connection; - /** The session to send the test messages on. */ + /** The controlSession to send the test messages on. */ private Session session; /** The producer to send the test messages with. */ @@ -147,9 +147,11 @@ public class TestCase2BasicP2P implements InteropClientTestCase /** * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. * + * @param numMessages The number of test messages to send. + * * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. */ - public void start() throws JMSException + public void start(int numMessages) throws JMSException { log.debug("public void start(): called"); @@ -158,7 +160,7 @@ public class TestCase2BasicP2P implements InteropClientTestCase { Message testMessage = session.createTextMessage("test"); - for (int i = 0; i < numMessages; i++) + for (int i = 0; i < this.numMessages; i++) { producer.send(testMessage); @@ -171,7 +173,7 @@ public class TestCase2BasicP2P implements InteropClientTestCase /** * Gets a report on the actions performed by the test case in its assigned role. * - * @param session The session to create the report message in. + * @param session The controlSession to create the report message in. * * @return The report message. * @@ -179,7 +181,7 @@ public class TestCase2BasicP2P implements InteropClientTestCase */ public Message getReport(Session session) throws JMSException { - log.debug("public Message getReport(Session session): called"); + log.debug("public Message getReport(Session controlSession): called"); // Close the test connection. connection.close(); diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java index a11d045e89..622ddc2f64 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java @@ -22,9 +22,9 @@ package org.apache.qpid.interop.clienttestcases; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.distributedtesting.InteropClientTestCase; -import org.apache.qpid.test.framework.distributedtesting.TestClient; import org.apache.qpid.test.framework.TestUtils; +import org.apache.qpid.test.framework.distributedtesting.TestClient; +import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest; import javax.jms.*; @@ -42,7 +42,7 @@ import javax.jms.*; * Generate test reports. * */ -public class TestCase3BasicPubSub implements InteropClientTestCase +public class TestCase3BasicPubSub implements TestClientControlledTest, MessageListener { /** Used for debugging. */ private static final Logger log = Logger.getLogger(TestCase3BasicPubSub.class); @@ -174,9 +174,11 @@ public class TestCase3BasicPubSub implements InteropClientTestCase /** * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. * + * @param numMessages The number of test messages to send. + * * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. */ - public void start() throws JMSException + public void start(int numMessages) throws JMSException { log.debug("public void start(): called"); @@ -185,7 +187,7 @@ public class TestCase3BasicPubSub implements InteropClientTestCase { Message testMessage = session[0].createTextMessage("test"); - for (int i = 0; i < numMessages; i++) + for (int i = 0; i < this.numMessages; i++) { producer.send(testMessage); @@ -198,7 +200,7 @@ public class TestCase3BasicPubSub implements InteropClientTestCase /** * Gets a report on the actions performed by the test case in its assigned role. * - * @param session The session to create the report message in. + * @param session The controlSession to create the report message in. * * @return The report message. * @@ -206,7 +208,7 @@ public class TestCase3BasicPubSub implements InteropClientTestCase */ public Message getReport(Session session) throws JMSException { - log.debug("public Message getReport(Session session): called"); + log.debug("public Message getReport(Session controlSession): called"); // Close the test connections. for (Connection conn : connection) diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/CircuitTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/CircuitTestCase.java deleted file mode 100644 index 966a545e16..0000000000 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/CircuitTestCase.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.interop.testcases; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.framework.sequencers.TestCaseSequencer; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.FrameworkBaseCase; -import org.apache.qpid.test.framework.MessagingTestConfigProperties; - -import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; -import uk.co.thebadgerset.junit.extensions.util.TestContextProperties; - -/** - * CircuitTestCase runs a test over a {@link Circuit} controlled by the test parameters. - * - *

- *
CRC Card
Responsibilities Collaborations - *
- *
- * - * @todo When working with test context properties, add overrides to defaults to the singleton instance, but when taking - * a starting point to add specific test case parameters to, take a copy. Use the copy with test case specifics - * to control the test. - */ -public class CircuitTestCase extends FrameworkBaseCase -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(CircuitTestCase.class); - - /** - * Creates a new test case with the specified name. - * - * @param name The test case name. - */ - public CircuitTestCase(String name) - { - super(name); - } - - /** - * Performs the a basic P2P test case. - * - * @throws Exception Any exceptions are allowed to fall through and fail the test. - */ - public void testBasicP2P() throws Exception - { - log.debug("public void testBasicP2P(): called"); - - // Get the test parameters, any overrides on the command line will have been applied. - ParsedProperties testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); - - // Customize the test parameters. - testProps.setProperty("TEST_NAME", "DEFAULT_CIRCUIT_TEST"); - testProps.setProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME, "testqueue"); - - // Get the test sequencer to create test circuits and run the standard test procedure through. - TestCaseSequencer sequencer = getTestSequencer(); - - // Send the test messages, and check that there were no errors doing so. - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); - - // Check that all of the message were sent. - // Check that the receiving end got the same number of messages as the publishing end. - } - - /** - * Should provide a translation from the junit method name of a test to its test case name as known to the test - * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test - * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case - * name "TC2_BasicP2P". - * - * @param methodName The name of the JUnit test method. - * - * @return The name of the corresponding interop test case. - */ - public String getTestCaseNameForTestMethod(String methodName) - { - return "DEFAULT_CIRCUIT_TEST"; - } -} diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java index 73e08b578e..60cd9f47f3 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java @@ -22,7 +22,7 @@ package org.apache.qpid.interop.testcases; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.distributedtesting.DistributedTestCase; +import org.apache.qpid.test.framework.FrameworkBaseCase; import java.util.Properties; @@ -33,10 +33,10 @@ import java.util.Properties; *

*
CRC Card
Responsibilities Collaborations *
Exercises the interop testing framework without actually sending any test messages. - * {@link org.apache.qpid.test.framework.distributedtesting.DistributedTestCase} + * {@link FrameworkBaseCase} *
*/ -public class InteropTestCase1DummyRun extends DistributedTestCase +public class InteropTestCase1DummyRun extends FrameworkBaseCase { /** Used for debugging. */ private static final Logger log = Logger.getLogger(InteropTestCase1DummyRun.class); @@ -63,7 +63,7 @@ public class InteropTestCase1DummyRun extends DistributedTestCase Properties testConfig = new Properties(); testConfig.put("TEST_NAME", "TC1_DummyRun"); - /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig); + /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig); // Compare sender and receivers reports. // Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length); diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java index f77bbf032f..8983249daa 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java @@ -22,7 +22,7 @@ package org.apache.qpid.interop.testcases; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.distributedtesting.DistributedTestCase; +import org.apache.qpid.test.framework.FrameworkBaseCase; import java.util.Properties; @@ -33,10 +33,10 @@ import java.util.Properties; * *

*
CRC Card
Responsibilities Collaborations - *
Setup p2p test parameters and compare with test output. {@link DistributedTestCase} + *
Setup p2p test parameters and compare with test output. {@link FrameworkBaseCase} *
*/ -public class InteropTestCase2BasicP2P extends DistributedTestCase +public class InteropTestCase2BasicP2P extends FrameworkBaseCase { /** Used for debugging. */ private static final Logger log = Logger.getLogger(InteropTestCase2BasicP2P.class); @@ -65,7 +65,7 @@ public class InteropTestCase2BasicP2P extends DistributedTestCase testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue"); testConfig.put("P2P_NUM_MESSAGES", 50); - /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig); + /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig); // Compare sender and receivers reports. /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT"); diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java index ad27ca63bd..6e87c3e3ee 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java @@ -22,17 +22,17 @@ package org.apache.qpid.interop.testcases; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.distributedtesting.DistributedTestCase; +import org.apache.qpid.test.framework.FrameworkBaseCase; import java.util.Properties; /** *

*
CRC Card
Responsibilities Collaborations - *
Setup pub/sub test parameters and compare with test output. {@link DistributedTestCase} + *
Setup pub/sub test parameters and compare with test output. {@link FrameworkBaseCase} *
*/ -public class InteropTestCase3BasicPubSub extends DistributedTestCase +public class InteropTestCase3BasicPubSub extends FrameworkBaseCase { /** Used for debugging. */ private static final Logger log = Logger.getLogger(InteropTestCase3BasicPubSub.class); @@ -62,7 +62,7 @@ public class InteropTestCase3BasicPubSub extends DistributedTestCase testConfig.put("PUBSUB_NUM_MESSAGES", 10); testConfig.put("PUBSUB_NUM_RECEIVERS", 5); - /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig); + /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig); // Compare sender and receivers reports. /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT"); diff --git a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java index 65e05fab4b..2764f2c3aa 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java @@ -57,7 +57,7 @@ import java.util.concurrent.CountDownLatch; * Send required number of test messages using pub/sub. Generate test reports. * */ -public class SustainedClientTestCase extends TestCase3BasicPubSub implements ExceptionListener +public class SustainedClientTestCase extends TestCase3BasicPubSub implements ExceptionListener, MessageListener { /** Used for debugging. */ private static final Logger log = Logger.getLogger(SustainedClientTestCase.class); @@ -205,8 +205,9 @@ public class SustainedClientTestCase extends TestCase3BasicPubSub implements Exc } } - /** Performs the test case actions. */ - public void start() throws JMSException + /** Performs the test case actions. + * @param numMessages*/ + public void start(int numMessages) throws JMSException { log.debug("public void start(): called"); @@ -235,7 +236,7 @@ public class SustainedClientTestCase extends TestCase3BasicPubSub implements Exc /** * Gets a report on the actions performed by the test case in its assigned role. * - * @param session The session to create the report message in. + * @param session The controlSession to create the report message in. * * @return The report message. * @@ -243,7 +244,7 @@ public class SustainedClientTestCase extends TestCase3BasicPubSub implements Exc */ public Message getReport(Session session) throws JMSException { - log.debug("public Message getReport(Session session): called"); + log.debug("public Message getReport(Session controlSession): called"); // Close the test connections. for (int i = 0; i < connection.length; i++) @@ -318,7 +319,7 @@ public class SustainedClientTestCase extends TestCase3BasicPubSub implements Exc * @param clientname The _client id used to identify this connection. * @param batchSize The number of messages that are to be sent per batch. Note: This is not used to * control the interval between sending reports. - * @param session The session used for communication. + * @param session The controlSession used for communication. * @param sendDestination The destination that update reports should be sent to. * * @throws JMSException My occur if creatingthe Producer fails diff --git a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java index 36f9b4eaf1..5979a459ec 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java @@ -23,8 +23,8 @@ package org.apache.qpid.sustained; import org.apache.log4j.Logger; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.test.framework.distributedtesting.DistributedTestCase; import org.apache.qpid.test.framework.DropInTest; +import org.apache.qpid.test.framework.FrameworkBaseCase; import javax.jms.JMSException; import javax.jms.Message; @@ -32,7 +32,7 @@ import javax.jms.Message; import java.util.Properties; /** - * SustainedTestCase is a {@link org.apache.qpid.test.framework.distributedtesting.DistributedTestCase} that runs the "Perf_SustainedPubSub" test case. This consists of one + * SustainedTestCase is a {@link FrameworkBaseCase} that runs the "Perf_SustainedPubSub" test case. This consists of one * test client sending, and several receiving, and attempts to find the highest rate at which messages can be broadcast * to the receivers. It is also a {@link DropInTest} to which more test clients may be added during a test run. * @@ -41,7 +41,7 @@ import java.util.Properties; * * */ -public class SustainedTestCase extends DistributedTestCase implements DropInTest +public class SustainedTestCase extends FrameworkBaseCase implements DropInTest { /** Used for debugging. */ Logger log = Logger.getLogger(SustainedTestCase.class); @@ -78,7 +78,7 @@ public class SustainedTestCase extends DistributedTestCase implements DropInTest log.info("Created Config: " + testConfig.entrySet().toArray()); - getTestSequencer().sequenceTest(null, null, testConfig); + getCircuitFactory().sequenceTest(null, null, testConfig); } /** diff --git a/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropClientTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropClientTestCase.java deleted file mode 100644 index 5e6d61a9e0..0000000000 --- a/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropClientTestCase.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.Session; - -/** - * InteropClientTestCase provides an interface that classes implementing test cases from the interop testing spec - * (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification) should implement. Implementations - * must be Java beans, that is, to provide a default constructor and to implement the {@link #getName} method. - * - *

- *
CRC Card
Responsibilities - *
Supply the name of the test case that this implements. - *
Accept/Reject invites based on test parameters. - *
Adapt to assigned roles. - *
Perform test case actions. - *
Generate test reports. - *
- */ -public interface InteropClientTestCase extends MessageListener -{ - /** Defines the possible test case roles that an interop test case can take on. */ - public enum Roles - { - /** Specifies the sender role. */ - SENDER, - - /** Specifies the receivers role. */ - RECEIVER - } - - /** - * Should provide the name of the test case that this class implements. The exact names are defined in the - * interop testing spec. - * - * @return The name of the test case that this implements. - */ - public String getName(); - - /** - * Determines whether the test invite that matched this test case is acceptable. - * - * @param inviteMessage The invitation to accept or reject. - * - * @return true to accept the invitation, false to reject it. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public boolean acceptInvite(Message inviteMessage) throws JMSException; - - /** - * Assigns the role to be played by this test case. The test parameters are fully specified in the - * assignment message. When this method return the test case will be ready to execute. - * - * @param role The role to be played; sender or receivers. - * @param assignRoleMessage The role assingment message, contains the full test parameters. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public void assignRole(Roles role, Message assignRoleMessage) throws JMSException; - - /** - * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. - * - * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. - */ - public void start() throws JMSException; - - /** - * Gets a report on the actions performed by the test case in its assigned role. - * - * @param session The session to create the report message in. - * - * @return The report message. - * - * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through. - */ - public Message getReport(Session session) throws JMSException; -} diff --git a/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java b/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java index 12c0d0aa69..6e726c53bb 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java @@ -21,6 +21,7 @@ package org.apache.qpid.test.framework.distributedtesting; import org.apache.log4j.Logger; +import org.apache.log4j.NDC; import org.apache.qpid.interop.clienttestcases.TestCase1DummyRun; import org.apache.qpid.interop.clienttestcases.TestCase2BasicP2P; @@ -28,17 +29,14 @@ import org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub; 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.distributedcircuit.TestClientCircuitEnd; import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; import uk.co.thebadgerset.junit.extensions.util.TestContextProperties; import javax.jms.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * Implements a test client as described in the interop testing spec @@ -57,8 +55,8 @@ import java.util.Map; * *

*
CRC Card
Responsibilities Collaborations - *
Handle all incoming control messages. {@link InteropClientTestCase} - *
Configure and look up test cases by name. {@link InteropClientTestCase} + *
Handle all incoming control messages. {@link TestClientControlledTest} + *
Configure and look up test cases by name. {@link TestClientControlledTest} *
*/ public class TestClient implements MessageListener @@ -86,10 +84,10 @@ public class TestClient implements MessageListener TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); /** Holds all the test cases loaded from the classpath. */ - Map testCases = new HashMap(); + Map testCases = new HashMap(); /** Holds the test case currently being run by this client. */ - protected InteropClientTestCase currentTestCase; + protected TestClientControlledTest currentTestCase; /** Holds the connection to the broker that the test is being coordinated on. */ protected Connection connection; @@ -97,7 +95,7 @@ public class TestClient implements MessageListener /** Holds the message producer to hold the test coordination over. */ protected MessageProducer producer; - /** Holds the JMS session for the test coordination. */ + /** Holds the JMS controlSession for the test coordination. */ protected Session session; /** Holds the name of this client, with a default value. */ @@ -113,11 +111,12 @@ public class TestClient implements MessageListener * @param brokerUrl The url of the broker to connect to. * @param virtualHost 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) { - log.debug("public SustainedTestClient(String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost - + ", String clientName = " + clientName + "): called"); + log.debug("public TestClient(String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost + + ", String clientName = " + clientName + ", boolean join = " + join + "): called"); // Retain the connection parameters. this.brokerUrl = brokerUrl; @@ -140,6 +139,9 @@ public class TestClient implements MessageListener */ public static void main(String[] args) { + log.debug("public static void main(String[] args = " + Arrays.toString(args) + "): called"); + console.info("Qpid Distributed Test Client."); + // Override the default broker url to be localhost:5672. testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672"); @@ -163,18 +165,22 @@ public class TestClient implements MessageListener String brokerUrl = options.getProperty("b"); String virtualHost = options.getProperty("h"); String clientName = options.getProperty("n"); + clientName = (clientName == null) ? CLIENT_NAME : clientName; boolean join = options.getPropertyAsBoolean("j"); + // To distinguish logging output set up an NDC on the client name. + NDC.push(clientName); + // Create a test client and start it running. - TestClient client = new TestClient(brokerUrl, virtualHost, (clientName == null) ? CLIENT_NAME : clientName, join); + TestClient client = new TestClient(brokerUrl, virtualHost, clientName, join); // Use a class path scanner to find all the interop test case implementations. // Hard code the test classes till the classpath scanner is fixed. - Collection> testCaseClasses = - new ArrayList>(); - // ClasspathScanner.getMatches(InteropClientTestCase.class, "^TestCase.*", true); + Collection> testCaseClasses = + new ArrayList>(); + // ClasspathScanner.getMatches(TestClientControlledTest.class, "^TestCase.*", true); Collections.addAll(testCaseClasses, TestCase1DummyRun.class, TestCase2BasicP2P.class, TestCase3BasicPubSub.class, - SustainedClientTestCase.class); + SustainedClientTestCase.class, TestClientCircuitEnd.class); try { @@ -183,6 +189,7 @@ public class TestClient implements MessageListener catch (Exception e) { log.error("The test client was unable to start.", e); + console.info(e.getMessage()); System.exit(1); } } @@ -195,16 +202,17 @@ public class TestClient implements MessageListener * * @throws JMSException Any underlying JMSExceptions are allowed to fall through. */ - protected void start(Collection> testCaseClasses) throws JMSException + protected void start(Collection> testCaseClasses) throws JMSException { - log.debug("private void start(): called"); + log.debug("protected void start(Collection> testCaseClasses = " + + testCaseClasses + "): called"); // Create all the test case implementations and index them by the test names. - for (Class nextClass : testCaseClasses) + for (Class nextClass : testCaseClasses) { try { - InteropClientTestCase testCase = nextClass.newInstance(); + TestClientControlledTest testCase = nextClass.newInstance(); testCases.put(testCase.getName(), testCase); } catch (InstantiationException e) @@ -259,6 +267,7 @@ public class TestClient implements MessageListener */ public void onMessage(Message message) { + NDC.push(clientName); log.debug("public void onMessage(Message message = " + message + "): called"); try @@ -266,7 +275,7 @@ public class TestClient implements MessageListener String controlType = message.getStringProperty("CONTROL_TYPE"); String testName = message.getStringProperty("TEST_NAME"); - log.info("onMessage(Message message = " + message + "): for '" + controlType + "' to '" + testName + "'"); + log.debug("Received control of type '" + controlType + "' for the test '" + testName + "'"); // Check if the message is a test invite. if ("INVITE".equals(controlType)) @@ -280,13 +289,21 @@ public class TestClient implements MessageListener log.debug("Got an invite to test: " + testName); // Check if the requested test case is available. - InteropClientTestCase testCase = testCases.get(testName); + TestClientControlledTest testCase = testCases.get(testName); if (testCase != null) { + log.debug("Found implementing class for test '" + testName + "', enlisting for it."); + + // Check if the test case will accept the invitation. + enlist = testCase.acceptInvite(message); + + log.debug("The test case " + + (enlist ? " accepted the invite, enlisting for it." + : " did not accept the invite, not enlisting.")); + // Make the requested test case the current test case. currentTestCase = testCase; - enlist = true; } else { @@ -295,7 +312,7 @@ public class TestClient implements MessageListener } else { - log.debug("Got a compulsory invite."); + log.debug("Got a compulsory invite, enlisting for it."); enlist = true; } @@ -309,7 +326,20 @@ public class TestClient implements MessageListener enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName); enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID()); - log.info("Sending Message '" + enlistMessage + "'. to " + message.getJMSReplyTo()); + log.debug("Sending enlist message '" + enlistMessage + "' to " + message.getJMSReplyTo()); + + producer.send(message.getJMSReplyTo(), enlistMessage); + } + else + { + // Reply with the client name in an Decline message. + Message enlistMessage = session.createMessage(); + enlistMessage.setStringProperty("CONTROL_TYPE", "DECLINE"); + enlistMessage.setStringProperty("CLIENT_NAME", clientName); + enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName); + enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID()); + + log.debug("Sending decline message '" + enlistMessage + "' to " + message.getJMSReplyTo()); producer.send(message.getJMSReplyTo(), enlistMessage); } @@ -321,15 +351,18 @@ public class TestClient implements MessageListener log.debug("Got a role assignment to role: " + roleName); - InteropClientTestCase.Roles role = Enum.valueOf(InteropClientTestCase.Roles.class, roleName); + TestClientControlledTest.Roles role = Enum.valueOf(TestClientControlledTest.Roles.class, roleName); currentTestCase.assignRole(role, message); // Reply by accepting the role in an Accept Role message. Message acceptRoleMessage = session.createMessage(); + acceptRoleMessage.setStringProperty("CLIENT_NAME", clientName); acceptRoleMessage.setStringProperty("CONTROL_TYPE", "ACCEPT_ROLE"); acceptRoleMessage.setJMSCorrelationID(message.getJMSCorrelationID()); + log.debug("Sending accept role message '" + acceptRoleMessage + "' to " + message.getJMSReplyTo()); + producer.send(message.getJMSReplyTo(), acceptRoleMessage); } else if ("START".equals(controlType) || "STATUS_REQUEST".equals(controlType)) @@ -338,8 +371,21 @@ public class TestClient implements MessageListener { log.debug("Got a start notification."); + // Extract the number of test messages to send from the start notification. + int numMessages; + + try + { + numMessages = message.getIntProperty("MESSAGE_COUNT"); + } + catch (JMSException e) + { + // If the number of messages is not specified, use the default of one. + numMessages = 1; + } + // Start the current test case. - currentTestCase.start(); + currentTestCase.start(numMessages); } else { @@ -348,9 +394,12 @@ public class TestClient implements MessageListener // Generate the report from the test case and reply with it as a Report message. Message reportMessage = currentTestCase.getReport(session); + reportMessage.setStringProperty("CLIENT_NAME", clientName); reportMessage.setStringProperty("CONTROL_TYPE", "REPORT"); reportMessage.setJMSCorrelationID(message.getJMSCorrelationID()); + log.debug("Sending report message '" + reportMessage + "' to " + message.getJMSReplyTo()); + producer.send(message.getJMSReplyTo(), reportMessage); } else if ("TERMINATE".equals(controlType)) @@ -370,8 +419,18 @@ public class TestClient implements MessageListener catch (JMSException e) { // Log a warning about this, but otherwise ignore it. - log.warn("A JMSException occurred whilst handling a message."); - log.debug("Got JMSException whilst handling message: " + message, e); + log.warn("Got JMSException whilst handling message: " + message, e); + } + // Log any runtimes that fall through this message handler. These are fatal errors for the test client. + catch (RuntimeException e) + { + log.error("The test client message handler got an unhandled exception: ", e); + console.info("The message handler got an unhandled exception, terminating the test client."); + System.exit(1); + } + finally + { + NDC.pop(); } } } diff --git a/java/perftests/jar-with-dependencies.xml b/java/perftests/jar-with-dependencies.xml index 3e95e7ab22..959473f535 100644 --- a/java/perftests/jar-with-dependencies.xml +++ b/java/perftests/jar-with-dependencies.xml @@ -16,32 +16,51 @@ specific language governing permissions and limitations under the License. --> - + - all-test-deps - - jar - - false - - - - - true - test - - - - - target/classes - - - - target/test-classes - - - + all-test-deps + + tar.gz + zip + + false + + + / + false + test + + + + + target/classes + + + + target/test-classes + + + + + + target + + + qpid-perftests-1.0-incubating-M2-SNAPSHOT.jar + + + + + + target + + + qpid-perftests-1.0-incubating-M2-SNAPSHOT-tests.jar + + + + diff --git a/java/perftests/pom.xml b/java/perftests/pom.xml index e07b0696e5..41bd6c1a84 100644 --- a/java/perftests/pom.xml +++ b/java/perftests/pom.xml @@ -71,6 +71,11 @@ qpid-client + + org.apache.qpid + qpid-systests + + log4j log4j @@ -85,9 +90,10 @@ junit junit + compile - + org.slf4j slf4j-log4j12 1.4.0 @@ -354,13 +360,34 @@ jar-with-dependencies.xml - dist-zip.xml + target target/assembly/work + + + org.apache.maven.plugins + maven-jar-plugin + + + test_jar + + + + true + + + + + test-jar + + + + + diff --git a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java index 78ab7c4c73..82b36bf233 100644 --- a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java +++ b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java @@ -92,10 +92,10 @@ public class PingPongBouncer implements MessageListener /** The producer for sending replies with. */ private MessageProducer _replyProducer; - /** The consumer session. */ + /** The consumer controlSession. */ private Session _consumerSession; - /** The producer session. */ + /** The producer controlSession. */ private Session _producerSession; /** Holds the connection to the broker. */ @@ -149,7 +149,7 @@ public class PingPongBouncer implements MessageListener // Set up the failover notifier. getConnection().setConnectionListener(new FailoverNotifier()); - // Create a session to listen for messages on and one to send replies on, transactional depending on the + // Create a controlSession to listen for messages on and one to send replies on, transactional depending on the // command line option. _consumerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE); _producerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE); @@ -323,8 +323,8 @@ public class PingPongBouncer implements MessageListener } /** - * Convenience method to commit the transaction on the specified session. If the session to commit on is not - * a transactional session, this method does nothing. + * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not + * a transactional controlSession, this method does nothing. * *

If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker diff --git a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java index 03f5f0549d..140e3bad1c 100644 --- a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java +++ b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java @@ -395,10 +395,10 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis /** Holds the connection to the broker. */ protected Connection _connection; - /** Holds the session on which ping replies are received. */ + /** Holds the controlSession on which ping replies are received. */ protected Session _consumerSession; - /** Holds the producer session, needed to create ping messages. */ + /** Holds the producer controlSession, needed to create ping messages. */ protected Session _producerSession; /** Holds the destination where the response messages will arrive. */ @@ -1305,8 +1305,8 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis } /** - * Convenience method to commit the transaction on the specified session. If the session to commit on is not a - * transactional session, this method does nothing (unless the failover after send flag is set). + * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not a + * transactional controlSession, this method does nothing (unless the failover after send flag is set). * *

If the {@link #_failAfterSend} flag is set, this will prompt the user to kill the broker before the commit is * applied. This flag applies whether the pinger is transactional or not. @@ -1315,9 +1315,9 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis * is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker after the * commit is applied. These flags will only apply if using a transactional pinger. * - * @param session The session to commit + * @param session The controlSession to commit * - * @return true if the session was committed, false if it was not. + * @return true if the controlSession was committed, false if it was not. * * @throws javax.jms.JMSException If the commit fails and then the rollback fails. * @@ -1327,7 +1327,7 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis */ protected boolean commitTx(Session session) throws JMSException { - // log.debug("protected void commitTx(Session session): called"); + // log.debug("protected void commitTx(Session controlSession): called"); boolean committed = false; diff --git a/java/perftests/src/test/java/org/apache/qpid/perftests/QpidTestThroughputPerf.java b/java/perftests/src/test/java/org/apache/qpid/perftests/QpidTestThroughputPerf.java new file mode 100644 index 0000000000..760d1c84a4 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/perftests/QpidTestThroughputPerf.java @@ -0,0 +1,170 @@ +/* + * + * 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.perftests; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.apache.log4j.Logger; + +import org.apache.qpid.test.framework.Assertion; +import org.apache.qpid.test.framework.Circuit; +import org.apache.qpid.test.framework.FrameworkBaseCase; +import org.apache.qpid.test.framework.MessagingTestConfigProperties; +import org.apache.qpid.test.framework.sequencers.CircuitFactory; + +import uk.co.thebadgerset.junit.extensions.TestThreadAware; +import uk.co.thebadgerset.junit.extensions.TimingController; +import uk.co.thebadgerset.junit.extensions.TimingControllerAware; +import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; +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. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ * + * @todo Check that all of the messages were sent. Check that the receiving end got the same number of messages as + * the publishing end. + */ +public class QpidTestThroughputPerf extends FrameworkBaseCase implements TimingControllerAware, TestThreadAware +{ + /** Used for debugging. */ + private static final Logger log = Logger.getLogger(QpidTestThroughputPerf.class); + + /** Holds the timing controller, used to log test timings from self-timed tests. */ + private TimingController timingController; + + /** Thread local to hold the per-thread test setup fields. */ + ThreadLocal threadSetup = new ThreadLocal(); + + /** + * Creates a new test case with the specified name. + * + * @param name The test case name. + */ + public QpidTestThroughputPerf(String name) + { + super(name); + } + + /** + * Performs the a basic P2P test case. + * + * @param numMessages The number of messages to send in the test. + */ + public void testThroughput(int numMessages) + { + log.debug("public void testThroughput(): called"); + + PerThreadSetup setup = threadSetup.get(); + assertNoFailures(setup.testCircuit.test(numMessages, new LinkedList())); + } + + /** + * Should provide a translation from the junit method name of a test to its test case name as known to the test + * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test + * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case + * name "TC2_BasicP2P". + * + * @param methodName The name of the JUnit test method. + * + * @return The name of the corresponding interop test case. + */ + public String getTestCaseNameForTestMethod(String methodName) + { + log.debug("public String getTestCaseNameForTestMethod(String methodName = " + methodName + "): called"); + + return "DEFAULT_CIRCUIT_TEST"; + } + + /** + * Used by test runners that can supply a {@link uk.co.thebadgerset.junit.extensions.TimingController} to set the + * controller on an aware test. + * + * @param controller The timing controller. + */ + public void setTimingController(TimingController controller) + { + timingController = controller; + } + + /** + * Performs test fixture creation on a per thread basis. This will only be called once for each test thread. + */ + public void threadSetUp() + { + // Get the test parameters, any overrides on the command line will have been applied. + ParsedProperties testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); + + // Customize the test parameters. + testProps.setProperty("TEST_NAME", "DEFAULT_CIRCUIT_TEST"); + testProps.setProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME, "testqueue"); + + // Get the test circuit factory to create test circuits and run the standard test procedure through. + CircuitFactory circuitFactory = getCircuitFactory(); + + // Create the test circuit. This projects the circuit onto the available test nodes and connects it up. + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + // Store the test configuration for the thread. + PerThreadSetup setup = new PerThreadSetup(); + setup.testCircuit = testCircuit; + threadSetup.set(setup); + } + + /** + * Called when a test thread is destroyed. + */ + public void threadTearDown() + { } + + /** + * Holds the per-thread test configurations. + */ + protected static class PerThreadSetup + { + /** Holds the test circuit to run tests on. */ + Circuit testCircuit; + } + + /** + * Compiles all the tests in this class into a suite. + * + * @return The test suite. + */ + public static Test suite() + { + // Build a new test suite + TestSuite suite = new TestSuite("Qpid Throughput Performance Tests"); + + suite.addTest(new QpidTestThroughputPerf("testThroughput")); + + return suite; + } +} diff --git a/java/systests/etc/bin/testclients.sh b/java/systests/etc/bin/testclients.sh new file mode 100644 index 0000000000..4b10c833de --- /dev/null +++ b/java/systests/etc/bin/testclients.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# +# 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. +# +for x in `seq 1 $1`; +do + java -cp qpid-integrationtests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar -Dlog4j.configuration=file:/home/rupert/qpid/trunk/qpid/java/etc/mylog4j.xml org.apache.qpid.test.framework.distributedtesting.TestClient -n $x & +done diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java index 4a0a27bb06..9b5c9c3d00 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java @@ -20,11 +20,11 @@ */ package org.apache.qpid.server.exchange; -import org.apache.qpid.test.framework.sequencers.TestCaseSequencer; 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; @@ -85,9 +85,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, false); // Run the default test sequence over the test circuit checking for no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */ @@ -98,43 +99,44 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, false); // Send one message with no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */ - public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P() throws Exception + public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P() { // Ensure transactional sessions are off. testProps.setProperty(TRANSACTED_PROPNAME, false); testProps.setProperty(PUBSUB_PROPNAME, false); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message and get a linked no consumers exception. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion()))); } /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */ - public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P() throws Exception + public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P() { // Ensure transactional sessions are on. testProps.setProperty(TRANSACTED_PROPNAME, true); testProps.setProperty(PUBSUB_PROPNAME, false); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message and get a linked no consumers exception. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion()))); } /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */ @@ -149,9 +151,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */ @@ -166,9 +169,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } /** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */ @@ -179,9 +183,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, true); // Send one message with no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */ @@ -192,13 +197,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, true); // Send one message with no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */ - public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxPubSub() throws Exception + public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxPubSub() { // Ensure transactional sessions are off. testProps.setProperty(TRANSACTED_PROPNAME, false); @@ -207,18 +213,18 @@ public class ImmediateMessageTest extends FrameworkBaseCase // Use durable subscriptions, so that the route remains open with no subscribers. testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message and get a linked no consumers exception. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion()))); } /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */ - public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxPubSub() throws Exception + public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxPubSub() { // Ensure transactional sessions are on. testProps.setProperty(TRANSACTED_PROPNAME, true); @@ -227,14 +233,14 @@ public class ImmediateMessageTest extends FrameworkBaseCase // Use durable subscriptions, so that the route remains open with no subscribers. testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message and get a linked no consumers exception. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion()))); } /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */ @@ -249,9 +255,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */ @@ -266,9 +273,10 @@ public class ImmediateMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } protected void setUp() throws Exception @@ -283,5 +291,6 @@ public class ImmediateMessageTest extends FrameworkBaseCase /** 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/server/exchange/MandatoryMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java index 94a33806d0..df99d044d2 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java @@ -20,11 +20,11 @@ */ package org.apache.qpid.server.exchange; -import org.apache.qpid.test.framework.sequencers.TestCaseSequencer; 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; @@ -85,9 +85,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, false); // Run the default test sequence over the test circuit checking for no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */ @@ -98,49 +99,50 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, false); // Run the default test sequence over the test circuit checking for no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** * Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected but * the route exists. */ - public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxP2P() throws Exception + public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxP2P() { // Ensure transactional sessions are off. testProps.setProperty(TRANSACTED_PROPNAME, false); testProps.setProperty(PUBSUB_PROPNAME, false); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message with no errors. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** * Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but * the route exists. */ - public void test_QPID_517_MandatoryOkConsumerDisconnectedTxP2P() throws Exception + public void test_QPID_517_MandatoryOkConsumerDisconnectedTxP2P() { // Ensure transactional sessions are on. testProps.setProperty(TRANSACTED_PROPNAME, true); testProps.setProperty(PUBSUB_PROPNAME, false); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message with no errors. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */ @@ -155,9 +157,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } /** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */ @@ -172,9 +175,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } /** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */ @@ -185,9 +189,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, true); // Run the default test sequence over the test circuit checking for no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */ @@ -198,16 +203,17 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(PUBSUB_PROPNAME, true); // Run the default test sequence over the test circuit checking for no errors. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** * Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected but * the route exists. */ - public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxPubSub() throws Exception + public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxPubSub() { // Ensure transactional sessions are off. testProps.setProperty(TRANSACTED_PROPNAME, false); @@ -216,21 +222,21 @@ public class MandatoryMessageTest extends FrameworkBaseCase // Use durable subscriptions, so that the route remains open with no subscribers. testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message with no errors. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** * Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but * the route exists. */ - public void test_QPID_517_MandatoryOkConsumerDisconnectedTxPubSub() throws Exception + public void test_QPID_517_MandatoryOkConsumerDisconnectedTxPubSub() { // Ensure transactional sessions are on. testProps.setProperty(TRANSACTED_PROPNAME, true); @@ -239,14 +245,14 @@ public class MandatoryMessageTest extends FrameworkBaseCase // Use durable subscriptions, so that the route remains open with no subscribers. testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true); - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - // Disconnect the consumer. - testCircuit.getReceiver().getConsumer().close(); + testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false); + + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); // Send one message with no errors. - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps); + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion()))); } /** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */ @@ -261,9 +267,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } /** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */ @@ -278,9 +285,10 @@ public class MandatoryMessageTest extends FrameworkBaseCase testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false); // Send one message and get a linked no route exception. - TestCaseSequencer sequencer = getTestSequencer(); - Circuit testCircuit = sequencer.createCircuit(testProps); - sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps); + CircuitFactory circuitFactory = getCircuitFactory(); + Circuit testCircuit = circuitFactory.createCircuit(testProps); + + assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion()))); } protected void setUp() throws Exception @@ -295,5 +303,6 @@ public class MandatoryMessageTest extends FrameworkBaseCase /** 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/test/framework/CircuitEnd.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java index 43c3fa4c66..e557620cf5 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java @@ -74,4 +74,18 @@ public interface CircuitEnd * @throws JMSException Any JMSExceptions occurring during the close are allowed to fall through. */ public void close() throws JMSException; + + /** + * Returns the message monitor for reporting on received messages on this circuit end. + * + * @return The message monitor for this circuit end. + */ + public MessageMonitor getMessageMonitor(); + + /** + * Returns the exception monitor for reporting on exceptions received on this circuit end. + * + * @return The exception monitor for this circuit end. + */ + public ExceptionMonitor getExceptionMonitor(); } 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 54a30d9c6e..251b216c45 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 @@ -41,21 +41,31 @@ public class CircuitEndBase implements CircuitEnd /** Holds the single message consumer. */ MessageConsumer consumer; - /** Holds the session for the circuit end. */ + /** Holds the controlSession for the circuit end. */ Session session; + /** Holds the message monitor for the circuit end. */ + MessageMonitor messageMonitor; + + /** Holds the exception monitor for the circuit end. */ + ExceptionMonitor exceptionMonitor; + /** - * Creates a circuit end point on the specified producer, consumer and session. + * Creates a circuit end point on the specified producer, consumer and controlSession. * * @param producer The message producer for the circuit end point. * @param consumer The message consumer for the circuit end point. - * @param session The session for the circuit end point. + * @param session The controlSession for the circuit end point. */ - public CircuitEndBase(MessageProducer producer, MessageConsumer consumer, Session session) + public CircuitEndBase(MessageProducer producer, MessageConsumer consumer, Session session, MessageMonitor messageMonitor, + ExceptionMonitor exceptionMonitor) { this.producer = producer; this.consumer = consumer; this.session = session; + + this.messageMonitor = messageMonitor; + this.exceptionMonitor = exceptionMonitor; } /** @@ -116,4 +126,24 @@ public class CircuitEndBase implements CircuitEnd consumer.close(); } } + + /** + * Returns the message monitor for reporting on received messages on this circuit end. + * + * @return The message monitor for this circuit end. + */ + public MessageMonitor getMessageMonitor() + { + return messageMonitor; + } + + /** + * Returns the exception monitor for reporting on exceptions received on this circuit end. + * + * @return The exception monitor for this circuit end. + */ + public ExceptionMonitor getExceptionMonitor() + { + return 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 606f2eabda..437b2cc142 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 @@ -20,6 +20,8 @@ */ package org.apache.qpid.test.framework; +import org.apache.log4j.Logger; + import javax.jms.ExceptionListener; import javax.jms.JMSException; @@ -39,6 +41,9 @@ import java.util.List; */ public class ExceptionMonitor implements ExceptionListener { + /** Used for debugging. */ + private final Logger log = Logger.getLogger(ExceptionMonitor.class); + /** Holds the received exceptions. */ List exceptions = new ArrayList(); @@ -49,6 +54,8 @@ public class ExceptionMonitor implements ExceptionListener */ public void onException(JMSException e) { + log.debug("public void onException(JMSException e): called"); + exceptions.add(e); } 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 d6cb0cad13..77bb7a5c52 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 @@ -22,13 +22,16 @@ 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.test.framework.sequencers.TestCaseSequencer; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.test.framework.localcircuit.CircuitImpl; +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; @@ -47,10 +50,13 @@ import java.util.Properties; * Convert failed assertions to error messages. * */ -public class FrameworkBaseCase extends TestCase +public class FrameworkBaseCase extends AsymptoticTestCase { + /** Used for debugging purposes. */ + private static final Logger log = Logger.getLogger(FrameworkBaseCase.class); + /** Holds the test sequencer to create and run test circuits with. */ - protected TestCaseSequencer testSequencer = new DefaultTestSequencer(); + protected CircuitFactory circuitFactory = new DefaultCircuitFactory(); /** * Creates a new test case with the specified name. @@ -69,20 +75,20 @@ public class FrameworkBaseCase extends TestCase * * @return The test case sequencer. */ - protected TestCaseSequencer getTestSequencer() + protected CircuitFactory getCircuitFactory() { - return testSequencer; + return circuitFactory; } /** - * Overrides the default test sequencer. Test decorators can use this to supply distributed test sequencers or other - * test sequencer specializations. + * Overrides the default test circuit factory. Test decorators can use this to supply distributed test sequencers or + * other test circuit factory specializations. * - * @param sequencer The new test sequencer. + * @param circuitFactory The new test circuit factory. */ - public void setTestSequencer(TestCaseSequencer sequencer) + public void setCircuitFactory(CircuitFactory circuitFactory) { - this.testSequencer = sequencer; + this.circuitFactory = circuitFactory; } /** @@ -112,6 +118,8 @@ public class FrameworkBaseCase extends TestCase */ protected void assertNoFailures(List asserts) { + log.debug("protected void assertNoFailures(List asserts = " + asserts + "): called"); + // Check if there are no assertion failures, and return without doing anything if so. if ((asserts == null) || asserts.isEmpty()) { @@ -175,10 +183,25 @@ public class FrameworkBaseCase extends TestCase } /** - * DefaultTestSequencer is a test sequencer that creates test circuits with publishing and receiving ends rooted + * Should provide a translation from the junit method name of a test to its test case name as known to the test + * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test + * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case + * name "TC2_BasicP2P". + * + * @param methodName The name of the JUnit test method. + * + * @return The name of the corresponding interop test case. + */ + public String getTestCaseNameForTestMethod(String methodName) + { + return methodName; + } + + /** + * DefaultCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted * on the same JVM. */ - public class DefaultTestSequencer implements TestCaseSequencer + public class DefaultCircuitFactory implements CircuitFactory { /** * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, @@ -201,7 +224,57 @@ public class FrameworkBaseCase extends TestCase */ public Circuit createCircuit(ParsedProperties testProperties) { - return CircuitImpl.createCircuit(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 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/FrameworkClientBaseCase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkClientBaseCase.java new file mode 100644 index 0000000000..2456ba1709 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkClientBaseCase.java @@ -0,0 +1,11 @@ +package org.apache.qpid.test.framework; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ */ +public class FrameworkClientBaseCase +{ +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java b/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java index 873f876012..245b6fa7fd 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java @@ -20,27 +20,86 @@ */ package org.apache.qpid.test.framework; +import org.apache.log4j.Logger; + import javax.jms.Message; import javax.jms.MessageListener; +import java.util.concurrent.atomic.AtomicInteger; + /** * MessageMonitor is used to record information about messages received. This will provide methods to check various * properties, such as the type, number and content of messages received in order to verify the correct behaviour of * tests. * - *

At the moment this monitor does not do anything. - * *

*
CRC Card
Responsibilities Collaborations + *
Count incoming messages. + *
Record time ellapsed since the arrival of the first message. + *
Reset all counts and timings. *
*/ public class MessageMonitor implements MessageListener { + /** Used for debugging. */ + private final Logger log = Logger.getLogger(MessageMonitor.class); + + /** Holds the count of messages received since the last query. */ + protected AtomicInteger numMessages = new AtomicInteger(); + + /** Holds the time of arrival of the first message. */ + protected Long firstMessageTime = null; + /** * Handles received messages. Does Nothing. * * @param message The message. Ignored. */ public void onMessage(Message message) - { } + { + log.debug("public void onMessage(Message message): called"); + + numMessages.getAndIncrement(); + } + + /** + * Gets the count of messages. + * + * @return The count of messages. + */ + public int getNumMessage() + { + if (firstMessageTime == null) + { + firstMessageTime = System.nanoTime(); + } + + return numMessages.get(); + } + + /** + * Gets the time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet. + * + * @return The time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet. + */ + public long getTime() + { + if (firstMessageTime != null) + { + return System.nanoTime() - firstMessageTime; + } + else + { + return 0L; + } + } + + /** + * Resets the message count and timer to zero. + */ + public void reset() + { + numMessages.set(0); + firstMessageTime = null; + } } 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 3cc4a92886..f6664a78d9 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 @@ -24,6 +24,8 @@ import org.apache.qpid.jms.Session; import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; +import java.util.Properties; + /** * MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology, * and test parameters for running a messaging test over that topology. A Properties object holding some of these @@ -67,8 +69,11 @@ import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; * Responsibilities Collaborations * Provide the names and defaults of all test parameters. * + * + * @todo Put a type-safe wrapper around these properties, but continue to store the parameters as properties. This is + * simply to ensure that it is a simple matter to serialize/deserialize string/string pairs onto messages. */ -public class MessagingTestConfigProperties +public class MessagingTestConfigProperties extends ParsedProperties { // ====================== Connection Properties ================================== @@ -131,6 +136,18 @@ public class MessagingTestConfigProperties /** Holds the default value of the receivers consumer flag. */ public static final boolean RECEIVER_CONSUMER_BIND_DEFAULT = true; + /** Holds the name of the property to get the publishers consumer active flag from. */ + public static final String PUBLISHER_CONSUMER_ACTIVE_PROPNAME = "publisherConsumerActive"; + + /** Holds the default value of the publishers consumer active flag. */ + public static final boolean PUBLISHER_CONSUMER_ACTIVE_DEFAULT = true; + + /** Holds the name of the property to get the receivers consumer active flag from. */ + public static final String RECEIVER_CONSUMER_ACTIVE_PROPNAME = "receiverConsumerActive"; + + /** Holds the default value of the receivers consumer active flag. */ + public static final boolean RECEIVER_CONSUMER_ACTIVE_DEFAULT = true; + /** Holds the name of the property to get the destination name root from. */ public static final String SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot"; @@ -214,7 +231,7 @@ public class MessagingTestConfigProperties public static final boolean DURABLE_DESTS_DEFAULT = false; /** Holds the name of the proeprty to set the prefetch size from. */ - public static final String PREFECTH_PROPNAME = "prefetch"; + public static final String PREFETCH_PROPNAME = "prefetch"; /** Defines the default prefetch size to use when consuming messages. */ public static final int PREFETCH_DEFAULT = 100; @@ -275,6 +292,8 @@ public class MessagingTestConfigProperties defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT); defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT); defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT); + defaults.setPropertyIfNull(PUBLISHER_CONSUMER_ACTIVE_PROPNAME, PUBLISHER_CONSUMER_ACTIVE_DEFAULT); + 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); @@ -294,10 +313,173 @@ public class MessagingTestConfigProperties 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(PREFECTH_PROPNAME, PREFETCH_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); } + + /** + * Creates a test configuration based on the defaults. + */ + public MessagingTestConfigProperties() + { + super(defaults); + } + + /** + * Creates a test configuration based on the supplied properties. + * + * @param properties The test configuration. + */ + public MessagingTestConfigProperties(Properties properties) + { + super(properties); + } + + public int getMessageSize() + { + return getPropertyAsInteger(MESSAGE_SIZE_PROPNAME); + } + + public boolean getPublisherProducerBind() + { + return getPropertyAsBoolean(PUBLISHER_PRODUCER_BIND_PROPNAME); + } + + public boolean getPublisherConsumerBind() + { + return getPropertyAsBoolean(PUBLISHER_CONSUMER_BIND_PROPNAME); + } + + public boolean getReceiverProducerBind() + { + return getPropertyAsBoolean(RECEIVER_PRODUCER_BIND_PROPNAME); + } + + public boolean getReceiverConsumerBind() + { + return getPropertyAsBoolean(RECEIVER_CONSUMER_BIND_PROPNAME); + } + + public boolean getPublisherConsumerActive() + { + return getPropertyAsBoolean(PUBLISHER_CONSUMER_ACTIVE_PROPNAME); + } + + public boolean getReceiverConsumerActive() + { + return getPropertyAsBoolean(RECEIVER_CONSUMER_ACTIVE_PROPNAME); + } + + public String getSendDestinationNameRoot() + { + return getProperty(SEND_DESTINATION_NAME_ROOT_PROPNAME); + } + + public String getReceiveDestinationNameRoot() + { + return getProperty(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME); + } + + public boolean getPersistentMode() + { + return getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME); + } + + public boolean getTransacted() + { + return getPropertyAsBoolean(TRANSACTED_PROPNAME); + } + + public String getBroker() + { + return getProperty(BROKER_PROPNAME); + } + + public String getVirtualHost() + { + return getProperty(VIRTUAL_HOST_PROPNAME); + } + + public String getRate() + { + return getProperty(RATE_PROPNAME); + } + + public boolean getPubsub() + { + return getPropertyAsBoolean(PUBSUB_PROPNAME); + } + + public String getUsername() + { + return getProperty(USERNAME_PROPNAME); + } + + public String getPassword() + { + return getProperty(PASSWORD_PROPNAME); + } + + public int getDestinationCount() + { + return getPropertyAsInteger(DESTINATION_COUNT_PROPNAME); + } + + public long getTimeout() + { + return getPropertyAsLong(TIMEOUT_PROPNAME); + } + + public int getTxBatchSize() + { + return getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME); + } + + public boolean getDurableDests() + { + return getPropertyAsBoolean(DURABLE_DESTS_PROPNAME); + } + + public int getAckMode() + { + return getPropertyAsInteger(ACK_MODE_PROPNAME); + } + + public boolean getDurableSubscription() + { + return getPropertyAsBoolean(DURABLE_SUBSCRIPTION_PROPNAME); + } + + public int getMaxPending() + { + return getPropertyAsInteger(MAX_PENDING_PROPNAME); + } + + public int getPrefecth() + { + return getPropertyAsInteger(PREFETCH_PROPNAME); + } + + public boolean getNoLocal() + { + return getPropertyAsBoolean(NO_LOCAL_PROPNAME); + } + + public boolean getExclusive() + { + return getPropertyAsBoolean(EXCLUSIVE_PROPNAME); + } + + public boolean getImmediate() + { + return getPropertyAsBoolean(IMMEDIATE_PROPNAME); + } + + public boolean getMandatory() + { + return getPropertyAsBoolean(MANDATORY_PROPNAME); + } } 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 59aa9065dd..df35579533 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 @@ -21,17 +21,17 @@ package org.apache.qpid.test.framework; /** - * A Publisher is a {@link CircuitEnd} that represents one end of a test circuit. Its main purpose is to - * provide assertions that can be applied to test the behaviour of the publisher. + * 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. * *

*
CRC Card
Responsibilities - *
Provide assertion that the publisher received no exceptions. - *
Provide assertion that the publisher received a no consumers error code. - *
Provide assertion that the publisher received a no route error code. + *
Provide assertion that the publishers received no exceptions. + *
Provide assertion that the publishers received a no consumers error code on every message. + *
Provide assertion that the publishers received a no route error code on every message. *
*/ -public interface Publisher extends CircuitEnd +public interface Publisher { /** * Provides an assertion that the publisher encountered no exceptions. 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 6e01a7ea4f..e01b272d5a 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 @@ -21,8 +21,8 @@ package org.apache.qpid.test.framework; /** - * A Receiver is a {@link CircuitEnd} that represents one end of a test circuit. Its main purpose is to - * provide assertions that can be applied to test the behaviour of the receivers. + * 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. * *

*
CRC Card
Responsibilities @@ -30,7 +30,7 @@ package org.apache.qpid.test.framework; *
Provide assertion that the receivers received all test messages sent to it. *
*/ -public interface Receiver extends CircuitEnd +public interface Receiver { /** * Provides an assertion that the receivers encountered no exceptions. diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java index aadd378aed..921d16c998 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java @@ -20,11 +20,21 @@ */ package org.apache.qpid.test.framework.distributedcircuit; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.Publisher; -import org.apache.qpid.test.framework.Receiver; +import org.apache.log4j.Logger; +import org.apache.qpid.test.framework.*; +import org.apache.qpid.util.ConversationFactory; + +import uk.co.thebadgerset.junit.extensions.TimingController; +import uk.co.thebadgerset.junit.extensions.TimingControllerAware; +import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Session; + +import java.util.LinkedList; import java.util.List; /** @@ -42,9 +52,199 @@ import java.util.List; * Send test messages over the circuit. * Perform the default test procedue on the circuit. * + * + * @todo There is a short pause after receiving sender reports before asking for receiver reports, because receivers may + * not have finished receiving all their test messages before the report request arrives. This is going to be a + * problem for taking test timings and needs to be eliminiated. Suggested solution: have receiver send back reports + * asynchronously, on test batch size boundaries, and do so automatically rather than having to have the report + * request sent to them. Number each test run, or otherwise uniquely identify it, when a receiver does not get + * any more messages on a test run for more than a timeout, it can assume the test is complete and send a final + * report. On the coordinator end a future will need to be created to wait for all final reports to come in, and + * to register results and timings for the test. This must work in such a way that a new test cycle can be started + * without waiting for the results of the old one to come in. + * + * @todo Test circuits to be created per test thread, not per test method call. Per-thread setup and tear down to be + * reposible for circuit creation and clean up. Many individual test method calls to run over the same circuit. + * Important, otherwise test results will be skewed by circuit creation overheads. + * */ -public class DistributedCircuitImpl implements Circuit +public class DistributedCircuitImpl implements Circuit, TimingControllerAware { + /** Used for debugging purposes. */ + private static Logger log = Logger.getLogger(DistributedCircuitImpl.class); + + /** Holds the conversation factory over which to coordinate the test. */ + protected ConversationFactory conversationFactory; + + /** Holds the controlSession over which to hold the control conversation. */ + protected Session controlSession; + + /** Holds the sender nodes in the test circuit. */ + protected List senders; + + /** Holds the receiver nodes in the test circuit. */ + protected List receivers; + + /** Holds the sender control conversations. */ + protected ConversationFactory.Conversation[] senderConversation; + + /** Holds the receiver control conversations. */ + protected ConversationFactory.Conversation[] receiverConversation; + + /** Holds the control topics for the senders in the test circuit. */ + protected Destination[] senderControlTopic; + + /** Holds the control topics for the receivers in the test circuit. */ + protected Destination[] receiverControlTopic; + + /** Holds the number of messages to send per test run. */ + protected int numMessages; + + /** + * Holds the timing controller for the circuit. This is used to log test times asynchronously, when reciever nodes + * return their reports after senders have completed a test case. + */ + TimingController timingController; + + /** + * Creates a distributed test circuit on the specified senders and receivers. + * + * @param session The controlSession for all control conversations. + * @param senders The senders. + * @param receivers The receivers. + * @param senderConversation A control conversation with the senders. + * @param receiverConversation A control conversation with the receivers. + * @param senderControlTopic The senders control topic. + * @param receiverControlTopic The receivers control topic. + */ + protected DistributedCircuitImpl(Session session, List senders, List receivers, + ConversationFactory.Conversation[] senderConversation, ConversationFactory.Conversation[] receiverConversation, + Destination[] senderControlTopic, Destination[] receiverControlTopic) + { + this.controlSession = session; + this.senders = senders; + this.receivers = receivers; + this.senderConversation = senderConversation; + this.receiverConversation = receiverConversation; + this.senderControlTopic = senderControlTopic; + this.receiverControlTopic = receiverControlTopic; + } + + /** + * Creates a distributed test circuit from the specified test parameters, on the senders and receivers + * given. + * + * @param testProps The test parameters. + * @param senders The sender ends in the test circuit. + * @param receivers The receiver ends in the test circuit. + * @param conversationFactory A conversation factory for creating the control conversations with senders and receivers. + * + * @return A connected and ready to start, test circuit. + */ + public static Circuit createCircuit(ParsedProperties testProps, List senders, + List receivers, ConversationFactory conversationFactory) + { + log.debug("public static Circuit createCircuit(ParsedProperties testProps, List senders, " + + " List receivers, ConversationFactory conversationFactory)"); + + try + { + Session session = conversationFactory.getSession(); + + // Create control conversations with each of the senders. + ConversationFactory.Conversation[] senderConversation = new ConversationFactory.Conversation[senders.size()]; + Destination[] senderControlTopic = new Destination[senders.size()]; + + for (int i = 0; i < senders.size(); i++) + { + TestClientDetails sender = senders.get(i); + + senderControlTopic[i] = session.createTopic(sender.privateControlKey); + senderConversation[i] = conversationFactory.startConversation(); + } + + log.debug("Sender conversations created."); + + // Create control conversations with each of the receivers. + ConversationFactory.Conversation[] receiverConversation = new ConversationFactory.Conversation[receivers.size()]; + Destination[] receiverControlTopic = new Destination[receivers.size()]; + + for (int i = 0; i < receivers.size(); i++) + { + TestClientDetails receiver = receivers.get(i); + + receiverControlTopic[i] = session.createTopic(receiver.privateControlKey); + receiverConversation[i] = conversationFactory.startConversation(); + } + + log.debug("Receiver conversations created."); + + // Assign the sender role to each of the sending test clients. + for (int i = 0; i < senders.size(); i++) + { + TestClientDetails sender = senders.get(i); + + Message assignSender = conversationFactory.getSession().createMessage(); + TestUtils.setPropertiesOnMessage(assignSender, testProps); + assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); + assignSender.setStringProperty("ROLE", "SENDER"); + + senderConversation[i].send(senderControlTopic[i], assignSender); + } + + log.debug("Sender role assignments sent."); + + // Assign the receivers role to each of the receiving test clients. + for (int i = 0; i < receivers.size(); i++) + { + TestClientDetails receiver = receivers.get(i); + + Message assignReceiver = session.createMessage(); + TestUtils.setPropertiesOnMessage(assignReceiver, testProps); + assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); + assignReceiver.setStringProperty("ROLE", "RECEIVER"); + + receiverConversation[i].send(receiverControlTopic[i], assignReceiver); + } + + log.debug("Receiver role assignments sent."); + + // Wait for the senders and receivers to confirm their roles. + for (int i = 0; i < senders.size(); i++) + { + senderConversation[i].receive(); + } + + log.debug("Got all sender role confirmations"); + + for (int i = 0; i < receivers.size(); i++) + { + receiverConversation[i].receive(); + } + + log.debug("Got all receiver role confirmations"); + + // Package everything up as a circuit. + return new DistributedCircuitImpl(session, senders, receivers, senderConversation, receiverConversation, + senderControlTopic, receiverControlTopic); + } + catch (JMSException e) + { + throw new RuntimeException("JMSException not handled."); + } + } + + /** + * Used by tests cases that can supply a {@link uk.co.thebadgerset.junit.extensions.TimingController} to set the + * controller on an aware test. + * + * @param controller The timing controller. + */ + public void setTimingController(TimingController controller) + { + this.timingController = controller; + } + /** * Gets the interface on the publishing end of the circuit. * @@ -70,16 +270,132 @@ public class DistributedCircuitImpl implements Circuit */ public void start() { - throw new RuntimeException("Not Implemented."); + log.debug("public void start(): called"); + + try + { + // Start the test on each of the senders. + Message start = controlSession.createMessage(); + start.setStringProperty("CONTROL_TYPE", "START"); + start.setIntProperty("MESSAGE_COUNT", numMessages); + + for (int i = 0; i < senders.size(); i++) + { + senderConversation[i].send(senderControlTopic[i], start); + } + + log.debug("All senders told to start their tests."); + } + catch (JMSException e) + { + throw new RuntimeException("Unhandled JMSException.", e); + } } /** * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit, * into a report, against which assertions may be checked. + * + * @todo Replace the asynch receiver report thread with a choice of direct os asynch executor, so that asynch + * or synch logging of test timings is optional. Also need to provide an onMessage method that is capable + * of receiving timing reports that receivers will generate during an ongoing test, on the test sample + * size boundaries. The message timing logging code should be factored out as a common method that can + * be called in response to the final report responses, or the onMessage method. Another alternative is + * to abandon the final report request altogether and just use the onMessage method? I think the two + * differ though, as the final report is used to apply assertions, and the ongoing report is just for + * periodic timing results... In which case, maybe there needs to be a way for the onMessage method + * to process just some of the incoming messages, and forward the rest on to the conversion helper, as + * a sort of pre-conversation helper filter? */ public void check() { - throw new RuntimeException("Not Implemented."); + log.debug("public void check(): called"); + + try + { + // Wait for all the test senders to return their reports. + for (int i = 0; i < senders.size(); i++) + { + Message senderReport = senderConversation[i].receive(); + log.debug("Sender " + senderReport.getStringProperty("CLIENT_NAME") + " reports message count: " + + senderReport.getIntProperty("MESSAGE_COUNT")); + log.debug("Sender " + senderReport.getStringProperty("CLIENT_NAME") + " reports message time: " + + senderReport.getLongProperty("TEST_TIME")); + } + + log.debug("Got all sender test reports."); + + // Apply sender assertions to pass/fail the tests. + + // Inject a short pause to give the receivers time to finish receiving their test messages. + TestUtils.pause(500); + + // Ask the receivers for their reports. + Message statusRequest = controlSession.createMessage(); + statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); + + for (int i = 0; i < receivers.size(); i++) + { + receiverConversation[i].send(receiverControlTopic[i], statusRequest); + } + + log.debug("All receiver test reports requested."); + + // Wait for all receiver reports to come in, but do so asynchronously. + Runnable gatherAllReceiverReports = + new Runnable() + { + public void run() + { + try + { + // Wait for all the receivers to send their reports. + for (int i = 0; i < receivers.size(); i++) + { + Message receiverReport = receiverConversation[i].receive(); + + String clientName = receiverReport.getStringProperty("CLIENT_NAME"); + int messageCount = receiverReport.getIntProperty("MESSAGE_COUNT"); + long testTime = receiverReport.getLongProperty("TEST_TIME"); + + log.debug("Receiver " + clientName + " reports message count: " + messageCount); + log.debug("Receiver " + receiverReport.getStringProperty("CLIENT_NAME") + + " reports message time: " + testTime); + + // Apply receiver assertions to pass/fail the tests. + + // Log the test timings on the asynchronous test timing controller. + try + { + timingController.completeTest(true, messageCount, testTime); + } + // The timing controll can throw InterruptedException is the current test is to be + // interrupted. + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + log.debug("All receiver test reports received."); + } + catch (JMSException e) + { + throw new RuntimeException(e); + } + } + }; + + Thread receiverReportsThread = new Thread(gatherAllReceiverReports); + receiverReportsThread.start(); + + // return new Message[] { senderReport, receiverReport }; + + } + catch (JMSException e) + { + throw new RuntimeException("Unhandled JMSException.", e); + } } /** @@ -87,19 +403,34 @@ public class DistributedCircuitImpl implements Circuit */ public void close() { - throw new RuntimeException("Not Implemented."); + log.debug("public void close(): called"); + + // End the current test on all senders and receivers. } /** - * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing + * Applies a list of assertions against the test circuit. The {@link #check()} method should be called before doing * this, to ensure that the circuit has gathered its state into a report to assert against. * * @param assertions The list of assertions to apply. + * * @return Any assertions that failed. */ public List applyAssertions(List assertions) { - throw new RuntimeException("Not Implemented."); + log.debug("public List applyAssertions(List assertions = " + assertions + "): called"); + + List failures = new LinkedList(); + + for (Assertion assertion : assertions) + { + if (!assertion.apply()) + { + failures.add(assertion); + } + } + + return failures; } /** @@ -107,10 +438,34 @@ public class DistributedCircuitImpl implements Circuit * * @param numMessages The number of messages to send using the default test procedure. * @param assertions The list of assertions to apply. + * * @return Any assertions that failed. + * + * @todo From check onwards needs to be handled as a future. The future must call back onto the test case to + * report results asynchronously. */ public List test(int numMessages, List assertions) { - throw new RuntimeException("Not Implemented."); + log.debug("public List test(int numMessages = " + numMessages + ", List assertions = " + + assertions + "): called"); + + // Keep the number of messages to send per test run, where the send method can reference it. + this.numMessages = numMessages; + + // Start the test running on all sender circuit ends. + start(); + + // Request status reports to be handed in. + check(); + + // Assert conditions on the publishing end of the circuit. + // Assert conditions on the receiving end of the circuit. + List failures = applyAssertions(assertions); + + // Close the circuit ending the current test case. + close(); + + // Pass with no failed assertions or fail with a list of failed assertions. + return failures; } } 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 new file mode 100644 index 0000000000..9e3054964c --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedPublisherImpl.java @@ -0,0 +1,63 @@ +/* + * + * 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.distributedcircuit; + +import org.apache.qpid.test.framework.Assertion; +import org.apache.qpid.test.framework.Publisher; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ */ +public class DistributedPublisherImpl implements Publisher +{ + /** + * Provides an assertion that the publisher encountered no exceptions. + * + * @return An assertion that the publisher encountered no exceptions. + */ + public Assertion noExceptionsAssertion() + { + throw new RuntimeException("Not implemented."); + } + + /** + * Provides an assertion that the publisher got a no consumers exception on every message. + * + * @return An assertion that the publisher got a no consumers exception on every message. + */ + public Assertion noConsumersAssertion() + { + throw new RuntimeException("Not implemented."); + } + + /** + * Provides an assertion that the publisher got a no rout exception on every message. + * + * @return An assertion that the publisher got a no rout exception on every message. + */ + public Assertion noRouteAssertion() + { + 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 new file mode 100644 index 0000000000..4a77906448 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedReceiverImpl.java @@ -0,0 +1,53 @@ +/* + * + * 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.distributedcircuit; + +import org.apache.qpid.test.framework.Assertion; +import org.apache.qpid.test.framework.Receiver; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ */ +public class DistributedReceiverImpl implements Receiver +{ + /** + * Provides an assertion that the receivers encountered no exceptions. + * + * @return An assertion that the receivers encountered no exceptions. + */ + public Assertion noExceptionsAssertion() + { + throw new RuntimeException("Not implemented."); + } + + /** + * 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. + */ + public Assertion allMessagesAssertion() + { + 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 new file mode 100644 index 0000000000..bf0499314a --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/TestClientCircuitEnd.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.distributedcircuit; + +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; + +import javax.jms.*; + +/** + * A TestClientCircuitEnd is a {@link CircuitEnd} that may be controlled from a + * {@link org.apache.qpid.test.framework.distributedtesting.TestClient}, and that forms a single publishing or + * receiving end point in a distributed test {@link org.apache.qpid.test.framework.Circuit}. + * + *

When operating in the SENDER role, this circuit end is capable of acting as part of the default circuit test + * procedure (described in the class comment for {@link org.apache.qpid.test.framework.Circuit}). That is, it will + * send the number of test messages required, using the test configuration parameters given in the test invite, and + * return a report on its activities to the circuit controller. + * + *

When operation in the RECEIVER role, this circuit end acts as part of the default circuit test procedure. It will + * receive test messages, on the setup specified in the test configuration parameters, and keep count of the messages + * received, and time taken to receive them. When requested by the circuit controller to provide a report, it will + * return this report of its activities. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ */ +public class TestClientCircuitEnd implements CircuitEnd, TestClientControlledTest +{ + /** Used for debugging. */ + Logger log = Logger.getLogger(TestClientCircuitEnd.class); + + /** Holds the test parameters. */ + ParsedProperties testProps; + + /** The number of test messages to send. */ + private int numMessages; + + /** The role to be played by the test. */ + private Roles role; + + /** The connection to send the test messages on. */ + private Connection connection; + + /** Holds the circuit end for this test. */ + CircuitEnd circuitEnd; + + /** + * Holds a message monitor for this circuit end, either the monitor on the consumer when in RECEIVER more, or + * a monitor updated on every message sent, when acting as a SENDER. + */ + MessageMonitor messageMonitor; + + /** + * Should provide the name of the test case that this class implements. The exact names are defined in the + * interop testing spec. + * + * @return The name of the test case that this implements. + */ + public String getName() + { + return "DEFAULT_CIRCUIT_TEST"; + } + + /** + * Determines whether the test invite that matched this test case is acceptable. + * + * @param inviteMessage The invitation to accept or reject. + * @return true to accept the invitation, false to reject it. + * + * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. + */ + public boolean acceptInvite(Message inviteMessage) throws JMSException + { + log.debug("public boolean acceptInvite(Message inviteMessage): called"); + + // Populate the test parameters from the invitation. + testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults); + + for (Object key : testProps.keySet()) + { + String propName = (String) key; + + // If the test parameters is overridden by the invitation, use it instead. + String inviteValue = inviteMessage.getStringProperty(propName); + + if (inviteValue != null) + { + testProps.setProperty(propName, inviteValue); + log.debug("Test invite supplied override to " + propName + " of " + inviteValue); + } + + } + + // Accept the invitation. + return true; + } + + /** + * Assigns the role to be played by this test case. The test parameters are fully specified in the + * assignment message. When this method return the test case will be ready to execute. + * + * @param role The role to be played; sender or receivers. + * @param assignRoleMessage The role assingment message, contains the full test parameters. + * + * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. + */ + public void assignRole(Roles role, Message assignRoleMessage) throws JMSException + { + log.debug("public void assignRole(Roles role, Message assignRoleMessage): called"); + + // Take note of the role to be played. + this.role = role; + + // Extract and retain the test parameters. + numMessages = 1; // assignRoleMessage.getIntProperty("NUM_MESSAGES"); + + // Connect using the test parameters. + connection = TestUtils.createConnection(testProps); + + // Create a circuit end that matches the assigned role and test parameters. + 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); + + // Create a custom message monitor that will be updated on every message sent. + messageMonitor = new MessageMonitor(); + + break; + + // Otherwise the receivers role is being assigned, so set this up to listen for messages. + case RECEIVER: + + // Set up the receiver. + circuitEnd = LocalCircuitImpl.createReceiverCircuitEnd(connection, testProps, 0L); + + // Use the message monitor from the consumer for stats. + messageMonitor = getMessageMonitor(); + + break; + } + + // Reset all messaging stats for the report. + messageMonitor.reset(); + + connection.start(); + } + + /** + * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. + * + * @param numMessages The number of test messages to send. + * + * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. + * + * @todo Add round robin on destinations where multiple destinations being used. + * + * @todo Add rate limiting when rate limit specified on publishers. + * + * @todo Add Max pending message size protection. The receiver will have to send back some acks once in a while, + * to notify the publisher that its messages are being consumed. This makes the safety valve harder to + * implement than in the single VM case. For example, if the limit is 1000 messages, might want to get back + * an ack every 500, to notify the publisher that it can keep sending. What about pub/sub tests? Will it be + * necessary to wait for an ack from every receiver? This will have the effect of rate limiting to slow + * consumers too. + * + * @todo Add commits on every commit batch size boundary. + */ + public void start(int numMessages) throws JMSException + { + log.debug("public void start(): called"); + + // If in the SENDER role, send the specified number of test messages to the circuit destinations. + if (role.equals(Roles.SENDER)) + { + Message testMessage = getSession().createMessage(); + + for (int i = 0; i < numMessages; i++) + { + getProducer().send(testMessage); + + // Increment the message count and timings. + messageMonitor.onMessage(testMessage); + } + } + } + + /** + * Gets a report on the actions performed by the test case in its assigned role. + * + * @param session The controlSession to create the report message in. + * @return The report message. + * + * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through. + */ + public Message getReport(Session session) throws JMSException + { + Message report = session.createMessage(); + report.setStringProperty("CONTROL_TYPE", "REPORT"); + + // Add the count of messages sent/received to the report. + report.setIntProperty("MESSAGE_COUNT", messageMonitor.getNumMessage()); + + // Add the time to send/receive messages to the report. + report.setLongProperty("TEST_TIME", messageMonitor.getTime()); + + // Add any exceptions detected to the report. + + return report; + } + + /** + * Gets the message producer at this circuit end point. + * + * @return The message producer at with this circuit end point. + */ + public MessageProducer getProducer() + { + return circuitEnd.getProducer(); + } + + /** + * Gets the message consumer at this circuit end point. + * + * @return The message consumer at this circuit end point. + */ + public MessageConsumer getConsumer() + { + return circuitEnd.getConsumer(); + } + + /** + * Send the specified message over the producer at this end point. + * + * @param message The message to send. + * + * @throws JMSException Any JMS exception occuring during the send is allowed to fall through. + */ + public void send(Message message) throws JMSException + { + // Send the message on the circuit ends producer. + circuitEnd.send(message); + } + + /** + * Gets the JMS Session associated with this circuit end point. + * + * @return The JMS Session associated with this circuit end point. + */ + public Session getSession() + { + return circuitEnd.getSession(); + } + + /** + * Closes the message producers and consumers and the sessions, associated with this circuit end point. + * + * @throws JMSException Any JMSExceptions occurring during the close are allowed to fall through. + */ + public void close() throws JMSException + { + // Close the producer and consumer. + circuitEnd.close(); + } + + /** + * Returns the message monitor for reporting on received messages on this circuit end. + * + * @return The message monitor for this circuit end. + */ + public MessageMonitor getMessageMonitor() + { + return circuitEnd.getMessageMonitor(); + } + + /** + * Returns the exception monitor for reporting on exceptions received on this circuit end. + * + * @return The exception monitor for this circuit end. + */ + public ExceptionMonitor getExceptionMonitor() + { + return circuitEnd.getExceptionMonitor(); + } +} 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 7d28aee432..c4c9622091 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 @@ -25,18 +25,23 @@ import junit.framework.TestResult; import junit.framework.TestSuite; import org.apache.log4j.Logger; +import org.apache.log4j.NDC; +import org.apache.qpid.test.framework.FrameworkBaseCase; import org.apache.qpid.test.framework.MessagingTestConfigProperties; -import org.apache.qpid.test.framework.TestUtils; import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.test.framework.TestUtils; import org.apache.qpid.test.framework.listeners.XMLTestListener; import org.apache.qpid.util.ConversationFactory; import org.apache.qpid.util.PrettyPrintingUtils; +import uk.co.thebadgerset.junit.extensions.AsymptoticTestDecorator; import uk.co.thebadgerset.junit.extensions.TKTestResult; import uk.co.thebadgerset.junit.extensions.TKTestRunner; import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator; +import uk.co.thebadgerset.junit.extensions.listeners.CSVTestListener; import uk.co.thebadgerset.junit.extensions.util.CommandLineParser; +import uk.co.thebadgerset.junit.extensions.util.MathUtils; import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; import uk.co.thebadgerset.junit.extensions.util.TestContextProperties; @@ -120,17 +125,43 @@ public class Coordinator extends TKTestRunner /** Flag that indicates that all test clients should be terminated upon completion of the test cases. */ protected boolean terminate; + /** Flag that indicates the CSV results listener should be used to output results. */ + protected boolean csvResults; + + /** Flag that indiciates the XML results listener should be used to output results. */ + protected boolean xmlResults; + /** * Creates an interop test coordinator on the specified broker and virtual host. * - * @param brokerUrl The URL of the broker to connect to. - * @param virtualHost The virtual host to run all tests on. Optional, may be null. - * @param reportDir The directory to write out test results to. - * @param engine The distributed test engine type to run the tests with. + * @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 null. + * @param engine The distributed test engine type to run the tests with. + * @param terminate true if test client nodes should be terminated at the end of the tests. + * @param csv true if the CSV results listener should be attached. + * @param xml true if the XML results listener should be attached. */ - public Coordinator(String brokerUrl, String virtualHost, String reportDir, TestEngine engine, boolean terminate) + 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) { - log.debug("Coordinator(String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost + "): called"); + super(repetitions, duration, threads, delay, params, testCaseName, reportDir, runName, verbose); + + log.debug("public Coordinator(Integer repetitions = " + repetitions + " , Long duration = " + duration + + ", int[] threads = " + Arrays.toString(threads) + ", int delay = " + delay + ", int[] params = " + + Arrays.toString(params) + ", String testCaseName = " + testCaseName + ", String reportDir = " + reportDir + + ", String runName = " + runName + ", boolean verbose = " + verbose + ", String brokerUrl = " + brokerUrl + + ", String virtualHost =" + virtualHost + ", TestEngine engine = " + engine + ", boolean terminate = " + + terminate + ", boolean csv = " + csv + ", boolean xml = " + xml + "): called"); // Retain the connection parameters. this.brokerUrl = brokerUrl; @@ -138,6 +169,8 @@ public class Coordinator extends TKTestRunner this.reportDir = reportDir; this.engine = engine; this.terminate = terminate; + this.csvResults = csv; + this.xmlResults = xml; } /** @@ -158,6 +191,8 @@ public class Coordinator extends TKTestRunner */ public static void main(String[] args) { + NDC.push("coordinator"); + log.debug("public static void main(String[] args = " + Arrays.toString(args) + "): called"); console.info("Qpid Distributed Test Coordinator."); // Override the default broker url to be localhost:5672. @@ -181,7 +216,25 @@ public class Coordinator extends TKTestRunner "e", "The test execution engine to use. Default is interop.", "engine", "interop", "^interop$|^fanout$", "true" }, - { "t", "Terminate test clients on completion of tests.", "flag", "false" } + { "t", "Terminate test clients on completion of tests.", null, "false" }, + { "-csv", "Output test results in CSV format.", null, "false" }, + { "-xml", "Output test results in XML format.", null, "false" }, + { + "c", "The number of tests to run concurrently.", "num", "false", + MathUtils.SEQUENCE_REGEXP + }, + { "r", "The number of times to repeat each test.", "num", "false" }, + { + "d", "The length of time to run the tests for.", "duration", "false", + MathUtils.DURATION_REGEXP + }, + { + "f", "The maximum rate to call the tests at.", "frequency", "false", + "^([1-9][0-9]*)/([1-9][0-9]*)$" + }, + { "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" } }), testContextProperties)); // Extract the command line options. @@ -192,16 +245,29 @@ public class Coordinator extends TKTestRunner String testEngine = options.getProperty("e"); TestEngine engine = "fanout".equals(testEngine) ? TestEngine.FANOUT : TestEngine.INTEROP; 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"); + + int[] threads = (threadsString == null) ? null : MathUtils.parseSequence(threadsString); + int[] params = (paramsString == null) ? null : MathUtils.parseSequence(paramsString); + Long duration = (durationString == null) ? null : MathUtils.parseDuration(durationString); // If broker or virtual host settings were specified as command line options, override the defaults in the // test context properties with them. // Collection all of the test cases to be run. - Collection> testCaseClasses = - new ArrayList>(); + Collection> testCaseClasses = + new ArrayList>(); // Scan for available test cases using a classpath scanner. - // ClasspathScanner.getMatches(InteropTestCase.class, "^Test.*", true); + // ClasspathScanner.getMatches(DistributedTestCase.class, "^Test.*", true); // Hard code the test classes till the classpath scanner is fixed. // Collections.addAll(testCaseClasses, InteropTestCase1DummyRun.class, InteropTestCase2BasicP2P.class, @@ -222,7 +288,7 @@ public class Coordinator extends TKTestRunner { Class nextClass = Class.forName(nextFreeArg); - if (DistributedTestCase.class.isAssignableFrom(nextClass)) + if (FrameworkBaseCase.class.isAssignableFrom(nextClass)) { testCaseClasses.add(nextClass); console.info("Found distributed test case: " + nextFreeArg); @@ -237,7 +303,8 @@ public class Coordinator extends TKTestRunner // Check that some test classes were actually found. if (testCaseClasses.isEmpty()) { - throw new RuntimeException("No test cases implementing InteropTestCase were specified on the command line."); + throw new RuntimeException( + "No test cases implementing DistributedTestCase were specified on the command line."); } // Extract the names of all the test classes, to pass to the start method. @@ -250,7 +317,9 @@ public class Coordinator extends TKTestRunner } // Create a coordinator and begin its test procedure. - Coordinator coordinator = new Coordinator(brokerUrl, virtualHost, reportDir, engine, terminate); + Coordinator coordinator = + new Coordinator(repetitions, duration, threads, 0, params, null, reportDir, testRunName, verbose, brokerUrl, + virtualHost, engine, terminate, csvResults, xmlResults); TestResult testResult = coordinator.start(testClassNames); @@ -306,10 +375,15 @@ public class Coordinator extends TKTestRunner conversation.send(controlTopic, invite); // Wait for a short time, to give test clients an opportunity to reply to the invitation. - Collection enlists = conversation.receiveAll(0, 3000); - + Collection enlists = conversation.receiveAll(0, 500); enlistedClients = extractEnlists(enlists); + for (TestClientDetails client : enlistedClients) + { + log.debug("Got enlisted test client: " + client); + console.info("Test node " + client.clientName + " available."); + } + // Run the test in the suite using JUnit. TestResult result = null; @@ -357,7 +431,20 @@ public class Coordinator extends TKTestRunner clientDetails.clientName = enlist.getStringProperty("CLIENT_NAME"); clientDetails.privateControlKey = enlist.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY"); - enlistedClients.add(clientDetails); + String replyType = enlist.getStringProperty("CONTROL_TYPE"); + + if ("ENLIST".equals(replyType)) + { + enlistedClients.add(clientDetails); + } + else if ("DECLINE".equals(replyType)) + { + log.debug("Test client " + clientDetails.clientName + " declined the invite."); + } + else + { + log.warn("Got an unknown reply type, " + replyType + ", to the invite."); + } } return enlistedClients; @@ -395,9 +482,9 @@ public class Coordinator extends TKTestRunner Test nextTest = suite.testAt(i); log.debug("suite.testAt(" + i + ") = " + nextTest); - if (nextTest instanceof DistributedTestCase) + if (nextTest instanceof FrameworkBaseCase) { - log.debug("nextTest is a DistributedTestCase"); + log.debug("nextTest is a FrameworkBaseCase"); } } @@ -408,13 +495,13 @@ public class Coordinator extends TKTestRunner // Wrap the tests in a suitable distributed test decorator, to perform the invite/test cycle. targetTest = newTestDecorator(targetTest, enlistedClients, conversationFactory, connection); - TestSuite suite = new TestSuite(); - suite.addTest(targetTest); + // TestSuite suite = new TestSuite(); + // suite.addTest(targetTest); // Wrap the tests in a scaled test decorator to them them as a 'batch' in one thread. // targetTest = new ScaledTestDecorator(targetTest, new int[] { 1 }); - return super.doRun(suite, wait); + return super.doRun(targetTest, wait); } /** @@ -466,20 +553,48 @@ public class Coordinator extends TKTestRunner // Create the results file (make the name of this configurable as a command line parameter). Writer timingsWriter; - try + // Set up an XML results listener to output the timings to the results file, if requested on the command line. + if (xmlResults) { - File timingsFile = new File(reportDirFile, "TEST." + currentTestClassName + ".xml"); - timingsWriter = new BufferedWriter(new FileWriter(timingsFile), 20000); + try + { + File timingsFile = new File(reportDirFile, "TEST." + currentTestClassName + ".xml"); + timingsWriter = new BufferedWriter(new FileWriter(timingsFile), 20000); + } + catch (IOException e) + { + throw new RuntimeException("Unable to create the log file to write test results to: " + e, e); + } + + XMLTestListener listener = new XMLTestListener(timingsWriter, currentTestClassName); + result.addListener(listener); + result.addTKTestListener(listener); + + registerShutdownHook(listener); } - catch (IOException e) + + // Set up an CSV results listener to output the timings to the results file, if requested on the command line. + if (csvResults) { - throw new RuntimeException("Unable to create the log file to write test results to: " + e, e); - } + try + { + File timingsFile = + new File(reportDirFile, testRunName + "-" + TIME_STAMP_FORMAT.format(new Date()) + "-timings.csv"); + timingsWriter = new BufferedWriter(new FileWriter(timingsFile), 20000); + } + catch (IOException e) + { + throw new RuntimeException("Unable to create the log file to write test results to: " + e, e); + } - // Set up an XML results listener to output the timings to the results file. - XMLTestListener listener = new XMLTestListener(timingsWriter, currentTestClassName); - result.addListener(listener); - result.addTKTestListener(listener); + CSVTestListener listener = new CSVTestListener(timingsWriter); + result.addListener(listener); + result.addTKTestListener(listener); + + // Register the results listeners shutdown hook to flush its data if the test framework is shutdown + // prematurely. + registerShutdownHook(listener); + } // Register the results listeners shutdown hook to flush its data if the test framework is shutdown // prematurely. diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestCase.java deleted file mode 100644 index c47650ba1c..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestCase.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.distributedtesting; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.framework.sequencers.DistributedTestSequencer; -import org.apache.qpid.test.framework.FrameworkBaseCase; - -/** - * DistributedTestCase provides a base class implementation of the {@link org.apache.qpid.test.framework.sequencers.DistributedTestSequencer}, taking care of its - * more mundane aspects, such as recording the test pariticipants. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Accept notification of test case participants. - * {@link DistributedTestDecorator} - *
Accept JMS Connection to carry out the coordination over. - *
- */ -public abstract class DistributedTestCase extends FrameworkBaseCase -{ - /** Used for debugging. */ - private final Logger log = Logger.getLogger(DistributedTestCase.class); - - /** - * Creates a new test case with the specified name. - * - * @param name The test case name. - */ - public DistributedTestCase(String name) - { - super(name); - } - - /** - * Gets the test sequencer for this distributed test, cast as a {@link DistributedTestSequencer}, provided that it - * is one. If the test sequencer is not distributed, this returns null. - */ - public DistributedTestSequencer getDistributedTestSequencer() - { - try - { - return (DistributedTestSequencer) testSequencer; - } - catch (ClassCastException e) - { - return null; - } - } - - /** - * Should provide a translation from the junit method name of a test to its test case name as known to the test - * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test - * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case - * name "TC2_BasicP2P". - * - * @param methodName The name of the JUnit test method. - * - * @return The name of the corresponding interop test case. - */ - public abstract String getTestCaseNameForTestMethod(String methodName); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java index bcc409dff9..c2f34b44fc 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java @@ -24,8 +24,9 @@ import junit.framework.TestResult; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.sequencers.DistributedTestSequencer; +import org.apache.qpid.test.framework.FrameworkBaseCase; import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.test.framework.sequencers.CircuitFactory; import org.apache.qpid.util.ConversationFactory; import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator; @@ -42,10 +43,9 @@ import java.util.*; * distributed test cases. It provides a helper method, {@link #signupClients}, that broadcasts an invitation and * returns the set of test clients that are available to particiapte in the test. * - *

When used to wrap a {@link org.apache.qpid.test.framework.FrameworkBaseCase} test, it replaces the default - * {@link org.apache.qpid.test.framework.sequencers.TestCaseSequencer} implementations with a suitable - * {@link org.apache.qpid.test.framework.sequencers.DistributedTestSequencer}. Concrete implementations - * can use this to configure the sending and receiving roles on the test. + *

When used to wrap a {@link FrameworkBaseCase} test, it replaces the default {@link CircuitFactory} implementations + * with a suitable circuit factory for distributed tests. Concrete implementations can use this to configure the sending + * and receiving roles on the test. * *

*
CRC Card
Responsibilities Collaborations @@ -66,7 +66,7 @@ public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator /** Holds the connection that the control conversation is held over. */ Connection connection; - /** Holds the underlying {@link DistributedTestCase}s that this decorator wraps. */ + /** Holds the underlying test suite that this decorator wraps. */ WrappedSuiteTestDecorator testSuite; /** Holds the control topic, on which test invitations are broadcast. */ @@ -117,7 +117,7 @@ public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator * * @return A distributed test sequencer. */ - public abstract DistributedTestSequencer getDistributedTestSequencer(); + public abstract CircuitFactory getTestSequencer(); /** * Broadcasts an invitation to participate in a coordinating test case to find out what clients are available to @@ -127,7 +127,7 @@ public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator * * @return A set of test clients that accepted the invitation. */ - protected Set signupClients(DistributedTestCase coordTest) + protected Set signupClients(FrameworkBaseCase coordTest) { // Broadcast the invitation to find out what clients are available to test. Set enlists; @@ -143,7 +143,7 @@ public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator conversation.send(controlTopic, invite); // Wait for a short time, to give test clients an opportunity to reply to the invitation. - Collection replies = conversation.receiveAll(allClients.size(), 3000); + Collection replies = conversation.receiveAll(allClients.size(), 500); enlists = Coordinator.extractEnlists(replies); } catch (JMSException e) diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java index 83d6602e57..eed24c65c1 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java @@ -25,11 +25,12 @@ import junit.framework.TestResult; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.sequencers.DistributedTestSequencer; -import org.apache.qpid.test.framework.sequencers.FanOutTestSequencer; import org.apache.qpid.test.framework.DropInTest; -import org.apache.qpid.util.ConversationFactory; +import org.apache.qpid.test.framework.FrameworkBaseCase; import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.test.framework.sequencers.CircuitFactory; +import org.apache.qpid.test.framework.sequencers.FanOutCircuitFactory; +import org.apache.qpid.util.ConversationFactory; import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator; @@ -50,7 +51,7 @@ import java.util.Set; * *

*
CRC Card
Responsibilities Collaborations - *
Execute coordinated test cases. {@link DistributedTestCase} + *
Execute coordinated test cases. {@link FrameworkBaseCase} *
Accept test clients joining a running test. *
*/ @@ -60,7 +61,7 @@ public class FanOutTestDecorator extends DistributedTestDecorator implements Mes private static final Logger log = Logger.getLogger(FanOutTestDecorator.class); /** Holds the currently running test case. */ - DistributedTestCase currentTest = null; + FrameworkBaseCase currentTest = null; /** * Creates a wrapped suite test decorator from another one. @@ -112,9 +113,9 @@ public class FanOutTestDecorator extends DistributedTestDecorator implements Mes } // Run all of the test cases in the test suite. - for (Test test : tests) + for (Test test : getAllUnderlyingTests()) { - DistributedTestCase coordTest = (DistributedTestCase) test; + FrameworkBaseCase coordTest = (FrameworkBaseCase) test; // Get all of the clients able to participate in the test. Set enlists = signupClients(coordTest); @@ -125,28 +126,28 @@ public class FanOutTestDecorator extends DistributedTestDecorator implements Mes throw new RuntimeException("No clients to test with"); } - // Create a distributed test sequencer for the test. - DistributedTestSequencer sequencer = getDistributedTestSequencer(); + // Create a distributed test circuit factory for the test. + CircuitFactory circuitFactory = getTestSequencer(); // Set up the first client in the sender role, and the remainder in the receivers role. Iterator clients = enlists.iterator(); - sequencer.setSender(clients.next()); + circuitFactory.setSender(clients.next()); while (clients.hasNext()) { // Set the sending and receiving client details on the test case. - sequencer.setReceiver(clients.next()); + circuitFactory.setReceiver(clients.next()); } // Pass down the connection to hold the coordinating conversation over. - sequencer.setConversationFactory(conversationFactory); + circuitFactory.setConversationFactory(conversationFactory); // If the current test case is a drop-in test, set it up as the currently running test for late joiners to // add in to. Otherwise the current test field is set to null, to indicate that late joiners are not allowed. currentTest = (coordTest instanceof DropInTest) ? coordTest : null; // Execute the test case. - coordTest.setTestSequencer(sequencer); + coordTest.setCircuitFactory(circuitFactory); coordTest.run(testResult); currentTest = null; @@ -159,9 +160,9 @@ public class FanOutTestDecorator extends DistributedTestDecorator implements Mes * * @return A distributed test sequencer. */ - public DistributedTestSequencer getDistributedTestSequencer() + public CircuitFactory getTestSequencer() { - return new FanOutTestSequencer(); + return new FanOutCircuitFactory(); } /** 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 7743d2bba3..918f0f9177 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 @@ -25,9 +25,10 @@ import junit.framework.TestResult; import org.apache.log4j.Logger; -import org.apache.qpid.test.framework.sequencers.DistributedTestSequencer; -import org.apache.qpid.test.framework.sequencers.InteropTestSequencer; +import org.apache.qpid.test.framework.FrameworkBaseCase; import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.test.framework.sequencers.CircuitFactory; +import org.apache.qpid.test.framework.sequencers.InteropCircuitFactory; import org.apache.qpid.util.ConversationFactory; import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator; @@ -48,7 +49,7 @@ import java.util.*; *

Responsibilities Collaborations *
Broadcast test invitations and collect enlists. {@link org.apache.qpid.util.ConversationFactory}. *
Output test failures for clients unwilling to run the test case. {@link Coordinator} - *
Execute distributed test cases. {@link DistributedTestCase} + *
Execute distributed test cases. {@link FrameworkBaseCase} *
Fail non participating pairings. {@link OptOutTestCase} *
*/ @@ -74,7 +75,7 @@ public class InteropTestDecorator extends DistributedTestDecorator /** * Broadcasts a test invitation and accetps enlisting from participating clients. The wrapped test case is * then repeated for every combination of test clients (provided the wrapped test case extends - * {@link DistributedTestCase}. + * {@link FrameworkBaseCase}. * *

Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime exceptions, * resulting in the non-completion of the test run. @@ -89,9 +90,9 @@ public class InteropTestDecorator extends DistributedTestDecorator Collection tests = testSuite.getAllUnderlyingTests(); - for (Test test : tests) + for (Test test : getAllUnderlyingTests()) { - DistributedTestCase coordTest = (DistributedTestCase) test; + FrameworkBaseCase coordTest = (FrameworkBaseCase) test; // Broadcast the invitation to find out what clients are available to test. Set enlists = signupClients(coordTest); @@ -105,14 +106,14 @@ public class InteropTestDecorator extends DistributedTestDecorator for (List failPair : failPairs) { - // Create a distributed test sequencer for the test. - DistributedTestSequencer sequencer = getDistributedTestSequencer(); + // Create a distributed test circuit factory for the test. + CircuitFactory circuitFactory = getTestSequencer(); // Create an automatic failure test for the opted out test pair. - DistributedTestCase failTest = new OptOutTestCase("testOptOut"); - sequencer.setSender(failPair.get(0)); - sequencer.setReceiver(failPair.get(1)); - failTest.setTestSequencer(sequencer); + FrameworkBaseCase failTest = new OptOutTestCase("testOptOut"); + circuitFactory.setSender(failPair.get(0)); + circuitFactory.setReceiver(failPair.get(1)); + failTest.setCircuitFactory(circuitFactory); failTest.run(testResult); } @@ -122,18 +123,18 @@ public class InteropTestDecorator extends DistributedTestDecorator for (List enlistedPair : enlistedPairs) { - // Create a distributed test sequencer for the test. - DistributedTestSequencer sequencer = getDistributedTestSequencer(); + // Create a distributed test circuit factory for the test. + CircuitFactory circuitFactory = getTestSequencer(); - // Set the sending and receiving client details on the test sequencer. - sequencer.setSender(enlistedPair.get(0)); - sequencer.setReceiver(enlistedPair.get(1)); + // Set the sending and receiving client details on the test circuitFactory. + circuitFactory.setSender(enlistedPair.get(0)); + circuitFactory.setReceiver(enlistedPair.get(1)); // Pass down the connection to hold the coordination conversation over. - sequencer.setConversationFactory(conversationFactory); + circuitFactory.setConversationFactory(conversationFactory); // Execute the test case. - coordTest.setTestSequencer(sequencer); + coordTest.setCircuitFactory(circuitFactory); coordTest.run(testResult); } } @@ -145,9 +146,9 @@ public class InteropTestDecorator extends DistributedTestDecorator * * @return A distributed test sequencer. */ - public DistributedTestSequencer getDistributedTestSequencer() + public CircuitFactory getTestSequencer() { - return new InteropTestSequencer(); + return new InteropCircuitFactory(); } /** diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java index 83ec12ad56..fcdac20ca2 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/OptOutTestCase.java @@ -20,7 +20,8 @@ */ package org.apache.qpid.test.framework.distributedtesting; -import org.apache.qpid.test.framework.sequencers.DistributedTestSequencer; +import org.apache.qpid.test.framework.sequencers.CircuitFactory; +import org.apache.qpid.test.framework.FrameworkBaseCase; /** * An OptOutTestCase is a test case that automatically fails. It is used when a list of test clients has been generated @@ -32,7 +33,7 @@ import org.apache.qpid.test.framework.sequencers.DistributedTestSequencer; * Fail the test with a suitable reason. * */ -public class OptOutTestCase extends DistributedTestCase +public class OptOutTestCase extends FrameworkBaseCase { /** * Creates a new coordinating test case with the specified name. @@ -47,9 +48,9 @@ public class OptOutTestCase extends DistributedTestCase /** Generates an appropriate test failure assertion. */ public void testOptOut() { - DistributedTestSequencer sequencer = getDistributedTestSequencer(); + CircuitFactory circuitFactory = getCircuitFactory(); - fail("One of " + sequencer.getSender() + " and " + getDistributedTestSequencer().getReceivers() + fail("One of " + circuitFactory.getSender() + " and " + getCircuitFactory().getReceivers() + " opted out of the test."); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java new file mode 100644 index 0000000000..893a022b97 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClientControlledTest.java @@ -0,0 +1,108 @@ +/* + * + * 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.distributedtesting; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.Session; + +/** + * TestClientControlledTest provides an interface that classes implementing test cases to run on a {@link TestClient} + * node can use. Implementations must be Java beans, that is, to provide a default constructor and to implement the + * {@link #getName} method. + * + *

The methods specified in this interface are called when the {@link TestClient} receives control instructions to + * apply to the test. There are control instructions to present the test case with the test invite, so that it may + * choose whether or not to participate in the test, assign the test to play the sender or receiver role, start the + * test and obtain the test status report. + * + *

+ *
CRC Card
Responsibilities + *
Supply the name of the test case that this implements. + *
Accept/Reject invites based on test parameters. + *
Adapt to assigned roles. + *
Perform test case actions. + *
Generate test reports. + *
+ */ +public interface TestClientControlledTest +{ + /** Defines the possible test case roles that an interop test case can take on. */ + public enum Roles + { + /** Specifies the sender role. */ + SENDER, + + /** Specifies the receivers role. */ + RECEIVER + } + + /** + * Should provide the name of the test case that this class implements. The exact names are defined in the + * interop testing spec. + * + * @return The name of the test case that this implements. + */ + public String getName(); + + /** + * Determines whether the test invite that matched this test case is acceptable. + * + * @param inviteMessage The invitation to accept or reject. + * + * @return true to accept the invitation, false to reject it. + * + * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. + */ + public boolean acceptInvite(Message inviteMessage) throws JMSException; + + /** + * Assigns the role to be played by this test case. The test parameters are fully specified in the + * assignment message. When this method return the test case will be ready to execute. + * + * @param role The role to be played; sender or receivers. + * @param assignRoleMessage The role assingment message, contains the full test parameters. + * + * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. + */ + public void assignRole(Roles role, Message assignRoleMessage) throws JMSException; + + /** + * Performs the test case actions. Returning from here, indicates that the sending role has completed its test. + * + * @param numMessages The number of test messages to send. + * + * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. + */ + public void start(int numMessages) throws JMSException; + + /** + * Gets a report on the actions performed by the test case in its assigned role. + * + * @param session The controlSession to create the report message in. + * + * @return The report message. + * + * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through. + */ + public Message getReport(Session session) throws JMSException; +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java b/java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java index ee274a1e01..014dd21292 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/listeners/XMLTestListener.java @@ -26,6 +26,7 @@ import junit.framework.TestCase; import org.apache.log4j.Logger; +import uk.co.thebadgerset.junit.extensions.ShutdownHookable; import uk.co.thebadgerset.junit.extensions.listeners.TKTestListener; import java.io.IOException; @@ -62,7 +63,7 @@ import java.util.*; * the ant XML formatter, and a more structured one for outputing results with timings and summaries from * performance tests. */ -public class XMLTestListener implements TKTestListener +public class XMLTestListener implements TKTestListener, ShutdownHookable { /** Used for debugging. */ private static final Logger log = Logger.getLogger(XMLTestListener.class); @@ -350,6 +351,22 @@ public class XMLTestListener implements TKTestListener } } + /** + * Supplies the shutdown hook. + * + * @return The shut down hook. + */ + public Thread getShutdownHook() + { + return new Thread(new Runnable() + { + public void run() + { + log.debug("XMLTestListener::ShutdownHook: called"); + } + }); + } + /** * Used to capture the results of a particular test run. */ diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/CircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/CircuitImpl.java deleted file mode 100644 index 3c678eef7d..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/CircuitImpl.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.localcircuit; - -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.test.framework.*; - -import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; - -import javax.jms.*; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; - -/** - * CircuitImpl provides an implementation of the test circuit. This is a first prototype implementation and only supports - * a single producer/consumer on each end of the circuit, with both ends of the circuit on the same JVM. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Supply the publishing and receiving ends of a test messaging circuit. - * {@link PublisherImpl}, {@link ReceiverImpl} - *
Start the circuit running. - *
Close the circuit down. - *
Take a reading of the circuits state. - *
Apply assertions against the circuits state. {@link org.apache.qpid.test.framework.Assertion} - *
Send test messages over the circuit. - *
Perform the default test procedure on the circuit. - *
Provide access to connection and session exception monitors {@link org.apache.qpid.test.framework.ExceptionMonitor} - *
- * - * @todo Add ability to create routes with no consumers active on them. Immediate/Mandatory tests are closing consumers - * themsleves to create this scenario. Should make it part of the test configuration. - */ -public class CircuitImpl implements Circuit -{ - /** 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; - - /** Holds the publishing end of the circuit. */ - private PublisherImpl publisher; - - /** Holds the receiving end of the circuit. */ - private ReceiverImpl receiver; - - /** Holds the connection for the publishing end of the circuit. */ - private Connection connection; - - /** Holds the exception listener for the connection on the publishing end of the circuit. */ - private ExceptionMonitor connectionExceptionMonitor; - - /** Holds the exception listener for the session on the publishing end of the circuit. */ - private ExceptionMonitor exceptionMonitor; - - /** - * Creates a test circuit using the specified test parameters. The publisher, receivers, connection and - * connection monitor must already have been created, to assemble the circuit. - * - * @param testProps The test parameters. - * @param publisher The test publisher. - * @param receiver The test receivers. - * @param connection The connection. - * @param connectionExceptionMonitor The connection exception monitor. - */ - protected CircuitImpl(ParsedProperties testProps, PublisherImpl publisher, ReceiverImpl receiver, Connection connection, - ExceptionMonitor connectionExceptionMonitor) - { - this.testProps = testProps; - this.publisher = publisher; - this.receiver = receiver; - this.connection = connection; - this.connectionExceptionMonitor = connectionExceptionMonitor; - this.exceptionMonitor = new ExceptionMonitor(); - - // Set this as the parent circuit on the publisher and receivers. - publisher.setCircuit(this); - receiver.setCircuit(this); - } - - /** - * Creates a 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 - { - // ParsedProperties testProps = new ParsedProperties(testProps); - - // Get a unique offset to append to destination names to make them unique to the connection. - long uniqueId = uniqueDestsId.incrementAndGet(); - - // Extract the standard test configuration parameters relevant to the connection. - String destinationSendRoot = - testProps.getProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME) + "_" + uniqueId; - String destinationReceiveRoot = - testProps.getProperty(MessagingTestConfigProperties.RECEIVE_DESTINATION_NAME_ROOT_PROPNAME) + "_" + uniqueId; - boolean createPublisherProducer = - testProps.getPropertyAsBoolean(MessagingTestConfigProperties.PUBLISHER_PRODUCER_BIND_PROPNAME); - boolean createPublisherConsumer = - testProps.getPropertyAsBoolean(MessagingTestConfigProperties.PUBLISHER_CONSUMER_BIND_PROPNAME); - boolean createReceiverProducer = - testProps.getPropertyAsBoolean(MessagingTestConfigProperties.RECEIVER_PRODUCER_BIND_PROPNAME); - boolean createReceiverConsumer = - testProps.getPropertyAsBoolean(MessagingTestConfigProperties.RECEIVER_CONSUMER_BIND_PROPNAME); - - // Check which JMS flags and options are to be set. - int ackMode = testProps.getPropertyAsInteger(MessagingTestConfigProperties.ACK_MODE_PROPNAME); - boolean useTopics = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.PUBSUB_PROPNAME); - boolean transactional = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.TRANSACTED_PROPNAME); - boolean durableSubscription = - testProps.getPropertyAsBoolean(MessagingTestConfigProperties.DURABLE_SUBSCRIPTION_PROPNAME); - - // Check if any Qpid/AMQP specific flags or options need to be set. - boolean immediate = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.IMMEDIATE_PROPNAME); - boolean mandatory = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.MANDATORY_PROPNAME); - boolean needsQpidOptions = immediate | mandatory; - - /*log.debug("ackMode = " + ackMode); - log.debug("useTopics = " + useTopics); - log.debug("destinationSendRoot = " + destinationSendRoot); - log.debug("destinationReceiveRoot = " + destinationReceiveRoot); - log.debug("createPublisherProducer = " + createPublisherProducer); - log.debug("createPublisherConsumer = " + createPublisherConsumer); - log.debug("createReceiverProducer = " + createReceiverProducer); - log.debug("createReceiverConsumer = " + createReceiverConsumer); - log.debug("transactional = " + transactional); - log.debug("immediate = " + immediate); - log.debug("mandatory = " + mandatory); - log.debug("needsQpidOptions = " + needsQpidOptions);*/ - - // Create connection, sessions and producer/consumer pairs on each session. - Connection connection = TestUtils.createConnection(testProps); - - // Add the connection exception listener to assert on exception conditions with. - ExceptionMonitor exceptionMonitor = new ExceptionMonitor(); - connection.setExceptionListener(exceptionMonitor); - - Session publisherSession = connection.createSession(transactional, ackMode); - Session receiverSession = connection.createSession(transactional, ackMode); - - Destination publisherProducerDestination = - useTopics ? publisherSession.createTopic(destinationSendRoot) - : publisherSession.createQueue(destinationSendRoot); - - MessageProducer publisherProducer = - createPublisherProducer - ? (needsQpidOptions - ? ((AMQSession) publisherSession).createProducer(publisherProducerDestination, mandatory, immediate) - : publisherSession.createProducer(publisherProducerDestination)) : null; - - MessageConsumer publisherConsumer = - createPublisherConsumer - ? publisherSession.createConsumer(publisherSession.createQueue(destinationReceiveRoot)) : null; - - if (publisherConsumer != null) - { - publisherConsumer.setMessageListener(new MessageMonitor()); - } - - MessageProducer receiverProducer = - createReceiverProducer ? receiverSession.createProducer(receiverSession.createQueue(destinationReceiveRoot)) - : null; - - Destination receiverConsumerDestination = - useTopics ? receiverSession.createTopic(destinationSendRoot) - : receiverSession.createQueue(destinationSendRoot); - - MessageConsumer receiverConsumer = - createReceiverConsumer - ? ((durableSubscription && useTopics) - ? receiverSession.createDurableSubscriber((Topic) receiverConsumerDestination, "testsub") - : receiverSession.createConsumer(receiverConsumerDestination)) : null; - - if (receiverConsumer != null) - { - receiverConsumer.setMessageListener(new MessageMonitor()); - } - - // Start listening for incoming messages. - connection.start(); - - // Package everything up. - PublisherImpl publisher = new PublisherImpl(publisherProducer, publisherConsumer, publisherSession); - ReceiverImpl receiver = new ReceiverImpl(receiverProducer, receiverConsumer, receiverSession); - - return new CircuitImpl(testProps, publisher, receiver, connection, exceptionMonitor); - } - catch (JMSException e) - { - throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e); - } - } - - /** - * Gets the interface on the publishing end of the circuit. - * - * @return The publishing end of the circuit. - */ - public Publisher getPublisher() - { - return publisher; - } - - /** - * Gets the interface on the receiving end of the circuit. - * - * @return The receiving end of the circuit. - */ - public Receiver getReceiver() - { - return receiver; - } - - /** - * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit, - * into a report, against which assertions may be checked. - */ - public void check() - { } - - /** - * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing - * this, to ensure that the circuit has gathered its state into a report to assert against. - * - * @param assertions The list of assertions to apply. - * @return Any assertions that failed. - */ - public List applyAssertions(List assertions) - { - List failures = new LinkedList(); - - for (Assertion assertion : assertions) - { - if (!assertion.apply()) - { - failures.add(assertion); - } - } - - return failures; - } - - /** - * Connects and starts the circuit. After this method is called the circuit is ready to send messages. - */ - public void start() - { } - - /** - * Closes the circuit. All associated resources are closed. - */ - public void close() - { - try - { - publisher.close(); - receiver.close(); - connection.close(); - } - catch (JMSException e) - { - throw new RuntimeException("Got JMSException during close.", e); - } - } - - /** - * Sends a message on the test circuit. The exact nature of the message sent is controlled by the test parameters. - */ - public void send() - { - boolean transactional = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.TRANSACTED_PROPNAME); - - // Send an immediate message through the publisher and ensure that it results in a JMSException. - try - { - getPublisher().send(createTestMessage(getPublisher())); - - if (transactional) - { - getPublisher().getSession().commit(); - } - } - catch (JMSException e) - { - exceptionMonitor.onException(e); - } - } - - /** - * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. The - * outline of the default test procedure is: - * - *

-     * Start the circuit.
-     * Send test messages.
-     * Request a status report.
-     * Assert conditions on the publishing end of the circuit.
-     * Assert conditions on the receiving end of the circuit.
-     * Close the circuit.
-     * Pass with no failed assertions or fail with a list of failed assertions.
-     * 
- * - * @param numMessages The number of messages to send using the default test procedure. - * @param assertions The list of assertions to apply. - * @return Any assertions that failed. - */ - public List test(int numMessages, List assertions) - { - // Start the test circuit. - start(); - - // Send the requested number of test messages. - for (int i = 0; i < numMessages; i++) - { - send(); - } - - // Inject a short pause to allow time for exceptions to come back asynchronously. - TestUtils.pause(100L); - - // Request a status report. - check(); - - // Apply all of the requested assertions, keeping record of any that fail. - List failures = applyAssertions(assertions); - - // Clean up the publisher/receivers/session/connections. - close(); - - // Return any failed assertions to the caller. - return failures; - } - - /** - * Creates a message with the properties defined as per the test parameters. - * - * @param client The circuit end to create the message on. - * - * @return The test message. - * - * @throws JMSException Any JMSException occurring during creation of the message is allowed to fall through. - */ - private Message createTestMessage(CircuitEnd client) throws JMSException - { - return client.getSession().createTextMessage("Hello"); - } - - /** - * Gets the exception monitor for the publishing ends connection. - * - * @return The exception monitor for the publishing ends connection. - */ - public ExceptionMonitor getConnectionExceptionMonitor() - { - return connectionExceptionMonitor; - } - - /** - * Gets the exception monitor for the publishing ends session. - * - * @return The exception monitor for the publishing ends session. - */ - public ExceptionMonitor getExceptionMonitor() - { - return exceptionMonitor; - } -} 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 new file mode 100644 index 0000000000..ff7330f483 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalCircuitImpl.java @@ -0,0 +1,452 @@ +/* + * + * 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.log4j.Logger; + +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.test.framework.*; + +import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; + +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 + * supports a single producer/consumer on each end of the circuit, with both ends of the circuit on the same JVM. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
Supply the publishing and receiving ends of a test messaging circuit. + * {@link LocalPublisherImpl}, {@link LocalReceiverImpl} + *
Start the circuit running. + *
Close the circuit down. + *
Take a reading of the circuits state. + *
Apply assertions against the circuits state. {@link Assertion} + *
Send test messages over the circuit. + *
Perform the default test procedure on the circuit. + *
Provide access to connection and controlSession exception monitors {@link ExceptionMonitor} + *
+ */ +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; + + /** Holds the publishing end of the circuit. */ + private LocalPublisherImpl publisher; + + /** Holds the receiving end of the circuit. */ + private LocalReceiverImpl receiver; + + /** Holds the connection for the publishing end of the circuit. */ + private Connection connection; + + /** Holds the exception listener for the connection on the publishing end of the circuit. */ + private ExceptionMonitor connectionExceptionMonitor; + + /** Holds the exception listener for the controlSession on the publishing end of the circuit. */ + private ExceptionMonitor exceptionMonitor; + + /** + * Creates a test circuit using the specified test parameters. The publisher, receivers, connection and + * connection monitor must already have been created, to assemble the circuit. + * + * @param testProps The test parameters. + * @param publisher The test publisher. + * @param receiver The test receivers. + * @param connection The connection. + * @param connectionExceptionMonitor The connection exception monitor. + */ + protected LocalCircuitImpl(ParsedProperties testProps, LocalPublisherImpl publisher, LocalReceiverImpl receiver, + Connection connection, ExceptionMonitor connectionExceptionMonitor) + { + this.testProps = testProps; + this.publisher = publisher; + this.receiver = receiver; + this.connection = connection; + this.connectionExceptionMonitor = connectionExceptionMonitor; + this.exceptionMonitor = new ExceptionMonitor(); + + // Set this as the parent circuit on the publisher and receivers. + publisher.setCircuit(this); + receiver.setCircuit(this); + } + + /** + * 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. + */ + public Publisher getPublisher() + { + return publisher; + } + + /** + * Gets the local publishing circuit end, for direct manipulation. + * + * @return The local publishing circuit end. + */ + public CircuitEnd getLocalPublisherCircuitEnd() + { + return publisher; + } + + /** + * Gets the interface on the receiving end of the circuit. + * + * @return The receiving end of the circuit. + */ + public Receiver getReceiver() + { + return receiver; + } + + /** + * Gets the local receiving circuit end, for direct manipulation. + * + * @return The local receiving circuit end. + */ + public CircuitEnd getLocalReceiverCircuitEnd() + { + return receiver; + } + + /** + * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit, + * into a report, against which assertions may be checked. + */ + public void check() + { } + + /** + * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing + * this, to ensure that the circuit has gathered its state into a report to assert against. + * + * @param assertions The list of assertions to apply. + * @return Any assertions that failed. + */ + public List applyAssertions(List assertions) + { + List failures = new LinkedList(); + + for (Assertion assertion : assertions) + { + if (!assertion.apply()) + { + failures.add(assertion); + } + } + + return failures; + } + + /** + * Connects and starts the circuit. After this method is called the circuit is ready to send messages. + */ + public void start() + { } + + /** + * Closes the circuit. All associated resources are closed. + */ + public void close() + { + try + { + publisher.close(); + receiver.close(); + connection.close(); + } + catch (JMSException e) + { + throw new RuntimeException("Got JMSException during close.", e); + } + } + + /** + * Sends a message on the test circuit. The exact nature of the message sent is controlled by the test parameters. + */ + protected void send() + { + boolean transactional = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.TRANSACTED_PROPNAME); + + // Send an immediate message through the publisher and ensure that it results in a JMSException. + try + { + CircuitEnd end = getLocalPublisherCircuitEnd(); + + end.send(createTestMessage(end)); + + if (transactional) + { + end.getSession().commit(); + } + } + catch (JMSException e) + { + exceptionMonitor.onException(e); + } + } + + /** + * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. The + * outline of the default test procedure is: + * + *

+     * Start the circuit.
+     * Send test messages.
+     * Request a status report.
+     * Assert conditions on the publishing end of the circuit.
+     * Assert conditions on the receiving end of the circuit.
+     * Close the circuit.
+     * Pass with no failed assertions or fail with a list of failed assertions.
+     * 
+ * + * @param numMessages The number of messages to send using the default test procedure. + * @param assertions The list of assertions to apply. + * @return Any assertions that failed. + */ + public List test(int numMessages, List assertions) + { + // Start the test circuit. + start(); + + // Send the requested number of test messages. + for (int i = 0; i < numMessages; i++) + { + send(); + } + + // Inject a short pause to allow time for exceptions to come back asynchronously. + TestUtils.pause(100L); + + // Request a status report. + check(); + + // Apply all of the requested assertions, keeping record of any that fail. + List failures = applyAssertions(assertions); + + // Clean up the publisher/receivers/controlSession/connections. + close(); + + // Return any failed assertions to the caller. + return failures; + } + + /** + * Creates a message with the properties defined as per the test parameters. + * + * @param client The circuit end to create the message on. + * + * @return The test message. + * + * @throws JMSException Any JMSException occurring during creation of the message is allowed to fall through. + */ + private Message createTestMessage(CircuitEnd client) throws JMSException + { + return client.getSession().createTextMessage("Hello"); + } + + /** + * Gets the exception monitor for the publishing ends connection. + * + * @return The exception monitor for the publishing ends connection. + */ + public ExceptionMonitor getConnectionExceptionMonitor() + { + return connectionExceptionMonitor; + } + + /** + * Gets the exception monitor for the publishing ends controlSession. + * + * @return The exception monitor for the publishing ends controlSession. + */ + public ExceptionMonitor getExceptionMonitor() + { + return exceptionMonitor; + } +} 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 new file mode 100644 index 0000000000..93a137dffa --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalPublisherImpl.java @@ -0,0 +1,180 @@ +/* + * + * 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 javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +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 + * between the publisher and its single circuit end, in order to ascertain its status. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
Provide a message producer for sending messages. + *
Provide a message consumer for receiving messages. + *
Provide assertion that the publisher received no exceptions. + *
Provide assertion that the publisher received a no consumers error code. + *
Provide assertion that the publisher received a no route error code. + *
+ */ +public class LocalPublisherImpl extends CircuitEndBase implements Publisher +{ + /** Holds a reference to the containing circuit. */ + private LocalCircuitImpl circuit; + + /** + * Creates a circuit end point on the specified producer, consumer and controlSession. + * + * @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. + */ + public LocalPublisherImpl(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 LocalPublisherImpl(CircuitEndBase end) + { + super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor()); + } + + /** + * Provides an assertion that the publisher encountered no exceptions. + * + * @return An assertion that the publisher encountered no exceptions. + */ + public Assertion noExceptionsAssertion() + { + return new AssertionBase() + { + public boolean apply() + { + boolean passed = true; + ExceptionMonitor sessionExceptionMonitor = circuit.getExceptionMonitor(); + ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); + + if (!connectionExceptionMonitor.assertNoExceptions()) + { + passed = false; + + addError("Was expecting no exceptions.\n"); + addError("Got the following exceptions on the connection, " + + circuit.getConnectionExceptionMonitor()); + } + + if (!sessionExceptionMonitor.assertNoExceptions()) + { + passed = false; + + addError("Was expecting no exceptions.\n"); + addError("Got the following exceptions on the producer, " + circuit.getExceptionMonitor()); + } + + return passed; + } + }; + } + + /** + * Provides an assertion that the publisher got a no consumers exception on every message. + * + * @return An assertion that the publisher got a no consumers exception on every message. + */ + public Assertion noConsumersAssertion() + { + 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. + * + * @return An assertion that the publisher got a no rout exception on every message. + */ + public Assertion noRouteAssertion() + { + 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; + } + }; + } + + /** + * Sets the contianing circuit. + * + * @param circuit The containing circuit. + */ + public void setCircuit(LocalCircuitImpl circuit) + { + this.circuit = circuit; + } +} 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 new file mode 100644 index 0000000000..1b5acf92de --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalReceiverImpl.java @@ -0,0 +1,100 @@ +/* + * + * 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.test.framework.*; + +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; + +/** + * Provides an implementation of the {@link Receiver} interface that wraps a single message producer and consumer on + * a single controlSession, as a {@link CircuitEnd}. A local receiver 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 + * between the publisher and its single circuit end, in order to ascertain its status. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
Provide a message producer for sending messages. + *
Provide a message consumer for receiving messages. + *
Provide assertion that the receivers received no exceptions. + *
Provide assertion that the receivers received all test messages sent to it. + *
+ */ +public class LocalReceiverImpl extends CircuitEndBase implements Receiver +{ + /** Holds a reference to the containing circuit. */ + private LocalCircuitImpl circuit; + + /** + * Creates a circuit end point on the specified producer, consumer and controlSession. + * + * @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. + */ + public LocalReceiverImpl(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 LocalReceiverImpl(CircuitEndBase end) + { + super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor()); + } + + /** + * Provides an assertion that the receivers encountered no exceptions. + * + * @return An assertion that the receivers encountered no exceptions. + */ + public Assertion noExceptionsAssertion() + { + return null; + } + + /** + * 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. + */ + public Assertion allMessagesAssertion() + { + return null; + } + + /** + * Sets the contianing circuit. + * + * @param circuit The containing circuit. + */ + public void setCircuit(LocalCircuitImpl circuit) + { + this.circuit = circuit; + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/PublisherImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/PublisherImpl.java deleted file mode 100644 index 5b63607867..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/PublisherImpl.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.localcircuit; - -import org.apache.qpid.client.AMQNoConsumersException; -import org.apache.qpid.client.AMQNoRouteException; -import org.apache.qpid.test.framework.localcircuit.CircuitImpl; -import org.apache.qpid.test.framework.*; - -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * Provides an implementation of the {@link org.apache.qpid.test.framework.Publisher} interface that wraps a single message producer and consumer on - * a single session. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a message producer for sending messages. - *
Provide a message consumer for receiving messages. - *
Provide assertion that the publisher received no exceptions. - *
Provide assertion that the publisher received a no consumers error code. - *
Provide assertion that the publisher received a no route error code. - *
- */ -public class PublisherImpl extends CircuitEndBase implements Publisher -{ - /** Holds a reference to the containing circuit. */ - private CircuitImpl circuit; - - /** - * Creates a circuit end point on the specified producer, consumer and session. - * - * @param producer The message producer for the circuit end point. - * @param consumer The message consumer for the circuit end point. - * @param session The session for the circuit end point. - */ - public PublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session) - { - super(producer, consumer, session); - } - - /** - * Provides an assertion that the publisher encountered no exceptions. - * - * @return An assertion that the publisher encountered no exceptions. - */ - public Assertion noExceptionsAssertion() - { - return new AssertionBase() - { - public boolean apply() - { - boolean passed = true; - ExceptionMonitor sessionExceptionMonitor = circuit.getExceptionMonitor(); - ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); - - if (!connectionExceptionMonitor.assertNoExceptions()) - { - passed = false; - addError("Was expecting no exceptions.\n"); - addError("Got the following exceptions on the connection, " - + circuit.getConnectionExceptionMonitor()); - } - - if (!sessionExceptionMonitor.assertNoExceptions()) - { - passed = false; - addError("Was expecting no exceptions.\n"); - addError("Got the following exceptions on the producer, " + circuit.getExceptionMonitor()); - } - - return passed; - } - }; - } - - /** - * Provides an assertion that the publisher got a no consumers exception on every message. - * - * @return An assertion that the publisher got a no consumers exception on every message. - */ - public Assertion noConsumersAssertion() - { - return new AssertionBase() - { - public boolean apply() - { - boolean passed = true; - ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); - - if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoConsumersException.class)) - { - 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. - * - * @return An assertion that the publisher got a no rout exception on every message. - */ - public Assertion noRouteAssertion() - { - return new AssertionBase() - { - public boolean apply() - { - boolean passed = true; - ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor(); - - if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoRouteException.class)) - { - 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; - } - }; - } - - /** - * Sets the contianing circuit. - * - * @param circuit The containing circuit. - */ - public void setCircuit(CircuitImpl circuit) - { - this.circuit = circuit; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/ReceiverImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/ReceiverImpl.java deleted file mode 100644 index 6dd7056806..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/ReceiverImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.localcircuit; - -import org.apache.qpid.test.framework.localcircuit.CircuitImpl; -import org.apache.qpid.test.framework.CircuitEndBase; -import org.apache.qpid.test.framework.Receiver; -import org.apache.qpid.test.framework.Assertion; - -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -/** - * Provides an implementation of the {@link org.apache.qpid.test.framework.Receiver} interface that wraps a single message producer and consumer on - * a single session. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Provide a message producer for sending messages. - *
Provide a message consumer for receiving messages. - *
Provide assertion that the receivers received no exceptions. - *
Provide assertion that the receivers received all test messages sent to it. - *
- */ -public class ReceiverImpl extends CircuitEndBase implements Receiver -{ - /** Holds a reference to the containing circuit. */ - private CircuitImpl circuit; - - /** - * Creates a circuit end point on the specified producer, consumer and session. - * - * @param producer The message producer for the circuit end point. - * @param consumer The message consumer for the circuit end point. - * @param session The session for the circuit end point. - */ - public ReceiverImpl(MessageProducer producer, MessageConsumer consumer, Session session) - { - super(producer, consumer, session); - } - - /** - * Provides an assertion that the receivers encountered no exceptions. - * - * @return An assertion that the receivers encountered no exceptions. - */ - public Assertion noExceptionsAssertion() - { - return null; - } - - /** - * 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. - */ - public Assertion allMessagesAssertion() - { - return null; - } - - /** - * Sets the contianing circuit. - * - * @param circuit The containing circuit. - */ - public void setCircuit(CircuitImpl circuit) - { - this.circuit = circuit; - } -} 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 new file mode 100644 index 0000000000..555071760e --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java @@ -0,0 +1,128 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.test.framework.sequencers; + +import org.apache.log4j.Logger; + +import org.apache.qpid.test.framework.Circuit; +import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.util.ConversationFactory; + +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ */ +public abstract class BaseCircuitFactory implements CircuitFactory +{ + /** Used for debugging. */ + private final Logger log = Logger.getLogger(BaseCircuitFactory.class); + + /** Holds the contact details for the sending test client. */ + protected TestClientDetails sender; + + /** Holds the contact details for the receving test client. */ + protected List receivers = new LinkedList(); + + /** Holds the conversation factory over which to coordinate the test. */ + protected ConversationFactory conversationFactory; + + /** + * Creates a test circuit for the test, configered by the test parameters specified. + * + * @param testProperties The test parameters. + * @return A test circuit. + */ + public Circuit createCircuit(Properties testProperties) + { + throw new RuntimeException("Not implemented."); + } + + /** + * Sets the sender test client to coordinate the test with. + * + * @param sender The contact details of the sending client in the test. + */ + public void setSender(TestClientDetails sender) + { + log.debug("public void setSender(TestClientDetails sender = " + sender + "): called"); + + this.sender = sender; + } + + /** + * Sets the receiving test client to coordinate the test with. + * + * @param receiver The contact details of the sending client in the test. + */ + public void setReceiver(TestClientDetails receiver) + { + log.debug("public void setReceiver(TestClientDetails receivers = " + receiver + "): called"); + + this.receivers.add(receiver); + } + + /** + * Supplies the sending test client. + * + * @return The sending test client. + */ + public TestClientDetails getSender() + { + return sender; + } + + /** + * Supplies the receiving test client. + * + * @return The receiving test client. + */ + public List getReceivers() + { + return receivers; + } + + /** + * Accepts the conversation factory over which to hold the test coordinating conversation. + * + * @param conversationFactory The conversation factory to coordinate the test over. + */ + public void setConversationFactory(ConversationFactory conversationFactory) + { + this.conversationFactory = conversationFactory; + } + + /** + * Provides the conversation factory for providing the distributed test sequencing conversations over the test + * connection. + * + * @return The conversation factory to create test sequencing conversations with. + */ + public ConversationFactory getConversationFactory() + { + return conversationFactory; + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseDistributedTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseDistributedTestSequencer.java deleted file mode 100644 index a0e3d3b4a6..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseDistributedTestSequencer.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.framework.distributedtesting.DistributedTestCase; -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.util.ConversationFactory; - -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -/** - *

- *
CRC Card
Responsibilities Collaborations - *
- *
- */ -public abstract class BaseDistributedTestSequencer implements DistributedTestSequencer -{ - /** Used for debugging. */ - private final Logger log = Logger.getLogger(DistributedTestCase.class); - - /** Holds the contact details for the sending test client. */ - protected TestClientDetails sender; - - /** Holds the contact details for the receving test client. */ - protected List receivers = new LinkedList(); - - /** Holds the conversation factory over which to coordinate the test. */ - protected ConversationFactory conversationFactory; - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * @return A test circuit. - */ - public Circuit createCircuit(Properties testProperties) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Sets the sender test client to coordinate the test with. - * - * @param sender The contact details of the sending client in the test. - */ - public void setSender(TestClientDetails sender) - { - log.debug("public void setSender(TestClientDetails sender = " + sender + "): called"); - - this.sender = sender; - } - - /** - * Sets the receiving test client to coordinate the test with. - * - * @param receiver The contact details of the sending client in the test. - */ - public void setReceiver(TestClientDetails receiver) - { - log.debug("public void setReceiver(TestClientDetails receivers = " + receiver + "): called"); - - this.receivers.add(receiver); - } - - /** - * Supplies the sending test client. - * - * @return The sending test client. - */ - public TestClientDetails getSender() - { - return sender; - } - - /** - * Supplies the receiving test client. - * - * @return The receiving test client. - */ - public List getReceivers() - { - return receivers; - } - - /** - * Accepts the conversation factory over which to hold the test coordinating conversation. - * - * @param conversationFactory The conversation factory to coordinate the test over. - */ - public void setConversationFactory(ConversationFactory conversationFactory) - { - this.conversationFactory = conversationFactory; - } - - /** - * Provides the conversation factory for providing the distributed test sequencing conversations over the test - * connection. - * - * @return The conversation factory to create test sequencing conversations with. - */ - public ConversationFactory getConversationFactory() - { - return conversationFactory; - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java new file mode 100644 index 0000000000..82caa20d79 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java @@ -0,0 +1,111 @@ +/* + * + * 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.sequencers; + +import org.apache.qpid.test.framework.Assertion; +import org.apache.qpid.test.framework.Circuit; +import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.util.ConversationFactory; + +import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; + +import javax.jms.JMSException; +import javax.jms.Message; + +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * A TestCaseSequence is responsibile for creating test circuits appropriate to the context that a test case is + * running in, and providing an implementation of a standard test procedure over a test circuit. + * + *

+ *
CRC Card
Responsibilities + *
Provide a standard test procedure over a test circuit. + *
Construct test circuits appropriate to a tests context. + *
+ * + * @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 +{ + /** + * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, + * begining the test, gathering the test reports from the participants, and checking for assertion failures against + * the test reports. + * + * @param testCircuit The test circuit. + * @param assertions The list of assertions to apply to the test circuit. + * @param testProperties The test case definition. + * + * @deprecated Use test circuits and Circuit.test instead. + */ + public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties); + + /** + * Creates a test circuit for the test, configered by the test parameters specified. + * + * @param testProperties The test parameters. + * + * @return A test circuit. + */ + public Circuit createCircuit(ParsedProperties testProperties); + + /** + * Sets the sender test client to coordinate the test with. + * + * @param sender The contact details of the sending client in the test. + */ + public void setSender(TestClientDetails sender); + + /** + * Sets the receiving test client to coordinate the test with. + * + * @param receiver The contact details of the sending client in the test. + */ + public void setReceiver(TestClientDetails receiver); + + /** + * Supplies the sending test client. + * + * @return The sending test client. + */ + public TestClientDetails getSender(); + + /** + * Supplies the receiving test client. + * + * @return The receiving test client. + */ + public List getReceivers(); + + /** + * Accepts the conversation factory over which to hold the test coordinating conversation. + * + * @param conversationFactory The conversation factory to coordinate the test over. + */ + public void setConversationFactory(ConversationFactory conversationFactory); +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/DistributedTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/DistributedTestSequencer.java deleted file mode 100644 index 73e61ec921..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/DistributedTestSequencer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.util.ConversationFactory; - -import java.util.List; - -/** - * A DistributedTestSequencer is a test sequencer that coordinates activity amongst many - * {@link org.apache.qpid.test.framework.distributedtesting.TestClient}s. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Accept notification of test case participants. - *
Accept JMS Connection to carry out the coordination over. - *
Coordinate a test sequence amongst participants. {@link ConversationFactory} - *
- */ -public interface DistributedTestSequencer extends TestCaseSequencer -{ - /** - * Sets the sender test client to coordinate the test with. - * - * @param sender The contact details of the sending client in the test. - */ - public void setSender(TestClientDetails sender); - - /** - * Sets the receiving test client to coordinate the test with. - * - * @param receiver The contact details of the sending client in the test. - */ - public void setReceiver(TestClientDetails receiver); - - /** - * Supplies the sending test client. - * - * @return The sending test client. - */ - public TestClientDetails getSender(); - - /** - * Supplies the receiving test client. - * - * @return The receiving test client. - */ - public List getReceivers(); - - /** - * Accepts the conversation factory over which to hold the test coordinating conversation. - * - * @param conversationFactory The conversation factory to coordinate the test over. - */ - public void setConversationFactory(ConversationFactory conversationFactory); -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java new file mode 100644 index 0000000000..673b47df03 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java @@ -0,0 +1,201 @@ +/* + * + * 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.sequencers; + +import org.apache.log4j.Logger; + +import org.apache.qpid.test.framework.Assertion; +import org.apache.qpid.test.framework.Circuit; +import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.test.framework.TestUtils; +import org.apache.qpid.test.framework.distributedcircuit.DistributedCircuitImpl; +import org.apache.qpid.util.ConversationFactory; + +import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Session; + +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +/** + * FanOutCircuitFactory 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 the remainder to the RECEIVER role. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ * + * @todo Adapt this to be an n*m topology circuit factory. Need to add circuit topology definitions to the test + * parameters. Place n senders onto the available test clients, and m receivers. Where n or m is larger than + * the available nodes, start stacking multiple test clients on each node. There will also be an option that + * indicates whether nodes can play both roles, and how many nodes out of all available may be assigned to + * each role. + * + * @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 + * 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 + * creation, but the runs many tests over it, in which case the handling of responsibilities becomes clearer. + */ +public class FanOutCircuitFactory extends BaseCircuitFactory +{ + /** Used for debugging. */ + Logger log = Logger.getLogger(FanOutCircuitFactory.class); + + /** + * 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) + { + log.debug("public Circuit createCircuit(ParsedProperties testProperties): called"); + + List senders = new LinkedList(); + senders.add(getSender()); + List receivers = getReceivers(); + ConversationFactory conversationFactory = getConversationFactory(); + + return DistributedCircuitImpl.createCircuit(testProperties, senders, receivers, conversationFactory); + } + + /** + * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, + * begining the test, gathering the test reports from the participants, and checking for assertion failures against + * the test reports. + * + * @param testCircuit The test circuit. + * @param assertions The list of assertions to apply to the test circuit. + * @param testProperties The test case definition. + * + * @deprecated Scheduled for removal once existing tests converted over to use test circuits. + */ + public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties) + { + log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called"); + + TestClientDetails sender = getSender(); + List receivers = getReceivers(); + ConversationFactory conversationFactory = getConversationFactory(); + + try + { + // Create a conversation on the sender clients private control route. + Session session = conversationFactory.getSession(); + Destination senderControlTopic = session.createTopic(sender.privateControlKey); + ConversationFactory.Conversation senderConversation = conversationFactory.startConversation(); + + // Assign the sender role to the sending test client. + Message assignSender = conversationFactory.getSession().createMessage(); + TestUtils.setPropertiesOnMessage(assignSender, testProperties); + assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); + assignSender.setStringProperty("ROLE", "SENDER"); + assignSender.setStringProperty("CLIENT_NAME", "Sustained_SENDER"); + + senderConversation.send(senderControlTopic, assignSender); + + // Wait for the sender to confirm its role. + senderConversation.receive(); + + // Assign the receivers roles. + for (TestClientDetails receiver : receivers) + { + assignReceiverRole(receiver, testProperties, true); + } + + // Start the test on the sender. + Message start = session.createMessage(); + start.setStringProperty("CONTROL_TYPE", "START"); + + senderConversation.send(senderControlTopic, start); + + // Wait for the test sender to return its report. + Message senderReport = senderConversation.receive(); + TestUtils.pause(500); + + // Ask the receivers for their reports. + Message statusRequest = session.createMessage(); + statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); + + // Gather the reports from all of the receiving clients. + + // Return all of the test reports, the senders report first. + // return new Message[] { senderReport }; + } + catch (JMSException e) + { + throw new RuntimeException("Unhandled JMSException."); + } + } + + /** + * Assigns the receivers role to the specified test client that is to act as a receivers during the test. This method + * does not always wait for the receiving clients to confirm their role assignments. This is because this method + * may be called from an 'onMessage' method, when a client is joining the test at a later point in time, and it + * is not possible to do a synchronous receive during an 'onMessage' method. There is a flag to indicate whether + * or not to wait for role confirmations. + * + * @param receiver The test client to assign the receivers role to. + * @param testProperties The test parameters. + * @param confirm Indicates whether role confirmation should be waited for. + * + * @throws JMSException Any JMSExceptions occurring during the conversation are allowed to fall through. + * + * @deprecated Scheduled for removal once existing tests converted over to use test circuits. + */ + protected void assignReceiverRole(TestClientDetails receiver, Properties testProperties, boolean confirm) + throws JMSException + { + log.info("assignReceiverRole(TestClientDetails receivers = " + receiver + ", Map testProperties = " + + testProperties + "): called"); + + ConversationFactory conversationFactory = getConversationFactory(); + + // Create a conversation with the receiving test client. + Session session = conversationFactory.getSession(); + Destination receiverControlTopic = session.createTopic(receiver.privateControlKey); + ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation(); + + // Assign the receivers role to the receiving client. + Message assignReceiver = session.createMessage(); + TestUtils.setPropertiesOnMessage(assignReceiver, testProperties); + assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); + assignReceiver.setStringProperty("ROLE", "RECEIVER"); + assignReceiver.setStringProperty("CLIENT_NAME", receiver.clientName); + + receiverConversation.send(receiverControlTopic, assignReceiver); + + // Wait for the role confirmation to come back. + if (confirm) + { + receiverConversation.receive(); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutTestSequencer.java deleted file mode 100644 index a116b23065..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutTestSequencer.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.util.ConversationFactory; - -import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; - -import java.util.List; -import java.util.Properties; - -/** - *

- *
CRC Card
Responsibilities Collaborations - *
- *
- */ -public class FanOutTestSequencer extends BaseDistributedTestSequencer -{ - /** Used for debugging. */ - Logger log = Logger.getLogger(FanOutTestSequencer.class); - - /** - * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, - * begining the test, gathering the test reports from the participants, and checking for assertion failures against - * the test reports. - * - * @param testCircuit The test circuit. - * @param assertions The list of assertions to apply to the test circuit. - * @param testProperties The test case definition. - */ - public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties) - { - log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called"); - - TestClientDetails sender = getSender(); - List receivers = getReceivers(); - ConversationFactory conversationFactory = getConversationFactory(); - - try - { - // Create a conversation on the sender clients private control rouete. - Session session = conversationFactory.getSession(); - Destination senderControlTopic = session.createTopic(sender.privateControlKey); - ConversationFactory.Conversation senderConversation = conversationFactory.startConversation(); - - // Assign the sender role to the sending test client. - Message assignSender = conversationFactory.getSession().createMessage(); - TestUtils.setPropertiesOnMessage(assignSender, testProperties); - assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignSender.setStringProperty("ROLE", "SENDER"); - assignSender.setStringProperty("CLIENT_NAME", "Sustained_SENDER"); - - senderConversation.send(senderControlTopic, assignSender); - - // Wait for the sender to confirm its role. - senderConversation.receive(); - - // Assign the receivers roles. - for (TestClientDetails receiver : receivers) - { - assignReceiverRole(receiver, testProperties, true); - } - - // Start the test on the sender. - Message start = session.createMessage(); - start.setStringProperty("CONTROL_TYPE", "START"); - - senderConversation.send(senderControlTopic, start); - - // Wait for the test sender to return its report. - Message senderReport = senderConversation.receive(); - TestUtils.pause(500); - - // Ask the receivers for their reports. - Message statusRequest = session.createMessage(); - statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); - - // Gather the reports from all of the receiving clients. - - // Return all of the test reports, the senders report first. - // return new Message[] { senderReport }; - } - catch (JMSException e) - { - throw new RuntimeException("Unhandled JMSException."); - } - } - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * @return A test circuit. - */ - public Circuit createCircuit(ParsedProperties testProperties) - { - throw new RuntimeException("Not implemented."); - } - - /** - * Assigns the receivers role to the specified test client that is to act as a receivers during the test. This method - * does not always wait for the receiving clients to confirm their role assignments. This is because this method - * may be called from an 'onMessage' method, when a client is joining the test at a later point in time, and it - * is not possible to do a synchronous receive during an 'onMessage' method. There is a flag to indicate whether - * or not to wait for role confirmations. - * - * @param receiver The test client to assign the receivers role to. - * @param testProperties The test parameters. - * @param confirm Indicates whether role confirmation should be waited for. - * - * @throws JMSException Any JMSExceptions occurring during the conversation are allowed to fall through. - */ - protected void assignReceiverRole(TestClientDetails receiver, Properties testProperties, boolean confirm) - throws JMSException - { - log.info("assignReceiverRole(TestClientDetails receivers = " + receiver + ", Map testProperties = " - + testProperties + "): called"); - - ConversationFactory conversationFactory = getConversationFactory(); - - // Create a conversation with the receiving test client. - Session session = conversationFactory.getSession(); - Destination receiverControlTopic = session.createTopic(receiver.privateControlKey); - ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation(); - - // Assign the receivers role to the receiving client. - Message assignReceiver = session.createMessage(); - TestUtils.setPropertiesOnMessage(assignReceiver, testProperties); - assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignReceiver.setStringProperty("ROLE", "RECEIVER"); - assignReceiver.setStringProperty("CLIENT_NAME", receiver.clientName); - - receiverConversation.send(receiverControlTopic, assignReceiver); - - // Wait for the role confirmation to come back. - if (confirm) - { - receiverConversation.receive(); - } - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java new file mode 100644 index 0000000000..fa4e43e6d6 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java @@ -0,0 +1,146 @@ +/* + * + * 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.sequencers; + +import org.apache.log4j.Logger; + +import org.apache.qpid.test.framework.Assertion; +import org.apache.qpid.test.framework.Circuit; +import org.apache.qpid.test.framework.TestClientDetails; +import org.apache.qpid.test.framework.TestUtils; +import org.apache.qpid.test.framework.distributedcircuit.DistributedCircuitImpl; +import org.apache.qpid.util.ConversationFactory; + +import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; + +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Session; + +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
+ *
+ */ +public class InteropCircuitFactory extends BaseCircuitFactory +{ + /** Used for debugging. */ + Logger log = Logger.getLogger(InteropCircuitFactory.class); + + /** + * 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) + { + log.debug("public Circuit createCircuit(ParsedProperties testProperties): called"); + + List senders = new LinkedList(); + senders.add(getSender()); + List receivers = getReceivers(); + ConversationFactory conversationFactory = getConversationFactory(); + + return DistributedCircuitImpl.createCircuit(testProperties, senders, receivers, conversationFactory); + } + + /** + * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, + * begining the test, gathering the test reports from the participants, and checking for assertion failures against + * the test reports. + * + * @param testCircuit The test circuit. + * @param assertions The list of assertions to apply to the test circuit. + * @param testProperties The test case definition. + */ + public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties) + { + log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called"); + + TestClientDetails sender = getSender(); + List receivers = getReceivers(); + ConversationFactory conversationFactory = getConversationFactory(); + + try + { + Session session = conversationFactory.getSession(); + Destination senderControlTopic = session.createTopic(sender.privateControlKey); + Destination receiverControlTopic = session.createTopic(receivers.get(0).privateControlKey); + + ConversationFactory.Conversation senderConversation = conversationFactory.startConversation(); + ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation(); + + // Assign the sender role to the sending test client. + Message assignSender = conversationFactory.getSession().createMessage(); + TestUtils.setPropertiesOnMessage(assignSender, testProperties); + assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); + assignSender.setStringProperty("ROLE", "SENDER"); + + senderConversation.send(senderControlTopic, assignSender); + + // Assign the receivers role the receiving client. + Message assignReceiver = session.createMessage(); + TestUtils.setPropertiesOnMessage(assignReceiver, testProperties); + assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); + assignReceiver.setStringProperty("ROLE", "RECEIVER"); + + receiverConversation.send(receiverControlTopic, assignReceiver); + + // Wait for the senders and receivers to confirm their roles. + senderConversation.receive(); + receiverConversation.receive(); + + // Start the test. + Message start = session.createMessage(); + start.setStringProperty("CONTROL_TYPE", "START"); + + senderConversation.send(senderControlTopic, start); + + // Wait for the test sender to return its report. + Message senderReport = senderConversation.receive(); + TestUtils.pause(500); + + // Ask the receivers for its report. + Message statusRequest = session.createMessage(); + statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); + + receiverConversation.send(receiverControlTopic, statusRequest); + + // Wait for the receivers to send its report. + Message receiverReport = receiverConversation.receive(); + + // return new Message[] { senderReport, receiverReport }; + + // Apply assertions. + } + catch (JMSException e) + { + throw new RuntimeException("JMSException not handled."); + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropTestSequencer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropTestSequencer.java deleted file mode 100644 index f2253d416b..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropTestSequencer.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.framework.TestClientDetails; -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; -import org.apache.qpid.test.framework.TestUtils; -import org.apache.qpid.util.ConversationFactory; - -import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; - -import java.util.List; -import java.util.Properties; - -/** - *

- *
CRC Card
Responsibilities Collaborations - *
- *
- */ -public class InteropTestSequencer extends BaseDistributedTestSequencer -{ - /** Used for debugging. */ - Logger log = Logger.getLogger(InteropTestSequencer.class); - - /** - * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, - * begining the test, gathering the test reports from the participants, and checking for assertion failures against - * the test reports. - * - * @param testCircuit The test circuit. - * @param assertions The list of assertions to apply to the test circuit. - * @param testProperties The test case definition. - */ - public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties) - { - log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called"); - - TestClientDetails sender = getSender(); - List receivers = getReceivers(); - ConversationFactory conversationFactory = getConversationFactory(); - - try - { - Session session = conversationFactory.getSession(); - Destination senderControlTopic = session.createTopic(sender.privateControlKey); - Destination receiverControlTopic = session.createTopic(receivers.get(0).privateControlKey); - - ConversationFactory.Conversation senderConversation = conversationFactory.startConversation(); - ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation(); - - // Assign the sender role to the sending test client. - Message assignSender = conversationFactory.getSession().createMessage(); - TestUtils.setPropertiesOnMessage(assignSender, testProperties); - assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignSender.setStringProperty("ROLE", "SENDER"); - - senderConversation.send(senderControlTopic, assignSender); - - // Assign the receivers role the receiving client. - Message assignReceiver = session.createMessage(); - TestUtils.setPropertiesOnMessage(assignReceiver, testProperties); - assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); - assignReceiver.setStringProperty("ROLE", "RECEIVER"); - - receiverConversation.send(receiverControlTopic, assignReceiver); - - // Wait for the senders and receivers to confirm their roles. - senderConversation.receive(); - receiverConversation.receive(); - - // Start the test. - Message start = session.createMessage(); - start.setStringProperty("CONTROL_TYPE", "START"); - - senderConversation.send(senderControlTopic, start); - - // Wait for the test sender to return its report. - Message senderReport = senderConversation.receive(); - TestUtils.pause(500); - - // Ask the receivers for its report. - Message statusRequest = session.createMessage(); - statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); - - receiverConversation.send(receiverControlTopic, statusRequest); - - // Wait for the receivers to send its report. - Message receiverReport = receiverConversation.receive(); - - // return new Message[] { senderReport, receiverReport }; - - // Apply assertions. - } - catch (JMSException e) - { - throw new RuntimeException("JMSException not handled."); - } - } - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * @return A test circuit. - */ - public Circuit createCircuit(ParsedProperties testProperties) - { - throw new RuntimeException("Not implemented."); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/TestCaseSequencer.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/TestCaseSequencer.java deleted file mode 100644 index 4f09642467..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/TestCaseSequencer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.test.framework.sequencers; - -import org.apache.qpid.test.framework.Assertion; -import org.apache.qpid.test.framework.Circuit; - -import uk.co.thebadgerset.junit.extensions.util.ParsedProperties; - -import javax.jms.JMSException; -import javax.jms.Message; - -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * A TestCaseSequence is responsibile for creating test circuits appropriate to the context that a test case is - * running in, and providing an implementation of a standard test procedure over a test circuit. - * - *

- *
CRC Card
Responsibilities - *
Provide a standard test procedure over a test circuit. - *
Construct test circuits appropriate to a tests context. - *
- */ -public interface TestCaseSequencer -{ - /** - * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles, - * begining the test, gathering the test reports from the participants, and checking for assertion failures against - * the test reports. - * - * @param testCircuit The test circuit. - * @param assertions The list of assertions to apply to the test circuit. - * @param testProperties The test case definition. - */ - public void sequenceTest(Circuit testCircuit, List assertions, Properties testProperties); - - /** - * Creates a test circuit for the test, configered by the test parameters specified. - * - * @param testProperties The test parameters. - * - * @return A test circuit. - */ - public Circuit createCircuit(ParsedProperties testProperties); -} diff --git a/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java b/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java index 0090bec3d0..a325e7025e 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 @@ -87,7 +87,7 @@ import java.util.concurrent.atomic.AtomicLong; * *

Conversation correlation id's are generated on a per thread basis. * - *

The same session is shared amongst all conversations. Calls to send are therefore synchronized because JMS + *

The same controlSession is shared amongst all conversations. Calls to send are therefore synchronized because JMS * sessions are not multi-threaded. * *

@@ -108,7 +108,7 @@ public class ConversationFactory /** Holds the connection over which the conversation is conducted. */ private Connection connection; - /** Holds the session over which the conversation is conduxted. */ + /** Holds the controlSession over which the conversation is conduxted. */ private Session session; /** The message consumer for incoming messages. */ @@ -219,9 +219,9 @@ public class ConversationFactory } /** - * Gets the session over which the conversation is conducted. + * Gets the controlSession over which the conversation is conducted. * - * @return The session over which the conversation is conducted. + * @return The controlSession over which the conversation is conducted. */ public Session getSession() { -- cgit v1.2.1
CRC Card