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 [2/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...

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/FanOutTestDecorator.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,200 @@
+/*
+ *
+ * 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 org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+import org.apache.qpid.interop.coordinator.sequencers.FanOutTestSequencer;
+import org.apache.qpid.interop.coordinator.sequencers.InteropTestSequencer;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * FanOutTestDecorator is an {@link DistributedTestDecorator} that runs one test client in the sender role, and the remainder
+ * in the receivers role. It also has the capability to listen for new test cases joining the test beyond the initial start
+ * point. This feature can be usefull when experimenting with adding more load, in the form of more test clients, to assess
+ * its impact on a running test.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Execute coordinated test cases. <td> {@link DistributedTestCase}
+ * <tr><td> Accept test clients joining a running test.
+ * </table>
+ */
+public class FanOutTestDecorator extends DistributedTestDecorator implements MessageListener
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(FanOutTestDecorator.class);
+
+    /** Holds the currently running test case. */
+    DistributedTestCase currentTest = null;
+
+    /**
+     * 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 FanOutTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
+        ConversationFactory controlConversation, Connection controlConnection)
+    {
+        super(suite, availableClients, controlConversation, controlConnection);
+
+        log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+            + availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called");
+
+        testSuite = suite;
+        allClients = availableClients;
+        conversationFactory = controlConversation;
+        connection = controlConnection;
+    }
+
+    /**
+     * Broadcasts a test invitation and accepts enlists from participating clients. The wrapped test cases are run
+     * with one test client in the sender role, and the remaining test clients in the receiving role.
+     *
+     * <p/>Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime
+     * exceptions, resulting in the non-completion of the test run.
+     *
+     * @param testResult The the results object to monitor the test results with.
+     *
+     * @todo Better error recovery for failure of the invite/enlist conversation could be added.
+     */
+    public void run(TestResult testResult)
+    {
+        log.debug("public void run(TestResult testResult): called");
+
+        Collection<Test> tests = testSuite.getAllUnderlyingTests();
+
+        // Listen for late joiners on the control topic.
+        try
+        {
+            conversationFactory.getSession().createConsumer(controlTopic).setMessageListener(this);
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("Unable to set up the message listener on the control topic.", e);
+        }
+
+        // Run all of the test cases in the test suite.
+        for (Test test : tests)
+        {
+            DistributedTestCase coordTest = (DistributedTestCase) test;
+
+            // Get all of the clients able to participate in the test.
+            Set<TestClientDetails> enlists = signupClients(coordTest);
+
+            // Check that there were some clients available.
+            if (enlists.size() == 0)
+            {
+                throw new RuntimeException("No clients to test with");
+            }
+
+            // Create a distributed test sequencer for the test.
+            DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+            // Set up the first client in the sender role, and the remainder in the receivers role.
+            Iterator<TestClientDetails> clients = enlists.iterator();
+            sequencer.setSender(clients.next());
+
+            while (clients.hasNext())
+            {
+                // Set the sending and receiving client details on the test case.
+                sequencer.setReceiver(clients.next());
+            }
+
+            // Pass down the connection to hold the coordinating conversation over.
+            sequencer.setConversationFactory(conversationFactory);
+
+            // If the current test case is a drop-in test, set it up as the currently running test for late joiners to
+            // add in to. Otherwise the current test field is set to null, to indicate that late joiners are not allowed.
+            currentTest = (coordTest instanceof DropInTest) ? coordTest : null;
+
+            // Execute the test case.
+            coordTest.setTestSequencer(sequencer);
+            coordTest.run(testResult);
+
+            currentTest = null;
+        }
+    }
+
+    /**
+     * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase}
+     * tests.
+     *
+     * @return A distributed test sequencer.
+     */
+    public DistributedTestSequencer getDistributedTestSequencer()
+    {
+        return new FanOutTestSequencer();
+    }
+
+    /**
+     * Listens to incoming messages on the control topic. If the messages are 'join' messages, signalling a new
+     * test client wishing to join the current test, then the new client will be added to the current test in the
+     * receivers role.
+     *
+     * @param message The incoming control message.
+     */
+    public void onMessage(Message message)
+    {
+        try
+        {
+            // Check if the message is from a test client attempting to join a running test, and join it to the current
+            // test case if so.
+            if (message.getStringProperty("CONTROL_TYPE").equals("JOIN") && (currentTest != null))
+            {
+                ((DropInTest) currentTest).lateJoin(message);
+            }
+        }
+        // There is not a lot can be done with this error, so it is deliberately ignored.
+        catch (JMSException e)
+        {
+            log.debug("Unable to process message:" + message);
+        }
+    }
+
+    /**
+     * Prints a string summarizing this test decorator, mainly for debugging purposes.
+     *
+     * @return String representation for debugging purposes.
+     */
+    public String toString()
+    {
+        return "FanOutTestDecorator: [ testSuite = " + testSuite + " ]";
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/InteropTestDecorator.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,206 @@
+/*
+ *
+ * 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 org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+import org.apache.qpid.interop.coordinator.sequencers.InteropTestSequencer;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+import javax.jms.Connection;
+
+import java.util.*;
+
+/**
+ * DistributedTestDecorator is a test decorator, written to implement the interop test specification. Given a list
+ * of enlisted test clients, that are available to run interop tests, this decorator invites them to participate
+ * in each test in the wrapped test suite. Amongst all the clients that respond to the invite, all pairs are formed,
+ * and each pairing (in both directions, but excluding the reflexive pairings) is split into a sender and receivers
+ * role and a test case run between them. Any enlisted combinations that do not accept a test invite are automatically
+ * failed.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Broadcast test invitations and collect enlists. <td> {@link org.apache.qpid.util.ConversationFactory}.
+ * <tr><td> Output test failures for clients unwilling to run the test case. <td> {@link Coordinator}
+ * <tr><td> Execute distributed test cases. <td> {@link DistributedTestCase}
+ * <tr><td> Fail non participating pairings. <td> {@link OptOutTestCase}
+ * </table>
+ */
+public class InteropTestDecorator extends DistributedTestDecorator
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(InteropTestDecorator.class);
+
+    /**
+     * 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 InteropTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
+        ConversationFactory controlConversation, Connection controlConnection)
+    {
+        super(suite, availableClients, controlConversation, controlConnection);
+    }
+
+    /**
+     * 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}.
+     *
+     * <p/>Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime exceptions,
+     * resulting in the non-completion of the test run.
+     *
+     * @todo Better error recovery for failure of the invite/enlist conversation could be added.
+     *
+     * @param testResult The the results object to monitor the test results with.
+     */
+    public void run(TestResult testResult)
+    {
+        log.debug("public void run(TestResult testResult): called");
+
+        Collection<Test> tests = testSuite.getAllUnderlyingTests();
+
+        for (Test test : tests)
+        {
+            DistributedTestCase coordTest = (DistributedTestCase) test;
+
+            // Broadcast the invitation to find out what clients are available to test.
+            Set<TestClientDetails> enlists = signupClients(coordTest);
+
+            // Compare the list of willing clients to the list of all available.
+            Set<TestClientDetails> optOuts = new HashSet<TestClientDetails>(allClients);
+            optOuts.removeAll(enlists);
+
+            // Output test failures for clients that will not particpate in the test.
+            Set<List<TestClientDetails>> failPairs = allPairs(optOuts, allClients);
+
+            for (List<TestClientDetails> failPair : failPairs)
+            {
+                // Create a distributed test sequencer for the test.
+                DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+                // Create an automatic failure test for the opted out test pair.
+                DistributedTestCase failTest = new OptOutTestCase("testOptOut");
+                sequencer.setSender(failPair.get(0));
+                sequencer.setReceiver(failPair.get(1));
+                failTest.setTestSequencer(sequencer);
+
+                failTest.run(testResult);
+            }
+
+            // Loop over all combinations of clients, willing to run the test.
+            Set<List<TestClientDetails>> enlistedPairs = allPairs(enlists, enlists);
+
+            for (List<TestClientDetails> enlistedPair : enlistedPairs)
+            {
+                // Create a distributed test sequencer for the test.
+                DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+                // Set the sending and receiving client details on the test sequencer.
+                sequencer.setSender(enlistedPair.get(0));
+                sequencer.setReceiver(enlistedPair.get(1));
+
+                // Pass down the connection to hold the coordination conversation over.
+                sequencer.setConversationFactory(conversationFactory);
+
+                // Execute the test case.
+                coordTest.setTestSequencer(sequencer);
+                coordTest.run(testResult);
+            }
+        }
+    }
+
+    /**
+     * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase}
+     * tests.
+     *
+     * @return A distributed test sequencer.
+     */
+    public DistributedTestSequencer getDistributedTestSequencer()
+    {
+        return new InteropTestSequencer();
+    }
+
+    /**
+     * Produces all pairs of combinations of elements from two sets. The ordering of the elements in the pair is
+     * important, that is the pair <l, r> is distinct from <r, l>; both pairs are generated. For any element, i, in
+     * both the left and right sets, the reflexive pair <i, i> is not generated.
+     *
+     * @param left  The left set.
+     * @param right The right set.
+     * @param <E>   The type of the content of the pairs.
+     *
+     * @return All pairs formed from the permutations of all elements of the left and right sets.
+     */
+    private <E> Set<List<E>> allPairs(Set<E> left, Set<E> right)
+    {
+        log.debug("private <E> Set<List<E>> allPairs(Set<E> left = " + left + ", Set<E> right = " + right + "): called");
+
+        Set<List<E>> results = new HashSet<List<E>>();
+
+        // Form all pairs from left to right.
+        // Form all pairs from right to left.
+        for (E le : left)
+        {
+            for (E re : right)
+            {
+                if (!le.equals(re))
+                {
+                    results.add(new Pair<E>(le, re));
+                    results.add(new Pair<E>(re, le));
+                }
+            }
+        }
+
+        log.debug("results = " + results);
+
+        return results;
+    }
+
+    /**
+     * A simple implementation of a pair, using a list.
+     */
+    private class Pair<T> extends ArrayList<T>
+    {
+        /**
+         * Creates a new pair of elements.
+         *
+         * @param first  The first element.
+         * @param second The second element.
+         */
+        public Pair(T first, T second)
+        {
+            super();
+            super.add(first);
+            super.add(second);
+        }
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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.Assert;
+
+import org.apache.qpid.interop.coordinator.sequencers.DistributedTestSequencer;
+
+/**
+ * An OptOutTestCase is a test case that automatically fails. It is used when a list of test clients has been generated
+ * from a compulsory invite, but only some of those clients have responded to a specific test case invite. The clients
+ * that did not respond, may automatically be given a fail for some tests.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Fail the test with a suitable reason.
+ * </table>
+ */
+public class OptOutTestCase extends DistributedTestCase
+{
+    /**
+     * Creates a new coordinating test case with the specified name.
+     *
+     * @param name The test case name.
+     */
+    public OptOutTestCase(String name)
+    {
+        super(name);
+    }
+
+    /** Generates an appropriate test failure assertion. */
+    public void testOptOut()
+    {
+        DistributedTestSequencer sequencer = getDistributedTestSequencer();
+
+        Assert.fail("One of " + sequencer.getSender() + " and " + getDistributedTestSequencer().getReceivers()
+            + " opted out of the test.");
+    }
+
+    /**
+     * Should provide a translation from the junit method name of a test to its test case name as defined in the
+     * interop testing specification. 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 "OptOutTest";
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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;
+
+/**
+ * TestClientDetails is used to encapsulate information about an interop test client. It pairs together the unique
+ * name of the client, and the route on which it listens to its control messages.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Record test clients control addresses together with their names.
+ * </table>
+ */
+public class TestClientDetails
+{
+    /** The test clients name. */
+    public String clientName;
+
+    /* The test clients unique sequence number. Not currently used. */
+
+    /** The routing key of the test clients control topic. */
+    public String privateControlKey;
+
+    /**
+     * Two TestClientDetails are considered to be equal, iff they have the same client name.
+     *
+     * @param o The object to compare to.
+     *
+     * @return <tt>If the object to compare to is a TestClientDetails equal to this one, <tt>false</tt> otherwise.
+     */
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+
+        if (!(o instanceof TestClientDetails))
+        {
+            return false;
+        }
+
+        final TestClientDetails testClientDetails = (TestClientDetails) o;
+
+        return !((clientName != null) ? (!clientName.equals(testClientDetails.clientName))
+                                      : (testClientDetails.clientName != null));
+    }
+
+    /**
+     * Computes a hash code compatible with the equals method; based on the client name alone.
+     *
+     * @return A hash code for this.
+     */
+    public int hashCode()
+    {
+        return ((clientName != null) ? clientName.hashCode() : 0);
+    }
+
+    /**
+     * Outputs the client name and address details. Mostly used for debugging purposes.
+     *
+     * @return The client name and address.
+     */
+    public String toString()
+    {
+        return "TestClientDetails: [ clientName = " + clientName + ", privateControlKey = " + privateControlKey + " ]";
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/XMLTestListener.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,382 @@
+/*
+ *
+ * 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.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+
+import uk.co.thebadgerset.junit.extensions.listeners.TKTestListener;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.*;
+
+/**
+ * Listens for test results for a named test and outputs these in the standard JUnit XML format to the specified
+ * writer.
+ *
+ * <p/>The API for this listener accepts notifications about different aspects of a tests results through different
+ * methods, so some assumption needs to be made as to which test result a notification refers to. For example
+ * {@link #startTest} will be called, then possibly {@link #timing} will be called, even though the test instance is
+ * passed in both cases, it is not enough to distinguish a particular run of the test, as the test case instance may
+ * be being shared between multiple threads, or being run a repeated number of times, and can therfore be re-used
+ * between calls. The listeners make the assumption that, for every test, a unique thread will call {@link #startTest}
+ * and {@link #endTest} to delimit each test. All calls to set test parameters, timings, state and so on, will occur
+ * between the start and end and will be given with the same thread id as the start and end, so the thread id provides
+ * a unqiue value to identify a particular test run against.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Listen to test lifecycle notifications.
+ * <tr><td> Listen to test errors and failures.
+ * <tr><td> Listen to test timings.
+ * <tr><td> Listen to test memory usages.
+ * <tr><td> Listen to parameterized test parameters.
+ * <tr><th> Responsibilities
+ * </table>
+ *
+ * @todo Merge this class with CSV test listener, making the collection of results common to both, and only factoring
+ *       out the results printing code into sub-classes. Provide a simple XML results formatter with the same format as
+ *       the ant XML formatter, and a more structured one for outputing results with timings and summaries from
+ *       performance tests.
+ */
+public class XMLTestListener implements TKTestListener
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(XMLTestListener.class);
+
+    /** The results file writer. */
+    protected Writer writer;
+
+    /** Holds the results for individual tests. */
+    // protected Map<Result, Result> results = new LinkedHashMap<Result, Result>();
+    // protected List<Result> results = new ArrayList<Result>();
+
+    /**
+     * Map for holding results on a per thread basis as they come in. A ThreadLocal is not used as sometimes an
+     * explicit thread id must be used, where notifications come from different threads than the ones that called
+     * the test method.
+     */
+    Map<Long, Result> threadLocalResults = Collections.synchronizedMap(new LinkedHashMap<Long, Result>());
+
+    /**
+     * Holds results for tests that have ended. Transferring these results here from the per-thread results map, means
+     * that the thread id is freed for the thread to generate more results.
+     */
+    List<Result> results = new ArrayList<Result>();
+
+    /** Holds the overall error count. */
+    protected int errors = 0;
+
+    /** Holds the overall failure count. */
+    protected int failures = 0;
+
+    /** Holds the overall tests run count. */
+    protected int runs = 0;
+
+    /** Holds the name of the class that tests are being run for. */
+    String testClassName;
+
+    /**
+     * Creates a new XML results output listener that writes to the specified location.
+     *
+     * @param writer        The location to write results to.
+     * @param testClassName The name of the test class to include in the test results.
+     */
+    public XMLTestListener(Writer writer, String testClassName)
+    {
+        log.debug("public XMLTestListener(Writer writer, String testClassName = " + testClassName + "): called");
+
+        this.writer = writer;
+        this.testClassName = testClassName;
+    }
+
+    /**
+     * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed.
+     *
+     * @param test     The test to resest any results for.
+     * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+     */
+    public void reset(Test test, Long threadId)
+    {
+        log.debug("public void reset(Test test = " + test + ", Long threadId = " + threadId + "): called");
+
+        XMLTestListener.Result r =
+            (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+        r.error = null;
+        r.failure = null;
+
+    }
+
+    /**
+     * Notification that a test started.
+     *
+     * @param test The test that started.
+     */
+    public void startTest(Test test)
+    {
+        log.debug("public void startTest(Test test = " + test + "): called");
+
+        Result newResult = new Result(test.getClass().getName(), ((TestCase) test).getName());
+
+        // Initialize the thread local test results.
+        threadLocalResults.put(Thread.currentThread().getId(), newResult);
+        runs++;
+    }
+
+    /**
+     * Should be called every time a test completes with the run time of that test.
+     *
+     * @param test     The name of the test.
+     * @param nanos    The run time of the test in nanoseconds.
+     * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+     */
+    public void timing(Test test, long nanos, Long threadId)
+    { }
+
+    /**
+     * Should be called every time a test completed with the amount of memory used before and after the test was run.
+     *
+     * @param test     The test which memory was measured for.
+     * @param memStart The total JVM memory used before the test was run.
+     * @param memEnd   The total JVM memory used after the test was run.
+     * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+     */
+    public void memoryUsed(Test test, long memStart, long memEnd, Long threadId)
+    { }
+
+    /**
+     * Should be called every time a parameterized test completed with the int value of its test parameter.
+     *
+     * @param test      The test which memory was measured for.
+     * @param parameter The int parameter value.
+     * @param threadId  Optional thread id if not calling from thread that started the test method. May be null.
+     */
+    public void parameterValue(Test test, int parameter, Long threadId)
+    { }
+
+    /**
+     * Should be called every time a test completes with the current number of test threads running.
+     *
+     * @param test     The test for which the measurement is being generated.
+     * @param threads  The number of tests being run concurrently.
+     * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+     */
+    public void concurrencyLevel(Test test, int threads, Long threadId)
+    { }
+
+    /**
+     * Notifies listeners of the tests read/set properties.
+     *
+     * @param properties The tests read/set properties.
+     */
+    public void properties(Properties properties)
+    { }
+
+    /**
+     * Notification that a test ended.
+     *
+     * @param test The test that ended.
+     */
+    public void endTest(Test test)
+    {
+        log.debug("public void endTest(Test test = " + test + "): called");
+
+        // Move complete test results into the completed tests list.
+        Result r = threadLocalResults.get(Thread.currentThread().getId());
+        results.add(r);
+
+        // Clear all the test results for the thread.
+        threadLocalResults.remove(Thread.currentThread().getId());
+    }
+
+    /**
+     * Called when a test completes. Success, failure and errors. This method should be used when registering an
+     * end test from a different thread than the one that started the test.
+     *
+     * @param test     The test which completed.
+     * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+     */
+    public void endTest(Test test, Long threadId)
+    {
+        log.debug("public void endTest(Test test = " + test + ", Long threadId = " + threadId + "): called");
+
+        // Move complete test results into the completed tests list.
+        Result r =
+            (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+        results.add(r);
+
+        // Clear all the test results for the thread.
+        threadLocalResults.remove(Thread.currentThread().getId());
+    }
+
+    /**
+     * An error occurred.
+     *
+     * @param test The test in which the error occurred.
+     * @param t    The throwable that resulted from the error.
+     */
+    public void addError(Test test, Throwable t)
+    {
+        log.debug("public void addError(Test test = " + test + ", Throwable t = " + t + "): called");
+
+        Result r = threadLocalResults.get(Thread.currentThread().getId());
+        r.error = t;
+        errors++;
+    }
+
+    /**
+     * A failure occurred.
+     *
+     * @param test The test in which the failure occurred.
+     * @param t    The JUnit assertions that led to the failure.
+     */
+    public void addFailure(Test test, AssertionFailedError t)
+    {
+        log.debug("public void addFailure(Test test = " + test + ", AssertionFailedError t = " + t + "): called");
+
+        Result r = threadLocalResults.get(Thread.currentThread().getId());
+        r.failure = t;
+        failures++;
+    }
+
+    /**
+     * Called when a test completes to mark it as a test fail. This method should be used when registering a
+     * failure from a different thread than the one that started the test.
+     *
+     * @param test     The test which failed.
+     * @param e        The assertion that failed the test.
+     * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+     */
+    public void addFailure(Test test, AssertionFailedError e, Long threadId)
+    {
+        log.debug("public void addFailure(Test test, AssertionFailedError e, Long threadId): called");
+
+        Result r =
+            (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+        r.failure = e;
+        failures++;
+    }
+
+    /**
+     * Notifies listeners of the start of a complete run of tests.
+     */
+    public void startBatch()
+    {
+        log.debug("public void startBatch(): called");
+
+        // Reset all results counts.
+        threadLocalResults = Collections.synchronizedMap(new HashMap<Long, Result>());
+        errors = 0;
+        failures = 0;
+        runs = 0;
+
+        // Write out the file header.
+        try
+        {
+            writer.write("<?xml version=\"1.0\" ?>\n");
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException("Unable to write the test results.", e);
+        }
+    }
+
+    /**
+     * Notifies listeners of the end of a complete run of tests.
+     *
+     * @param parameters The optional test parameters to log out with the batch results.
+     */
+    public void endBatch(Properties parameters)
+    {
+        log.debug("public void endBatch(Properties parameters = " + parameters + "): called");
+
+        // Write out the results.
+        try
+        {
+            // writer.write("<?xml version=\"1.0\" ?>\n");
+            writer.write("<testsuite errors=\"" + errors + "\" failures=\"" + failures + "\" tests=\"" + runs + "\" name=\""
+                + testClassName + "\">\n");
+
+            for (Result result : results)
+            {
+                writer.write("  <testcase classname=\"" + result.testClass + "\" name=\"" + result.testName + "\">\n");
+
+                if (result.error != null)
+                {
+                    writer.write("    <error type=\"" + result.error.getClass() + "\">");
+                    result.error.printStackTrace(new PrintWriter(writer));
+                    writer.write("    </error>");
+                }
+                else if (result.failure != null)
+                {
+                    writer.write("    <failure type=\"" + result.failure.getClass() + "\">");
+                    result.failure.printStackTrace(new PrintWriter(writer));
+                    writer.write("    </failure>");
+                }
+
+                writer.write("  </testcase>\n");
+            }
+
+            writer.write("</testsuite>\n");
+            writer.flush();
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException("Unable to write the test results.", e);
+        }
+    }
+
+    /**
+     * Used to capture the results of a particular test run.
+     */
+    protected static class Result
+    {
+        /** Holds the name of the test class. */
+        public String testClass;
+
+        /** Holds the name of the test method. */
+        public String testName;
+
+        /** Holds the exception that caused error in this test. */
+        public Throwable error;
+
+        /** Holds the assertion exception that caused failure in this test. */
+        public AssertionFailedError failure;
+
+        /**
+         * Creates a placeholder for the results of a test.
+         *
+         * @param testClass The test class.
+         * @param testName  The name of the test that was run.
+         */
+        public Result(String testClass, String testName)
+        {
+            this.testClass = testClass;
+            this.testName = testName;
+        }
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/distributedcircuit/DistributedCircuitImpl.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,116 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator.distributedcircuit;
+
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.Publisher;
+import org.apache.qpid.test.framework.Receiver;
+
+import java.util.List;
+
+/**
+ * DistributedCircuitImpl is a distributed implementation of the test {@link Circuit}. Many publishers and receivers
+ * accross multiple machines may be combined to form a single test circuit. The test circuit extracts reports from
+ * all of its publishers and receivers, and applies its assertions to these reports.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ * <tr><td> Start the circuit running.
+ * <tr><td> Close the circuit down.
+ * <tr><td> Take a reading of the circuits state.
+ * <tr><td> Apply assertions against the circuits state.
+ * <tr><td> Send test messages over the circuit.
+ * <tr><td> Perform the default test procedue on the circuit.
+ * </table>
+ */
+public class DistributedCircuitImpl implements Circuit
+{
+    /**
+     * Gets the interface on the publishing end of the circuit.
+     *
+     * @return The publishing end of the circuit.
+     */
+    public Publisher getPublisher()
+    {
+        throw new RuntimeException("Not Implemented.");
+    }
+
+    /**
+     * Gets the interface on the receiving end of the circuit.
+     *
+     * @return The receiving end of the circuit.
+     */
+    public Receiver getReceiver()
+    {
+        throw new RuntimeException("Not Implemented.");
+    }
+
+    /**
+     * Connects and starts the circuit. After this method is called the circuit is ready to send messages.
+     */
+    public void start()
+    {
+        throw new RuntimeException("Not Implemented.");
+    }
+
+    /**
+     * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+     * into a report, against which assertions may be checked.
+     */
+    public void check()
+    {
+        throw new RuntimeException("Not Implemented.");
+    }
+
+    /**
+     * Closes the circuit. All associated resources are closed.
+     */
+    public void close()
+    {
+        throw new RuntimeException("Not Implemented.");
+    }
+
+    /**
+     * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing
+     * this, to ensure that the circuit has gathered its state into a report to assert against.
+     *
+     * @param assertions The list of assertions to apply.
+     * @return Any assertions that failed.
+     */
+    public List<Assertion> applyAssertions(List<Assertion> assertions)
+    {
+        throw new RuntimeException("Not Implemented.");
+    }
+
+    /**
+     * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold.
+     *
+     * @param numMessages The number of messages to send using the default test procedure.
+     * @param assertions  The list of assertions to apply.
+     * @return Any assertions that failed.
+     */
+    public List<Assertion> test(int numMessages, List<Assertion> assertions)
+    {
+        throw new RuntimeException("Not Implemented.");
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/BaseDistributedTestSequencer.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,129 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator.sequencers;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.DistributedTestCase;
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.util.ConversationFactory;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public abstract class BaseDistributedTestSequencer implements DistributedTestSequencer
+{
+    /** Used for debugging. */
+    private final Logger log = Logger.getLogger(DistributedTestCase.class);
+
+    /** Holds the contact details for the sending test client. */
+    protected TestClientDetails sender;
+
+    /** Holds the contact details for the receving test client. */
+    protected List<TestClientDetails> receivers = new LinkedList<TestClientDetails>();
+
+    /** Holds the conversation factory over which to coordinate the test. */
+    protected ConversationFactory conversationFactory;
+
+    /**
+     * Creates a test circuit for the test, configered by the test parameters specified.
+     *
+     * @param testProperties The test parameters.
+     * @return A test circuit.
+     */
+    public Circuit createCircuit(Properties testProperties)
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+      * Sets the sender test client to coordinate the test with.
+      *
+      * @param sender The contact details of the sending client in the test.
+      */
+    public void setSender(TestClientDetails sender)
+    {
+        log.debug("public void setSender(TestClientDetails sender = " + sender + "): called");
+
+        this.sender = sender;
+    }
+
+    /**
+     * Sets the receiving test client to coordinate the test with.
+     *
+     * @param receiver The contact details of the sending client in the test.
+     */
+    public void setReceiver(TestClientDetails receiver)
+    {
+        log.debug("public void setReceiver(TestClientDetails receivers = " + receiver + "): called");
+
+        this.receivers.add(receiver);
+    }
+
+    /**
+     * Supplies the sending test client.
+     *
+     * @return The sending test client.
+     */
+    public TestClientDetails getSender()
+    {
+        return sender;
+    }
+
+    /**
+     * Supplies the receiving test client.
+     *
+     * @return The receiving test client.
+     */
+    public List<TestClientDetails> getReceivers()
+    {
+        return receivers;
+    }
+
+    /**
+     * Accepts the conversation factory over which to hold the test coordinating conversation.
+     *
+     * @param conversationFactory The conversation factory to coordinate the test over.
+     */
+    public void setConversationFactory(ConversationFactory conversationFactory)
+    {
+        this.conversationFactory = conversationFactory;
+    }
+
+    /**
+     * Provides the conversation factory for providing the distributed test sequencing conversations over the test
+     * connection.
+     *
+     * @return The conversation factory to create test sequencing conversations with.
+     */
+    public ConversationFactory getConversationFactory()
+    {
+        return conversationFactory;
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/DistributedTestSequencer.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,75 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator.sequencers;
+
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.util.ConversationFactory;
+
+import java.util.List;
+
+/**
+ * A DistributedTestSequencer is a test sequencer that coordinates activity amongst many
+ * {@link org.apache.qpid.interop.testclient.TestClient}s.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept notification of test case participants.
+ * <tr><td> Accept JMS Connection to carry out the coordination over.
+ * <tr><td> Coordinate a test sequence amongst participants. <td> {@link ConversationFactory}
+ * </table>
+ */
+public interface DistributedTestSequencer extends TestCaseSequencer
+{
+    /**
+     * Sets the sender test client to coordinate the test with.
+     *
+     * @param sender The contact details of the sending client in the test.
+     */
+    public void setSender(TestClientDetails sender);
+
+    /**
+     * Sets the receiving test client to coordinate the test with.
+     *
+     * @param receiver The contact details of the sending client in the test.
+     */
+    public void setReceiver(TestClientDetails receiver);
+
+    /**
+     * Supplies the sending test client.
+     *
+     * @return The sending test client.
+     */
+    public TestClientDetails getSender();
+
+    /**
+     * Supplies the receiving test client.
+     *
+     * @return The receiving test client.
+     */
+    public List<TestClientDetails> getReceivers();
+
+    /**
+     * Accepts the conversation factory over which to hold the test coordinating conversation.
+     *
+     * @param conversationFactory The conversation factory to coordinate the test over.
+     */
+    public void setConversationFactory(ConversationFactory conversationFactory);
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/FanOutTestSequencer.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,171 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator.sequencers;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class FanOutTestSequencer extends BaseDistributedTestSequencer
+{
+    /** Used for debugging. */
+    Logger log = Logger.getLogger(FanOutTestSequencer.class);
+
+    /**
+     * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+     * begining the test, gathering the test reports from the participants, and checking for assertion failures against
+     * the test reports.
+     *
+     * @param testCircuit    The test circuit.
+     * @param assertions     The list of assertions to apply to the test circuit.
+     * @param testProperties The test case definition.
+     */
+    public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
+    {
+        log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
+
+        TestClientDetails sender = getSender();
+        List<TestClientDetails> receivers = getReceivers();
+        ConversationFactory conversationFactory = getConversationFactory();
+
+        try
+        {
+            // Create a conversation on the sender clients private control rouete.
+            Session session = conversationFactory.getSession();
+            Destination senderControlTopic = session.createTopic(sender.privateControlKey);
+            ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
+
+            // Assign the sender role to the sending test client.
+            Message assignSender = conversationFactory.getSession().createMessage();
+            TestUtils.setPropertiesOnMessage(assignSender, testProperties);
+            assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+            assignSender.setStringProperty("ROLE", "SENDER");
+            assignSender.setStringProperty("CLIENT_NAME", "Sustained_SENDER");
+
+            senderConversation.send(senderControlTopic, assignSender);
+
+            // Wait for the sender to confirm its role.
+            senderConversation.receive();
+
+            // Assign the receivers roles.
+            for (TestClientDetails receiver : receivers)
+            {
+                assignReceiverRole(receiver, testProperties, true);
+            }
+
+            // Start the test on the sender.
+            Message start = session.createMessage();
+            start.setStringProperty("CONTROL_TYPE", "START");
+
+            senderConversation.send(senderControlTopic, start);
+
+            // Wait for the test sender to return its report.
+            Message senderReport = senderConversation.receive();
+            TestUtils.pause(500);
+
+            // Ask the receivers for their reports.
+            Message statusRequest = session.createMessage();
+            statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
+
+            // Gather the reports from all of the receiving clients.
+
+            // Return all of the test reports, the senders report first.
+            // return new Message[] { senderReport };
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("Unhandled JMSException.");
+        }
+    }
+
+    /**
+     * Creates a test circuit for the test, configered by the test parameters specified.
+     *
+     * @param testProperties The test parameters.
+     * @return A test circuit.
+     */
+    public Circuit createCircuit(ParsedProperties testProperties)
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Assigns the receivers role to the specified test client that is to act as a receivers during the test. This method
+     * does not always wait for the receiving clients to confirm their role assignments. This is because this method
+     * may be called from an 'onMessage' method, when a client is joining the test at a later point in time, and it
+     * is not possible to do a synchronous receive during an 'onMessage' method. There is a flag to indicate whether
+     * or not to wait for role confirmations.
+     *
+     * @param receiver       The test client to assign the receivers role to.
+     * @param testProperties The test parameters.
+     * @param confirm        Indicates whether role confirmation should be waited for.
+     *
+     * @throws JMSException Any JMSExceptions occurring during the conversation are allowed to fall through.
+     */
+    protected void assignReceiverRole(TestClientDetails receiver, Properties testProperties, boolean confirm)
+        throws JMSException
+    {
+        log.info("assignReceiverRole(TestClientDetails receivers = " + receiver + ", Map<String, Object> testProperties = "
+            + testProperties + "): called");
+
+        ConversationFactory conversationFactory = getConversationFactory();
+
+        // Create a conversation with the receiving test client.
+        Session session = conversationFactory.getSession();
+        Destination receiverControlTopic = session.createTopic(receiver.privateControlKey);
+        ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
+
+        // Assign the receivers role to the receiving client.
+        Message assignReceiver = session.createMessage();
+        TestUtils.setPropertiesOnMessage(assignReceiver, testProperties);
+        assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+        assignReceiver.setStringProperty("ROLE", "RECEIVER");
+        assignReceiver.setStringProperty("CLIENT_NAME", receiver.clientName);
+
+        receiverConversation.send(receiverControlTopic, assignReceiver);
+
+        // Wait for the role confirmation to come back.
+        if (confirm)
+        {
+            receiverConversation.receive();
+        }
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/InteropTestSequencer.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,137 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator.sequencers;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.interop.coordinator.TestClientDetails;
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class InteropTestSequencer extends BaseDistributedTestSequencer
+{
+    /** Used for debugging. */
+    Logger log = Logger.getLogger(InteropTestSequencer.class);
+
+    /**
+     * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+     * begining the test, gathering the test reports from the participants, and checking for assertion failures against
+     * the test reports.
+     *
+     * @param testCircuit    The test circuit.
+     * @param assertions     The list of assertions to apply to the test circuit.
+     * @param testProperties The test case definition.
+     */
+    public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
+    {
+        log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
+
+        TestClientDetails sender = getSender();
+        List<TestClientDetails> receivers = getReceivers();
+        ConversationFactory conversationFactory = getConversationFactory();
+
+        try
+        {
+            Session session = conversationFactory.getSession();
+            Destination senderControlTopic = session.createTopic(sender.privateControlKey);
+            Destination receiverControlTopic = session.createTopic(receivers.get(0).privateControlKey);
+
+            ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
+            ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
+
+            // Assign the sender role to the sending test client.
+            Message assignSender = conversationFactory.getSession().createMessage();
+            TestUtils.setPropertiesOnMessage(assignSender, testProperties);
+            assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+            assignSender.setStringProperty("ROLE", "SENDER");
+
+            senderConversation.send(senderControlTopic, assignSender);
+
+            // Assign the receivers role the receiving client.
+            Message assignReceiver = session.createMessage();
+            TestUtils.setPropertiesOnMessage(assignReceiver, testProperties);
+            assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+            assignReceiver.setStringProperty("ROLE", "RECEIVER");
+
+            receiverConversation.send(receiverControlTopic, assignReceiver);
+
+            // Wait for the senders and receivers to confirm their roles.
+            senderConversation.receive();
+            receiverConversation.receive();
+
+            // Start the test.
+            Message start = session.createMessage();
+            start.setStringProperty("CONTROL_TYPE", "START");
+
+            senderConversation.send(senderControlTopic, start);
+
+            // Wait for the test sender to return its report.
+            Message senderReport = senderConversation.receive();
+            TestUtils.pause(500);
+
+            // Ask the receivers for its report.
+            Message statusRequest = session.createMessage();
+            statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
+
+            receiverConversation.send(receiverControlTopic, statusRequest);
+
+            // Wait for the receivers to send its report.
+            Message receiverReport = receiverConversation.receive();
+
+            // return new Message[] { senderReport, receiverReport };
+
+            // Apply assertions.
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("JMSException not handled.");
+        }
+    }
+
+    /**
+     * Creates a test circuit for the test, configered by the test parameters specified.
+     *
+     * @param testProperties The test parameters.
+     * @return A test circuit.
+     */
+    public Circuit createCircuit(ParsedProperties testProperties)
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java?view=auto&rev=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/interop/coordinator/sequencers/TestCaseSequencer.java Wed Jul 25 05:17:59 2007
@@ -0,0 +1,66 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.coordinator.sequencers;
+
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * A TestCaseSequence is responsibile for creating test circuits appropriate to the context that a test case is
+ * running in, and providing an implementation of a standard test procedure over a test circuit.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * </table>
+ */
+public interface TestCaseSequencer
+{
+    /**
+     * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+     * begining the test, gathering the test reports from the participants, and checking for assertion failures against
+     * the test reports.
+     *
+     * @param testCircuit    The test circuit.
+     * @param assertions     The list of assertions to apply to the test circuit.
+     * @param testProperties The test case definition.
+     */
+    public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties);
+
+    /**
+     * Creates a test circuit for the test, configered by the test parameters specified.
+     *
+     * @param testProperties The test parameters.
+     *
+     * @return A test circuit.
+     */
+    public Circuit createCircuit(ParsedProperties testProperties);
+}

Modified: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java?view=diff&rev=559419&r1=559418&r2=559419
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java (original)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/server/exchange/ImmediateMessageTest.java Wed Jul 25 05:17:59 2007
@@ -20,8 +20,8 @@
  */
 package org.apache.qpid.server.exchange;
 
+import org.apache.qpid.interop.coordinator.sequencers.TestCaseSequencer;
 import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.CircuitImpl;
 import org.apache.qpid.test.framework.FrameworkBaseCase;
 import org.apache.qpid.test.framework.MessagingTestConfigProperties;
 import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
@@ -67,6 +67,16 @@
     /** Used to read the tests configurable properties through. */
     ParsedProperties testProps;
 
+    /**
+     * Creates a new test case with the specified name.
+     *
+     * @param name The test case name.
+     */
+    public ImmediateMessageTest(String name)
+    {
+        super(name);
+    }
+
     /** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
     public void test_QPID_517_ImmediateOkNoTxP2P()
     {
@@ -74,10 +84,10 @@
         testProps.setProperty(TRANSACTED_PROPNAME, false);
         testProps.setProperty(PUBSUB_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
-        // Send one message with no errors.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+        // Run the default test sequence over the test circuit checking for no errors.
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
     }
 
     /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
@@ -87,10 +97,10 @@
         testProps.setProperty(TRANSACTED_PROPNAME, true);
         testProps.setProperty(PUBSUB_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
         // Send one message with no errors.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
@@ -100,13 +110,14 @@
         testProps.setProperty(TRANSACTED_PROPNAME, false);
         testProps.setProperty(PUBSUB_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
 
         // Disconnect the consumer.
         testCircuit.getReceiver().getConsumer().close();
 
         // Send one message and get a linked no consumers exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
@@ -116,13 +127,14 @@
         testProps.setProperty(TRANSACTED_PROPNAME, true);
         testProps.setProperty(PUBSUB_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
 
         // Disconnect the consumer.
         testCircuit.getReceiver().getConsumer().close();
 
         // Send one message and get a linked no consumers exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
@@ -132,14 +144,14 @@
         testProps.setProperty(TRANSACTED_PROPNAME, false);
         testProps.setProperty(PUBSUB_PROPNAME, false);
 
-        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
         // collect its messages).
         testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
         // Send one message and get a linked no route exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
@@ -149,14 +161,14 @@
         testProps.setProperty(TRANSACTED_PROPNAME, true);
         testProps.setProperty(PUBSUB_PROPNAME, false);
 
-        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
         // collect its messages).
         testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
-        // Send one message and get a linked no consumers exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+        // Send one message and get a linked no route exception.
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
     }
 
     /** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
@@ -166,10 +178,10 @@
         testProps.setProperty(TRANSACTED_PROPNAME, false);
         testProps.setProperty(PUBSUB_PROPNAME, true);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
         // Send one message with no errors.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
     }
 
     /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
@@ -179,10 +191,10 @@
         testProps.setProperty(TRANSACTED_PROPNAME, true);
         testProps.setProperty(PUBSUB_PROPNAME, true);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
         // Send one message with no errors.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion())));
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noExceptionsAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
@@ -195,13 +207,14 @@
         // Use durable subscriptions, so that the route remains open with no subscribers.
         testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
 
         // Disconnect the consumer.
         testCircuit.getReceiver().getConsumer().close();
 
         // Send one message and get a linked no consumers exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
@@ -214,13 +227,14 @@
         // Use durable subscriptions, so that the route remains open with no subscribers.
         testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
 
         // Disconnect the consumer.
         testCircuit.getReceiver().getConsumer().close();
 
         // Send one message and get a linked no consumers exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noConsumersAssertion())));
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noConsumersAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
@@ -230,14 +244,14 @@
         testProps.setProperty(TRANSACTED_PROPNAME, false);
         testProps.setProperty(PUBSUB_PROPNAME, true);
 
-        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
         // collect its messages).
         testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
         // Send one message and get a linked no route exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
     }
 
     /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
@@ -247,14 +261,14 @@
         testProps.setProperty(TRANSACTED_PROPNAME, true);
         testProps.setProperty(PUBSUB_PROPNAME, true);
 
-        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receiver to
+        // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
         // collect its messages).
         testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
 
-        Circuit testCircuit = CircuitImpl.createCircuit(testProps);
-
         // Send one message and get a linked no route exception.
-        assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noRouteAssertion())));
+        TestCaseSequencer sequencer = getTestSequencer();
+        Circuit testCircuit = sequencer.createCircuit(testProps);
+        sequencer.sequenceTest(testCircuit, assertionList(testCircuit.getPublisher().noRouteAssertion()), testProps);
     }
 
     protected void setUp() throws Exception