You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ru...@apache.org on 2007/07/25 14:18:03 UTC

svn commit: r559419 [1/3] - in /incubator/qpid/branches/M2/java: broker/src/main/java/org/apache/qpid/server/queue/ common/src/main/java/org/apache/qpid/util/ etc/ integrationtests/src/main/java/org/apache/qpid/interop/coordinator/ integrationtests/src...

Author: rupertlssmith
Date: Wed Jul 25 05:17:59 2007
New Revision: 559419

URL: http://svn.apache.org/viewvc?view=rev&rev=559419
Log:
Refactored interop tests into general distributed test framework. Moved framework under systests from integrationtests.

Added:
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/util/
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/util/ClasspathScanner.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java
Removed:
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestCase.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestCase.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java
Modified:
    incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
    incubator/qpid/branches/M2/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
    incubator/qpid/branches/M2/java/etc/coding_standards.xml
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
    incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
    incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
    incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
    incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/exchange/MandatoryMessageTest.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTestManual.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Circuit.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java
    incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java

Modified: incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java (original)
+++ incubator/qpid/branches/M2/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java Wed Jul 25 05:17:59 2007
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.server.queue;
 
+
 public interface QueueNotificationListener
 {
     void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);

Modified: incubator/qpid/branches/M2/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java (original)
+++ incubator/qpid/branches/M2/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java Wed Jul 25 05:17:59 2007
@@ -483,9 +483,9 @@
     }
 
     /**
-     * If a command line has been parsed, calling this method sets all of its parsed options as system properties.
+     * If a command line has been parsed, calling this method sets all of its parsed options into the specified properties.
      */
-    public void addCommandLineToSysProperties()
+    public void addCommandLineToProperties(Properties properties)
     {
         if (parsedProperties != null)
         {
@@ -494,7 +494,7 @@
                 String name = (String) propKey;
                 String value = parsedProperties.getProperty(name);
 
-                System.setProperty(name, value);
+                properties.setProperty(name, value);
             }
         }
     }
@@ -606,11 +606,13 @@
      * Extracts all name=value pairs from the command line, sets them all as system properties and also returns
      * a map of properties containing them.
      *
-     * @param args The command line.
+     * @param args        The command line.
+     * @param commandLine The command line parser.
+     * @param properties  The properties object to inject all parsed properties into (optional may be <tt>null</tt>).
      *
      * @return A set of properties containing all name=value pairs from the command line.
      */
-    public static Properties processCommandLine(String[] args, CommandLineParser commandLine)
+    public static Properties processCommandLine(String[] args, CommandLineParser commandLine, Properties properties)
     {
         // Capture the command line arguments or display errors and correct usage and then exit.
         Properties options = null;
@@ -621,7 +623,7 @@
 
             // Add all the trailing command line options (name=value pairs) to system properties. They may be picked up
             // from there.
-            commandLine.addCommandLineToSysProperties();
+            commandLine.addCommandLineToProperties(properties);
         }
         catch (IllegalArgumentException e)
         {

Modified: incubator/qpid/branches/M2/java/etc/coding_standards.xml
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/etc/coding_standards.xml?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/etc/coding_standards.xml (original)
+++ incubator/qpid/branches/M2/java/etc/coding_standards.xml Wed Jul 25 05:17:59 2007
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.1//EN" "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
 <module name="Checker">
+
     <!-- Checks package.html defined for all packages. -->
-    <module name="PackageHtml"/>
+    <!-- <module name="PackageHtml"/> -->
 
     <module name="TreeWalker">
 

Added: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java (added)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CircuitTestCase.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,101 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator.testcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+/**
+ * CircuitTestCase runs a test over a {@link Circuit} controlled by the test parameters.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ *
+ * @todo When working with test context properties, add overrides to defaults to the singleton instance, but when taking
+ *       a starting point to add specific test case parameters to, take a copy. Use the copy with test case specifics
+ *       to control the test.
+ */
+public class CircuitTestCase extends FrameworkBaseCase
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(CircuitTestCase.class);
+
+    /**
+     * Creates a new test case with the specified name.
+     *
+     * @param name The test case name.
+     */
+    public CircuitTestCase(String name)
+    {
+        super(name);
+    }
+
+    /**
+     * Performs the a basic P2P test case.
+     *
+     * @throws Exception Any exceptions are allowed to fall through and fail the test.
+     */
+    public void testBasicP2P() throws Exception
+    {
+        log.debug("public void testBasicP2P(): called");
+
+        // Get the test parameters, any overrides on the command line will have been applied.
+        ParsedProperties testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+        // Customize the test parameters.
+        testProps.setProperty("TEST_NAME", "DEFAULT_CIRCUIT_TEST");
+        testProps.setProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME, "testqueue");
+
+        // Get the test sequencer to create test circuits and run the standard test procedure through.
+        TestCaseSequencer sequencer = getTestSequencer();
+
+        // Send the test messages, and check that there were no errors doing so.
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
+
+        // Check that all of the message were sent.
+        // Check that the receiving end got the same number of messages as the publishing end.
+    }
+
+    /**
+     * Should provide a translation from the junit method name of a test to its test case name as known to the test
+     * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+     * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+     * name "TC2_BasicP2P".
+     *
+     * @param methodName The name of the JUnit test method.
+     *
+     * @return The name of the corresponding interop test case.
+     */
+    public String getTestCaseNameForTestMethod(String methodName)
+    {
+        return "DEFAULT_CIRCUIT_TEST";
+    }
+}

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase1DummyRun.java Wed Jul 25 05:17:59 2007
@@ -20,28 +20,23 @@
  */
 package org.apache.qpid.interop.coordinator.testcases;
 
-import junit.framework.Assert;
-
 import org.apache.log4j.Logger;
 
-import org.apache.qpid.interop.coordinator.InteropTestCase;
-
-import javax.jms.Message;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
 
 /**
- * Coordinates test case 1, from the interop test specification. This test connects up the sender and receiver roles,
+ * Coordinates test case 1, from the interop test specification. This test connects up the sender and receivers roles,
  * and gets some dummy test reports from them, in order to check that the test framework itself is operational.
  *
  * <p><table id="crc"><caption>CRC Card</caption>
  * <tr><th> Responsibilities <th> Collaborations
  * <tr><td> Exercises the interop testing framework without actually sending any test messages.
- *     <td> {@link org.apache.qpid.interop.coordinator.InteropTestCase}
+ *     <td> {@link org.apache.qpid.interop.coordinator.DistributedTestCase}
  * </table>
  */
-public class InteropTestCase1DummyRun extends InteropTestCase
+public class InteropTestCase1DummyRun extends DistributedTestCase
 {
     /** Used for debugging. */
     private static final Logger log = Logger.getLogger(InteropTestCase1DummyRun.class);
@@ -65,13 +60,13 @@
     {
         log.debug("public void testDummyRun(): called");
 
-        Map<String, Object> testConfig = new HashMap<String, Object>();
+        Properties testConfig = new Properties();
         testConfig.put("TEST_NAME", "TC1_DummyRun");
 
-        Message[] reports = sequenceTest(testConfig);
+        /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig);
 
-        // Compare sender and receiver reports.
-        Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length);
+        // Compare sender and receivers reports.
+        // Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length);
     }
 
     /**

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase2BasicP2P.java Wed Jul 25 05:17:59 2007
@@ -20,28 +20,23 @@
  */
 package org.apache.qpid.interop.coordinator.testcases;
 
-import junit.framework.Assert;
-
 import org.apache.log4j.Logger;
 
-import org.apache.qpid.interop.coordinator.InteropTestCase;
-
-import javax.jms.Message;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
 
 /**
  * Implements test case 2, from the interop test specification. This test sets up the TC2_BasicP2P test for 50
- * messages. It checks that the sender and receiver reports both indicate that all the test messages were transmitted
+ * messages. It checks that the sender and receivers reports both indicate that all the test messages were transmitted
  * successfully.
  *
  * <p><table id="crc"><caption>CRC Card</caption>
  * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link InteropTestCase}
+ * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link DistributedTestCase}
  * </table>
  */
-public class InteropTestCase2BasicP2P extends InteropTestCase
+public class InteropTestCase2BasicP2P extends DistributedTestCase
 {
     /** Used for debugging. */
     private static final Logger log = Logger.getLogger(InteropTestCase2BasicP2P.class);
@@ -65,19 +60,19 @@
     {
         log.debug("public void testBasicP2P(): called");
 
-        Map<String, Object> testConfig = new HashMap<String, Object>();
-        testConfig.put("TEST_NAME", "TC2_BasicP2P");
-        testConfig.put("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
+        Properties testConfig = new Properties();
+        testConfig.setProperty("TEST_NAME", "TC2_BasicP2P");
+        testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
         testConfig.put("P2P_NUM_MESSAGES", 50);
 
-        Message[] reports = sequenceTest(testConfig);
+        /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig);
 
-        // Compare sender and receiver reports.
-        int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+        // Compare sender and receivers reports.
+        /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
         int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
 
         Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
-        Assert.assertEquals("Sender and receiver messages sent did not match up.", messagesSent, messagesReceived);
+        Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);*/
     }
 
     /**

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/InteropTestCase3BasicPubSub.java Wed Jul 25 05:17:59 2007
@@ -20,24 +20,19 @@
  */
 package org.apache.qpid.interop.coordinator.testcases;
 
-import junit.framework.Assert;
-
 import org.apache.log4j.Logger;
 
-import org.apache.qpid.interop.coordinator.InteropTestCase;
-
-import javax.jms.Message;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
 
 /**
  * <p><table id="crc"><caption>CRC Card</caption>
  * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link InteropTestCase}
+ * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link DistributedTestCase}
  * </table>
  */
-public class InteropTestCase3BasicPubSub extends InteropTestCase
+public class InteropTestCase3BasicPubSub extends DistributedTestCase
 {
     /** Used for debugging. */
     private static final Logger log = Logger.getLogger(InteropTestCase3BasicPubSub.class);
@@ -61,21 +56,21 @@
     {
         log.debug("public void testBasicPubSub(): called");
 
-        Map<String, Object> testConfig = new HashMap<String, Object>();
+        Properties testConfig = new Properties();
         testConfig.put("TEST_NAME", "TC3_BasicPubSub");
         testConfig.put("PUBSUB_KEY", "tc3route");
         testConfig.put("PUBSUB_NUM_MESSAGES", 10);
         testConfig.put("PUBSUB_NUM_RECEIVERS", 5);
 
-        Message[] reports = sequenceTest(testConfig);
+        /*Message[] reports =*/ getTestSequencer().sequenceTest(null, null, testConfig);
 
-        // Compare sender and receiver reports.
-        int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+        // Compare sender and receivers reports.
+        /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
         int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
 
         Assert.assertEquals("The requested number of messages were not sent.", 10, messagesSent);
         Assert.assertEquals("Received messages did not match up to num sent * num receivers.", messagesSent * 5,
-            messagesReceived);
+            messagesReceived);*/
     }
 
     /**

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java Wed Jul 25 05:17:59 2007
@@ -47,7 +47,7 @@
         /** Specifies the sender role. */
         SENDER,
 
-        /** Specifies the receiver role. */
+        /** Specifies the receivers role. */
         RECEIVER
     }
 
@@ -74,7 +74,7 @@
      * Assigns the role to be played by this test case. The test parameters are fully specified in the
      * assignment message. When this method return the test case will be ready to execute.
      *
-     * @param role              The role to be played; sender or receiver.
+     * @param role              The role to be played; sender or receivers.
      * @param assignRoleMessage The role assingment message, contains the full test parameters.
      *
      * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java Wed Jul 25 05:17:59 2007
@@ -25,6 +25,7 @@
 import org.apache.qpid.interop.testclient.testcases.TestCase1DummyRun;
 import org.apache.qpid.interop.testclient.testcases.TestCase2BasicP2P;
 import org.apache.qpid.interop.testclient.testcases.TestCase3BasicPubSub;
+import org.apache.qpid.sustained.SustainedClientTestCase;
 import org.apache.qpid.test.framework.MessagingTestConfigProperties;
 import org.apache.qpid.test.framework.TestUtils;
 
@@ -63,7 +64,10 @@
 public class TestClient implements MessageListener
 {
     /** Used for debugging. */
-    private static Logger log = Logger.getLogger(TestClient.class);
+    private static final Logger log = Logger.getLogger(TestClient.class);
+
+    /** Used for reporting to the console. */
+    private static final Logger console = Logger.getLogger("CONSOLE");
 
     /** Holds the default identifying name of the test client. */
     public static final String CLIENT_NAME = "java";
@@ -169,7 +173,8 @@
         Collection<Class<? extends InteropClientTestCase>> testCaseClasses =
             new ArrayList<Class<? extends InteropClientTestCase>>();
         // ClasspathScanner.getMatches(InteropClientTestCase.class, "^TestCase.*", true);
-        Collections.addAll(testCaseClasses, TestCase1DummyRun.class, TestCase2BasicP2P.class, TestCase3BasicPubSub.class);
+        Collections.addAll(testCaseClasses, TestCase1DummyRun.class, TestCase2BasicP2P.class, TestCase3BasicPubSub.class,
+            SustainedClientTestCase.class);
 
         try
         {
@@ -285,7 +290,7 @@
                     }
                     else
                     {
-                        log.warn("'" + testName + "' not part of this clients tests.");
+                        log.debug("Received an invite to the test '" + testName + "' but this test is not known.");
                     }
                 }
                 else

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java Wed Jul 25 05:17:59 2007
@@ -80,7 +80,7 @@
      * Assigns the role to be played by this test case. The test parameters are fully specified in the
      * assignment message. When this method return the test case will be ready to execute.
      *
-     * @param role              The role to be played; sender or receiver.
+     * @param role              The role to be played; sender or receivers.
      * @param assignRoleMessage The role assingment message, contains the full test parameters.
      *
      * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java Wed Jul 25 05:17:59 2007
@@ -98,7 +98,7 @@
      * Assigns the role to be played by this test case. The test parameters are fully specified in the
      * assignment message. When this method return the test case will be ready to execute.
      *
-     * @param role              The role to be played; sender or receiver.
+     * @param role              The role to be played; sender or receivers.
      *
      * @param assignRoleMessage The role assingment message, contains the full test parameters.
      *
@@ -134,7 +134,7 @@
             producer = session.createProducer(sendDestination);
             break;
 
-        // Otherwise the receiver role is being assigned, so set this up to listen for messages.
+        // Otherwise the receivers role is being assigned, so set this up to listen for messages.
         case RECEIVER:
             MessageConsumer consumer = session.createConsumer(sendDestination);
             consumer.setMessageListener(this);

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase3BasicPubSub.java Wed Jul 25 05:17:59 2007
@@ -30,7 +30,7 @@
 
 /**
  * Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
- * default topic exchange, using the specified number of receiver connections. Produces reports on the actual number of
+ * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
  * messages sent/received.
  *
  * <p><table id="crc"><caption>CRC Card</caption>
@@ -99,7 +99,7 @@
      * Assigns the role to be played by this test case. The test parameters are fully specified in the
      * assignment message. When this method return the test case will be ready to execute.
      *
-     * @param role              The role to be played; sender or receiver.
+     * @param role              The role to be played; sender or receivers.
      *
      * @param assignRoleMessage The role assingment message, contains the full test parameters.
      *
@@ -143,10 +143,10 @@
             producer = session[0].createProducer(sendDestination);
             break;
 
-        // Otherwise the receiver role is being assigned, so set this up to listen for messages on the required number
-        // of receiver connections.
+        // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
+        // of receivers connections.
         case RECEIVER:
-            // Create the required number of receiver connections.
+            // Create the required number of receivers connections.
             connection = new Connection[numReceivers];
             session = new Session[numReceivers];
 

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java Wed Jul 25 05:17:59 2007
@@ -46,7 +46,7 @@
 
 /**
  * Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
- * default topic exchange, using the specified number of receiver connections. Produces reports on the actual number of
+ * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
  * messages sent/received.
  *
  * <p><table id="crc"><caption>CRC Card</caption>
@@ -68,7 +68,7 @@
     /** The role to be played by the test. */
     private Roles role;
 
-    /** The number of receiver connection to use. */
+    /** The number of receivers connection to use. */
     private int numReceivers;
 
     /** The routing key to send them to on the default direct exchange. */
@@ -114,7 +114,7 @@
      * Assigns the role to be played by this test case. The test parameters are fully specified in the assignment
      * message. When this method return the test case will be ready to execute.
      *
-     * @param role              The role to be played; sender or receiver.
+     * @param role              The role to be played; sender or receivers.
      * @param assignRoleMessage The role assingment message, contains the full test parameters.
      *
      * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
@@ -172,11 +172,11 @@
 
             break;
 
-        // Otherwise the receiver role is being assigned, so set this up to listen for messages on the required number
-        // of receiver connections.
+        // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
+        // of receivers connections.
         case RECEIVER:
             console.info("Creating Receiver");
-            // Create the required number of receiver connections.
+            // Create the required number of receivers connections.
             connection = new Connection[numReceivers];
             session = new Session[numReceivers];
 

Modified: incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java (original)
+++ incubator/qpid/branches/M2/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java Wed Jul 25 05:17:59 2007
@@ -23,18 +23,17 @@
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
 import org.apache.qpid.interop.coordinator.DropInTest;
 import org.apache.qpid.interop.coordinator.TestClientDetails;
-import org.apache.qpid.interop.coordinator.FanOutTestCase;
 
 import javax.jms.JMSException;
 import javax.jms.Message;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Properties;
 
 /**
- * SustainedTestCase is a {@link FanOutTestCase} that runs the "Perf_SustainedPubSub" test case. This consists of one
+ * SustainedTestCase is a {@link org.apache.qpid.interop.coordinator.DistributedTestCase} that runs the "Perf_SustainedPubSub" test case. This consists of one
  * test client sending, and several receiving, and attempts to find the highest rate at which messages can be broadcast
  * to the receivers. It is also a {@link DropInTest} to which more test clients may be added during a test run.
  *
@@ -43,7 +42,7 @@
  * <tr><td>
  * </table>
  */
-public class SustainedTestCase extends FanOutTestCase implements DropInTest
+public class SustainedTestCase extends DistributedTestCase implements DropInTest
 {
     /** Used for debugging. */
     Logger log = Logger.getLogger(SustainedTestCase.class);
@@ -70,7 +69,7 @@
     {
         log.debug("public void testSinglePubSubCycle(): called");
 
-        Map<String, Object> testConfig = new HashMap<String, Object>();
+        Properties testConfig = new Properties();
         testConfig.put("TEST_NAME", "Perf_SustainedPubSub");
         testConfig.put("SUSTAINED_KEY", SUSTAINED_KEY);
         testConfig.put("SUSTAINED_NUM_RECEIVERS", Integer.getInteger("numReceives", 2));
@@ -80,7 +79,7 @@
 
         log.info("Created Config: " + testConfig.entrySet().toArray());
 
-        sequenceTest(testConfig);
+        getTestSequencer().sequenceTest(null, null, testConfig);
     }
 
     /**
@@ -98,14 +97,17 @@
      */
     public void lateJoin(Message message) throws JMSException
     {
+        throw new RuntimeException("Not implemented.");
+        /*
         // Extract the joining clients details from its join request message.
         TestClientDetails clientDetails = new TestClientDetails();
         clientDetails.clientName = message.getStringProperty("CLIENT_NAME");
         clientDetails.privateControlKey = message.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY");
 
-        // Register the joining client, but do block for confirmation as cannot do a synchronous receiver during this
+        // Register the joining client, but do block for confirmation as cannot do a synchronous receivers during this
         // method call, as it may have been called from an 'onMessage' method.
-        assignReceiverRole(clientDetails, new HashMap<String, Object>(), false);
+        assignReceiverRole(clientDetails, new Properties(), false);
+         */
     }
 
     /**

Modified: incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java (original)
+++ incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java Wed Jul 25 05:17:59 2007
@@ -20,18 +20,6 @@
  */
 package org.apache.qpid.ping;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.requestreply.PingPongProducer;
@@ -40,6 +28,18 @@
 import uk.co.thebadgerset.junit.extensions.util.MathUtils;
 import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
 
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * PingDurableClient is a variation of the {@link PingPongProducer} ping tool. Instead of sending its pings and
  * receiving replies to them at the same time, this tool sends pings until it is signalled by some 'event' to stop
@@ -167,7 +167,8 @@
         try
         {
             // Create a ping producer overriding its defaults with all options passed on the command line.
-            Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}));
+            Properties options =
+                CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
             PingDurableClient pingProducer = new PingDurableClient(options);
 
             // Create a shutdown hook to terminate the ping-pong producer.

Modified: incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java (original)
+++ incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java Wed Jul 25 05:17:59 2007
@@ -57,7 +57,7 @@
         try
         {
             // Create a ping producer overriding its defaults with all options passed on the command line.
-            Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}));
+            Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
             PingSendOnlyClient pingProducer = new PingSendOnlyClient(options);
 
             // Create a shutdown hook to terminate the ping-pong producer.

Modified: incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java (original)
+++ incubator/qpid/branches/M2/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java Wed Jul 25 05:17:59 2007
@@ -44,9 +44,7 @@
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
-import java.util.concurrent.BrokenBarrierException;
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
@@ -89,7 +87,7 @@
  * <tr><td> destinationCount <td> 1        <td> The number of receivers listening to the pings.
  * <tr><td> timeout          <td> 30000    <td> In milliseconds. The timeout to stop waiting for replies.
  * <tr><td> commitBatchSize  <td> 1        <td> The number of messages per transaction in transactional mode.
- * <tr><td> uniqueDests      <td> true     <td> Whether each receiver only listens to one ping destination or all.
+ * <tr><td> uniqueDests      <td> true     <td> Whether each receivers only listens to one ping destination or all.
  * <tr><td> durableDests     <td> false    <td> Whether or not durable destinations are used.
  * <tr><td> ackMode          <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
  *                                               0 - SESSION_TRANSACTED
@@ -373,7 +371,7 @@
     protected int _maxPendingSize;
 
     /**
-     * Holds a monitor which is used to synchronize sender and receiver threads, where the sender has elected
+     * Holds a monitor which is used to synchronize sender and receivers threads, where the sender has elected
      * to wait until the number of unreceived message is reduced before continuing to send.
      */
     protected Object _sendPauseMonitor = new Object();
@@ -570,7 +568,8 @@
     {
         try
         {
-            Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}));
+            Properties options =
+                CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
 
             // Create a ping producer overriding its defaults with all options passed on the command line.
             PingPongProducer pingProducer = new PingPongProducer(options);

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,496 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.util.PrettyPrintingUtils;
+
+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.util.CommandLineParser;
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+import javax.jms.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * <p/>Implements the coordinator client described in the interop testing specification
+ * (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). This coordinator is built on
+ * top of the JUnit testing framework.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Find out what test clients are available. <td> {@link ConversationFactory}
+ * <tr><td> Decorate available tests to run all available clients. <td> {@link DistributedTestDecorator}
+ * <tr><td> Attach XML test result logger.
+ * <tr><td> Terminate the interop testing framework.
+ * </table>
+ *
+ * @todo Should accumulate failures over all tests, and return with success or fail code based on all results. May need
+ *       to write a special TestResult to do this properly. At the moment only the last one used will be tested for
+ *       errors, as the start method creates a fresh one for each test case run.
+ *
+ * @todo Remove hard coding of test cases and put on command line instead.
+ */
+public class Coordinator extends TKTestRunner
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(Coordinator.class);
+
+    /** Used for reporting to the console. */
+    private static final Logger console = Logger.getLogger("CONSOLE");
+
+    /** Defines the possible distributed test engines available to run coordinated test cases with. */
+    public enum TestEngine
+    {
+        /** Specifies the interop test engine. This tests all available clients in pairs. */
+        INTEROP,
+
+        /** Specifies the fanout test engine. This sets up one publisher role, and many reciever roles. */
+        FANOUT
+    }
+
+    /**
+     * Holds the test context properties that provides the default test parameters, plus command line overrides.
+     * This is initialized with the default test parameters, to which command line overrides may be applied.
+     */
+    protected static ParsedProperties testContextProperties =
+        TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+    /** Holds the URL of the broker to coordinate the tests on. */
+    protected String brokerUrl;
+
+    /** Holds the virtual host to coordinate the tests on. If <tt>null</tt>, then the default virtual host is used. */
+    protected String virtualHost;
+
+    /** Holds the list of all clients that enlisted, when the compulsory invite was issued. */
+    protected Set<TestClientDetails> enlistedClients = new HashSet<TestClientDetails>();
+
+    /** Holds the conversation helper for the control conversation. */
+    protected ConversationFactory conversationFactory;
+
+    /** Holds the connection that the coordinating messages are sent over. */
+    protected Connection connection;
+
+    /**
+     * Holds the name of the class of the test currently being run. Ideally passed into the {@link #createTestResult}
+     * method, but as the signature is already fixed for this, the current value gets pushed here as a member variable.
+     */
+    protected String currentTestClassName;
+
+    /** Holds the path of the directory to output test results too, if one is defined. */
+    protected String reportDir;
+
+    /** Holds the coordinating test engine type to run the tests through. */
+    protected TestEngine engine;
+
+    /** Flag that indicates that all test clients should be terminated upon completion of the test cases. */
+    protected boolean terminate;
+
+    /**
+     * Creates an interop test coordinator on the specified broker and virtual host.
+     *
+     * @param brokerUrl   The URL of the broker to connect to.
+     * @param virtualHost The virtual host to run all tests on. Optional, may be <tt>null</tt>.
+     * @param reportDir   The directory to write out test results to.
+     * @param engine      The distributed test engine type to run the tests with.
+     */
+    public Coordinator(String brokerUrl, String virtualHost, String reportDir, TestEngine engine, boolean terminate)
+    {
+        log.debug("Coordinator(String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost + "): called");
+
+        // Retain the connection parameters.
+        this.brokerUrl = brokerUrl;
+        this.virtualHost = virtualHost;
+        this.reportDir = reportDir;
+        this.engine = engine;
+        this.terminate = terminate;
+    }
+
+    /**
+     * The entry point for the interop test coordinator. This client accepts the following command line arguments:
+     *
+     * <p/><table>
+     * <tr><td> -b         <td> The broker URL.   <td> Mandatory.
+     * <tr><td> -h         <td> The virtual host. <td> Optional.
+     * <tr><td> -o         <td> The directory to output test results to. <td> Optional.
+     * <tr><td> -e         <td> The type of test distribution engine to use. <td> Optional. One of: interop, fanout.
+     * <tr><td> ...        <td> Free arguments. The distributed test cases to run.
+     *                     <td> Mandatory. At least one must be defined.
+     * <tr><td> name=value <td> Trailing argument define name/value pairs. Added to the test contenxt properties.
+     *                     <td> Optional.
+     * </table>
+     *
+     * @param args The command line arguments.
+     */
+    public static void main(String[] args)
+    {
+        console.info("Qpid Distributed Test Coordinator.");
+
+        // Override the default broker url to be localhost:5672.
+        testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672");
+
+        try
+        {
+            // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
+            // and usage then exist if there are errors).
+            // Any options and trailing name=value pairs are also injected into the test context properties object,
+            // to override any defaults that may have been set up.
+            ParsedProperties options =
+                new ParsedProperties(CommandLineParser.processCommandLine(args,
+                        new CommandLineParser(
+                            new String[][]
+                            {
+                                { "b", "The broker URL.", "broker", "false" },
+                                { "h", "The virtual host to use.", "virtual host", "false" },
+                                { "o", "The name of the directory to output test timings to.", "dir", "false" },
+                                {
+                                    "e", "The test execution engine to use. Default is interop.", "engine", "interop",
+                                    "^interop$|^fanout$", "true"
+                                },
+                                { "t", "Terminate test clients on completion of tests.", "flag", "false" }
+                            }), testContextProperties));
+
+            // Extract the command line options.
+            String brokerUrl = options.getProperty("b");
+            String virtualHost = options.getProperty("h");
+            String reportDir = options.getProperty("o");
+            reportDir = (reportDir == null) ? "." : reportDir;
+            String testEngine = options.getProperty("e");
+            TestEngine engine = "fanout".equals(testEngine) ? TestEngine.FANOUT : TestEngine.INTEROP;
+            boolean terminate = options.getPropertyAsBoolean("t");
+
+            // If broker or virtual host settings were specified as command line options, override the defaults in the
+            // test context properties with them.
+
+            // Collection all of the test cases to be run.
+            Collection<Class<? extends DistributedTestCase>> testCaseClasses =
+                new ArrayList<Class<? extends DistributedTestCase>>();
+
+            // Scan for available test cases using a classpath scanner.
+            // ClasspathScanner.getMatches(InteropTestCase.class, "^Test.*", true);
+
+            // Hard code the test classes till the classpath scanner is fixed.
+            // Collections.addAll(testCaseClasses, InteropTestCase1DummyRun.class, InteropTestCase2BasicP2P.class,
+            // InteropTestCase3BasicPubSub.class);
+
+            // Parse all of the free arguments as test cases to run.
+            for (int i = 1; true; i++)
+            {
+                String nextFreeArg = options.getProperty(Integer.toString(i));
+
+                // Terminate the loop once all free arguments have been consumed.
+                if (nextFreeArg == null)
+                {
+                    break;
+                }
+
+                try
+                {
+                    Class nextClass = Class.forName(nextFreeArg);
+
+                    if (DistributedTestCase.class.isAssignableFrom(nextClass))
+                    {
+                        testCaseClasses.add(nextClass);
+                        console.info("Found distributed test case: " + nextFreeArg);
+                    }
+                }
+                catch (ClassNotFoundException e)
+                {
+                    console.info("Unable to instantiate the test case: " + nextFreeArg + ".");
+                }
+            }
+
+            // Check that some test classes were actually found.
+            if (testCaseClasses.isEmpty())
+            {
+                throw new RuntimeException("No test cases implementing InteropTestCase were specified on the command line.");
+            }
+
+            // Extract the names of all the test classes, to pass to the start method.
+            int i = 0;
+            String[] testClassNames = new String[testCaseClasses.size()];
+
+            for (Class testClass : testCaseClasses)
+            {
+                testClassNames[i++] = testClass.getName();
+            }
+
+            // Create a coordinator and begin its test procedure.
+            Coordinator coordinator = new Coordinator(brokerUrl, virtualHost, reportDir, engine, terminate);
+
+            TestResult testResult = coordinator.start(testClassNames);
+
+            // Return different error codes, depending on whether or not there were test failures.
+            if (testResult.failureCount() > 0)
+            {
+                System.exit(FAILURE_EXIT);
+            }
+            else
+            {
+                System.exit(SUCCESS_EXIT);
+            }
+        }
+        catch (Exception e)
+        {
+            log.debug("Top level handler caught execption.", e);
+            console.info(e.getMessage());
+            System.exit(EXCEPTION_EXIT);
+        }
+    }
+
+    /**
+     * Starts all of the test classes to be run by this coordinator.
+     *
+     * @param testClassNames An array of all the coordinating test case implementations.
+     *
+     * @return A JUnit TestResult to run the tests with.
+     *
+     * @throws Exception Any underlying exceptions are allowed to fall through, and fail the test process.
+     */
+    public TestResult start(String[] testClassNames) throws Exception
+    {
+        log.debug("public TestResult start(String[] testClassNames = " + PrettyPrintingUtils.printArray(testClassNames)
+            + ": called");
+
+        // Connect to the broker.
+        connection = TestUtils.createConnection(TestContextProperties.getInstance());
+        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+        Destination controlTopic = session.createTopic("iop.control");
+        Destination responseQueue = session.createQueue("coordinator");
+
+        conversationFactory = new ConversationFactory(connection, responseQueue, LinkedBlockingQueue.class);
+        ConversationFactory.Conversation conversation = conversationFactory.startConversation();
+
+        connection.start();
+
+        // Broadcast the compulsory invitation to find out what clients are available to test.
+        Message invite = session.createMessage();
+        invite.setStringProperty("CONTROL_TYPE", "INVITE");
+        invite.setJMSReplyTo(responseQueue);
+
+        conversation.send(controlTopic, invite);
+
+        // Wait for a short time, to give test clients an opportunity to reply to the invitation.
+        Collection<Message> enlists = conversation.receiveAll(0, 3000);
+
+        enlistedClients = extractEnlists(enlists);
+
+        // Run the test in the suite using JUnit.
+        TestResult result = null;
+
+        for (String testClassName : testClassNames)
+        {
+            // Record the current test class, so that the test results can be output to a file incorporating this name.
+            this.currentTestClassName = testClassName;
+
+            result = super.start(new String[] { testClassName });
+        }
+
+        // At this point in time, all tests have completed. Broadcast the shutdown message, if the termination option
+        // was set on the command line.
+        if (terminate)
+        {
+            Message terminate = session.createMessage();
+            terminate.setStringProperty("CONTROL_TYPE", "TERMINATE");
+
+            conversation.send(controlTopic, terminate);
+        }
+
+        return result;
+    }
+
+    /**
+     * For a collection of enlist messages, this method pulls out of the client details for the enlisting clients.
+     *
+     * @param enlists The enlist messages.
+     *
+     * @return A set of enlisting clients, extracted from the enlist messages.
+     *
+     * @throws JMSException Any underlying JMSException is allowed to fall through.
+     */
+    public static Set<TestClientDetails> extractEnlists(Collection<Message> enlists) throws JMSException
+    {
+        log.debug("public static Set<TestClientDetails> extractEnlists(Collection<Message> enlists = " + enlists
+            + "): called");
+
+        Set<TestClientDetails> enlistedClients = new HashSet<TestClientDetails>();
+
+        // Retain the list of all available clients.
+        for (Message enlist : enlists)
+        {
+            TestClientDetails clientDetails = new TestClientDetails();
+            clientDetails.clientName = enlist.getStringProperty("CLIENT_NAME");
+            clientDetails.privateControlKey = enlist.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY");
+
+            enlistedClients.add(clientDetails);
+        }
+
+        return enlistedClients;
+    }
+
+    /**
+     * Runs a test or suite of tests, using the super class implemenation. This method wraps the test to be run
+     * in any test decorators needed to add in the coordinators ability to invite test clients to participate in
+     * tests.
+     *
+     * @param test The test to run.
+     * @param wait Undocumented. Nothing in the JUnit javadocs to say what this is for.
+     *
+     * @return The results of the test run.
+     */
+    public TestResult doRun(Test test, boolean wait)
+    {
+        log.debug("public TestResult doRun(Test \"" + test + "\", boolean " + wait + "): called");
+
+        // Wrap all tests in the test suite with WrappedSuiteTestDecorators. This is quite ugly and a bit baffling,
+        // but the reason it is done is because the JUnit implementation of TestDecorator has some bugs in it.
+        WrappedSuiteTestDecorator targetTest = null;
+
+        if (test instanceof TestSuite)
+        {
+            log.debug("targetTest is a TestSuite");
+
+            TestSuite suite = (TestSuite) test;
+
+            int numTests = suite.countTestCases();
+            log.debug("There are " + numTests + " in the suite.");
+
+            for (int i = 0; i < numTests; i++)
+            {
+                Test nextTest = suite.testAt(i);
+                log.debug("suite.testAt(" + i + ") = " + nextTest);
+
+                if (nextTest instanceof DistributedTestCase)
+                {
+                    log.debug("nextTest is a DistributedTestCase");
+                }
+            }
+
+            targetTest = new WrappedSuiteTestDecorator(suite);
+            log.debug("Wrapped with a WrappedSuiteTestDecorator.");
+        }
+
+        // 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);
+
+        // 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);
+    }
+
+    /**
+     * Creates a wrapped test decorator, that is capable of inviting enlisted clients to participate in a specified
+     * test. This is the test engine that sets up the roles and sequences a distributed test case.
+     *
+     * @param targetTest          The test decorator to wrap.
+     * @param enlistedClients     The enlisted clients available to run the test.
+     * @param conversationFactory The conversation factory used to build conversation helper over the specified connection.
+     * @param connection          The connection to talk to the enlisted clients over.
+     *
+     * @return An invititing test decorator, that invites all the enlisted clients to participate in tests, in pairs.
+     */
+    protected DistributedTestDecorator newTestDecorator(WrappedSuiteTestDecorator targetTest,
+        Set<TestClientDetails> enlistedClients, ConversationFactory conversationFactory, Connection connection)
+    {
+        switch (engine)
+        {
+        case FANOUT:
+            return new FanOutTestDecorator(targetTest, enlistedClients, conversationFactory, connection);
+        case INTEROP:
+        default:
+            return new InteropTestDecorator(targetTest, enlistedClients, conversationFactory, connection);
+        }
+    }
+
+    /**
+     * Creates the TestResult object to be used for test runs.
+     *
+     * @return An instance of the test result object.
+     */
+    protected TestResult createTestResult()
+    {
+        log.debug("protected TestResult createTestResult(): called");
+
+        TKTestResult result = new TKTestResult(fPrinter.getWriter(), delay, verbose, testCaseName);
+
+        // Check if a directory to output reports to has been specified and attach test listeners if so.
+        if (reportDir != null)
+        {
+            // Create the report directory if it does not already exist.
+            File reportDirFile = new File(reportDir);
+
+            if (!reportDirFile.exists())
+            {
+                reportDirFile.mkdir();
+            }
+
+            // Create the results file (make the name of this configurable as a command line parameter).
+            Writer timingsWriter;
+
+            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);
+            }
+
+            // 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);
+
+            // Register the results listeners shutdown hook to flush its data if the test framework is shutdown
+            // prematurely.
+            // registerShutdownHook(listener);
+
+            // Record the start time of the batch.
+            // result.notifyStartBatch();
+
+            // At this point in time the test class has been instantiated, giving it an opportunity to read its parameters.
+            // Inform any test listers of the test properties.
+            result.notifyTestProperties(TestContextProperties.getAccessedProps());
+        }
+
+        return result;
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestCase.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,81 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+/**
+ * DistributedTestCase provides a base class implementation of the {@link org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer}, taking care of its
+ * more mundane aspects, such as recording the test pariticipants.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept notification of test case participants.
+ *     <td> {@link org.apache.qpid.interop.coordinator.DistributedTestDecorator}
+ * <tr><td> Accept JMS Connection to carry out the coordination over.
+ * </table>
+ */
+public abstract class DistributedTestCase extends FrameworkBaseCase
+{
+    /** Used for debugging. */
+    private final Logger log = Logger.getLogger(DistributedTestCase.class);
+
+    /**
+     * Creates a new test case with the specified name.
+     *
+     * @param name The test case name.
+     */
+    public DistributedTestCase(String name)
+    {
+        super(name);
+    }
+
+    /**
+     * Gets the test sequencer for this distributed test, cast as a {@link DistributedTestSequencer}, provided that it
+     * is one. If the test sequencer is not distributed, this returns null.
+     */
+    public DistributedTestSequencer getDistributedTestSequencer()
+    {
+        try
+        {
+            return (DistributedTestSequencer) testSequencer;
+        }
+        catch (ClassCastException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Should provide a translation from the junit method name of a test to its test case name as known to the test
+     * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+     * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+     * name "TC2_BasicP2P".
+     *
+     * @param methodName The name of the JUnit test method.
+     *
+     * @return The name of the corresponding interop test case.
+     */
+    public abstract String getTestCaseNameForTestMethod(String methodName);
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DistributedTestDecorator.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,165 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator;
+
+import junit.framework.TestResult;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import java.util.*;
+
+/**
+ * DistributedTestDecorator is a base class for writing test decorators that invite test clients to participate in
+ * distributed test cases. It provides a helper method, {@link #signupClients}, that broadcasts an invitation and
+ * returns the set of test clients that are available to particiapte in the test.
+ *
+ * <p/>When used to wrap a {@link org.apache.qpid.test.framework.FrameworkBaseCase} test, it replaces the default
+ * {@link org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer} implementations with a suitable
+ * {@link org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer}. Concrete implementations
+ * can use this to configure the sending and receiving roles on the test.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Broadcast test invitations and collect enlists. <td> {@link ConversationFactory}.
+ * </table>
+ */
+public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(DistributedTestDecorator.class);
+
+    /** Holds the contact information for all test clients that are available and that may take part in the test. */
+    Set<TestClientDetails> allClients;
+
+    /** Holds the conversation helper for the control level conversation for coordinating the test through. */
+    ConversationFactory conversationFactory;
+
+    /** Holds the connection that the control conversation is held over. */
+    Connection connection;
+
+    /** Holds the underlying {@link DistributedTestCase}s that this decorator wraps. */
+    WrappedSuiteTestDecorator testSuite;
+
+    /** Holds the control topic, on which test invitations are broadcast. */
+    protected Destination controlTopic;
+
+    /**
+     * Creates a wrapped suite test decorator from another one.
+     *
+     * @param suite               The test suite.
+     * @param availableClients    The list of all clients that responded to the compulsory invite.
+     * @param controlConversation The conversation helper for the control level, test coordination conversation.
+     * @param controlConnection   The connection that the coordination messages are sent over.
+     */
+    public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
+        ConversationFactory controlConversation, Connection controlConnection)
+    {
+        super(suite);
+
+        log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+            + availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called");
+
+        testSuite = suite;
+        allClients = availableClients;
+        conversationFactory = controlConversation;
+        connection = controlConnection;
+
+        // Set up the test control topic.
+        try
+        {
+            controlTopic = conversationFactory.getSession().createTopic("iop.control");
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("Unable to create the coordinating control topic to broadcast test invites on.", e);
+        }
+    }
+
+    /**
+     * Should run all of the tests in the wrapped test suite.
+     *
+     * @param testResult The the results object to monitor the test results with.
+     */
+    public abstract void run(TestResult testResult);
+
+    /**
+     * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase}
+     * tests.
+     *
+     * @return A distributed test sequencer.
+     */
+    public abstract DistributedTestSequencer getDistributedTestSequencer();
+
+    /**
+     * Broadcasts an invitation to participate in a coordinating test case to find out what clients are available to
+     * run the test case.
+     *
+     * @param coordTest The coordinating test case to broadcast an inviate for.
+     *
+     * @return A set of test clients that accepted the invitation.
+     */
+    protected Set<TestClientDetails> signupClients(DistributedTestCase coordTest)
+    {
+        // Broadcast the invitation to find out what clients are available to test.
+        Set<TestClientDetails> enlists;
+        try
+        {
+            Message invite = conversationFactory.getSession().createMessage();
+
+            ConversationFactory.Conversation conversation = conversationFactory.startConversation();
+
+            invite.setStringProperty("CONTROL_TYPE", "INVITE");
+            invite.setStringProperty("TEST_NAME", coordTest.getTestCaseNameForTestMethod(coordTest.getName()));
+
+            conversation.send(controlTopic, invite);
+
+            // Wait for a short time, to give test clients an opportunity to reply to the invitation.
+            Collection<Message> replies = conversation.receiveAll(allClients.size(), 3000);
+            enlists = Coordinator.extractEnlists(replies);
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("There was a JMSException during the invite/enlist conversation.", e);
+        }
+
+        return enlists;
+    }
+
+    /**
+     * Prints a string summarizing this test decorator, mainly for debugging purposes.
+     *
+     * @return String representation for debugging purposes.
+     */
+    public String toString()
+    {
+        return "DistributedTestDecorator: [ testSuite = " + testSuite + " ]";
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/DropInTest.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,51 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+/**
+ * A DropIn test is a test case that can accept late joining test clients into a running test. This can be usefull,
+ * for interactive experimentation.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Accept late joining test clients.
+ * </table>
+ */
+public interface DropInTest
+{
+    /**
+     * Should accept a late joining client into a running test case. The client will be enlisted with a control message
+     * with the 'CONTROL_TYPE' field set to the value 'LATEJOIN'. It should also provide values for the fields:
+     *
+     * <p/><table>
+     * <tr><td> CLIENT_NAME <td> A unique name for the new client.
+     * <tr><td> CLIENT_PRIVATE_CONTROL_KEY <td> The key for the route on which the client receives its control messages.
+     * </table>
+     *
+     * @param message The late joiners join message.
+     *
+     * @throws JMSException Any JMS Exception are allowed to fall through, indicating that the join failed.
+     */
+    public void lateJoin(Message message) throws JMSException;
+}