You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ai...@apache.org on 2008/02/08 11:10:11 UTC

svn commit: r619823 [17/19] - in /incubator/qpid/branches/thegreatmerge/qpid: ./ cpp/ dotnet/ dotnet/Qpid.Buffer.Tests/Properties/ dotnet/Qpid.Buffer/Properties/ dotnet/Qpid.Client.Tests/ dotnet/Qpid.Client.Tests/Channel/ dotnet/Qpid.Client.Tests/Commo...

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java Fri Feb  8 02:09:37 2008
@@ -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.test.framework;
+
+/**
+ * BrokerLifecycleAware is an awareness interface implemented by test cases that can run control the life-cycle of
+ * the brokers on which they run. Its purpose is to expose additional instrumentation of brokers during testing, that
+ * enables tests to use an automated failure mechanism to simulate broker failures, and to re-start failed brokers.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Indicate whether or not a test case is using an in-vm broker.
+ * <tr><td> Track which in-vm broker is currently in use.
+ * <tr><td> Accept setting of a failure mechanism. <td> {@link CauseFailure}.
+ * </table>
+ *
+ * @todo Need to think about how to present the brokers through this interface. Thinking numbering the available
+ *       brokers from 1 will do. Then can kill 1 and assume failing onto 2. Restart 1 and kill 2 and fail back onto
+ *       1 again?
+ */
+public interface BrokerLifecycleAware
+{
+    public void setInVmBrokers();
+
+    /**
+     * Indicates whether or not a test case is using in-vm brokers.
+     *
+     * @return <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise.
+     */
+    public boolean usingInVmBroker();
+
+    /**
+     * Sets the currently live in-vm broker.
+     *
+     * @param i The currently live in-vm broker.
+     */
+    public void setLiveBroker(int i);
+
+    /**
+     * Reports the currently live in-vm broker.
+     *
+     * @return The currently live in-vm broker.
+     */
+    public int getLiveBroker();
+
+    /**
+     * Accepts a failure mechanism.
+     *
+     * @param failureMechanism The failure mechanism.
+     */
+    public void setFailureMechanism(CauseFailure failureMechanism);
+}

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java Fri Feb  8 02:09:37 2008
@@ -0,0 +1,42 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * CauseFailure provides a method to cause a failure in a messaging broker, usually used in conjunction with fail-over
+ * or other failure mode testing. In some cases failures may be automated, for example by shutting down an in-vm broker,
+ * or by sending a special control signal to a broker over a network connection. In other cases, it may be preferable
+ * to ask a user interactively to cause a failure scenario, in which case an implementation may display a prompt or
+ * dialog box asking for notification once the failure has been caused. The purpose of this interface is to abstract
+ * the exact cause and nature of a failure out of failure test cases.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Cause messaging broker failure.
+ * </table>
+ */
+public interface CauseFailure
+{
+    /**
+     * Causes the active message broker to fail.
+     */
+    void causeFailure();
+}

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java Fri Feb  8 02:09:37 2008
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.qpid.test.framework.CauseFailure;
+
+import java.io.IOException;
+
+/**
+ * Causes a message broker failure by interactively prompting the user to cause it.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Cause messaging broker failure.
+ * </table>
+ */
+public class CauseFailureUserPrompt implements CauseFailure
+{
+    /**
+     * Causes the active message broker to fail.
+     */
+    public void causeFailure()
+    {
+        waitForUser("Cause a broker failure now, then press Return.");
+    }
+
+    /**
+     * Outputs a prompt to the console and waits for the user to press return.
+     *
+     * @param prompt The prompt to display on the console.
+     */
+    private void waitForUser(String prompt)
+    {
+        System.out.println(prompt);
+
+        try
+        {
+            System.in.read();
+        }
+        catch (IOException e)
+        {
+            // Ignored.
+        }
+
+        System.out.println("Continuing.");
+    }
+}

Modified: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java?rev=619823&r1=619822&r2=619823&view=diff
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java (original)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEndBase.java Fri Feb  8 02:09:37 2008
@@ -51,11 +51,14 @@
     ExceptionMonitor exceptionMonitor;
 
     /**
-     * Creates a circuit end point on the specified producer, consumer and controlSession.
+     * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+     * for messages and exceptions received by the circuit end.
      *
-     * @param producer The message producer for the circuit end point.
-     * @param consumer The message consumer for the circuit end point.
-     * @param session  The controlSession for the circuit end point.
+     * @param producer         The message producer for the circuit end point.
+     * @param consumer         The message consumer for the circuit end point.
+     * @param session          The controlSession for the circuit end point.
+     * @param messageMonitor   The monitor to notify of all messages received by the circuit end.
+     * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end.
      */
     public CircuitEndBase(MessageProducer producer, MessageConsumer consumer, Session session, MessageMonitor messageMonitor,
         ExceptionMonitor exceptionMonitor)

Modified: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java?rev=619823&r1=619822&r2=619823&view=diff
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java (original)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java Fri Feb  8 02:09:37 2008
@@ -12,6 +12,20 @@
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
+/*
+ *
+ * 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
@@ -36,7 +50,7 @@
  *
  * <p/><table id="crc"><caption>CRC Card</caption>
  * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Record all exceptions received. <td> {@link ExceptionListener}
+ * <tr><td> Record all exceptions received.
  * </table>
  */
 public class ExceptionMonitor implements ExceptionListener
@@ -45,14 +59,14 @@
     private final Logger log = Logger.getLogger(ExceptionMonitor.class);
 
     /** Holds the received exceptions. */
-    List<JMSException> exceptions = new ArrayList<JMSException>();
+    List<Exception> exceptions = new ArrayList<Exception>();
 
     /**
      * Receives incoming exceptions.
      *
      * @param e The exception to record.
      */
-    public void onException(JMSException e)
+    public synchronized void onException(JMSException e)
     {
         log.debug("public void onException(JMSException e): called", e);
 
@@ -64,7 +78,7 @@
      *
      * @return <tt>true</tt> if no exceptions have been received, <tt>false</tt> otherwise.
      */
-    public boolean assertNoExceptions()
+    public synchronized boolean assertNoExceptions()
     {
         return exceptions.isEmpty();
     }
@@ -74,7 +88,7 @@
      *
      * @return <tt>true</tt> if exactly one exception been received, <tt>false</tt> otherwise.
      */
-    public boolean assertOneJMSException()
+    public synchronized boolean assertOneJMSException()
     {
         return exceptions.size() == 1;
     }
@@ -82,20 +96,27 @@
     /**
      * Checks that exactly one exception, with a linked cause of the specified type, has been received.
      *
+     * @param aClass The type of the linked cause.
+     *
      * @return <tt>true</tt> if exactly one exception, with a linked cause of the specified type, been received,
      *         <tt>false</tt> otherwise.
      */
-    public boolean assertOneJMSExceptionWithLinkedCause(Class aClass)
+    public synchronized boolean assertOneJMSExceptionWithLinkedCause(Class aClass)
     {
         if (exceptions.size() == 1)
         {
-            JMSException e = exceptions.get(0);
-
-            Exception linkedCause = e.getLinkedException();
+            Exception e = exceptions.get(0);
 
-            if ((linkedCause != null) && aClass.isInstance(linkedCause))
+            if (e instanceof JMSException)
             {
-                return true;
+                JMSException jmse = (JMSException) e;
+
+                Exception linkedCause = jmse.getLinkedException();
+
+                if ((linkedCause != null) && aClass.isInstance(linkedCause))
+                {
+                    return true;
+                }
             }
         }
 
@@ -103,11 +124,37 @@
     }
 
     /**
+     * Checks that at least one exception of the the specified type, has been received.
+     *
+     * @param exceptionClass The type of the exception.
+     *
+     * @return <tt>true</tt> if at least one exception of the specified type has been received, <tt>false</tt> otherwise.
+     */
+    public synchronized boolean assertExceptionOfType(Class exceptionClass)
+    {
+        // Start by assuming that the exception has no been received.
+        boolean passed = false;
+
+        // Scan all the exceptions for a match.
+        for (Exception e : exceptions)
+        {
+            if (exceptionClass.isInstance(e))
+            {
+                passed = true;
+
+                break;
+            }
+        }
+
+        return passed;
+    }
+
+    /**
      * Reports the number of exceptions held by this monitor.
      *
      * @return The number of exceptions held by this monitor.
      */
-    public int size()
+    public synchronized int size()
     {
         return exceptions.size();
     }
@@ -115,9 +162,9 @@
     /**
      * Clears the record of received exceptions.
      */
-    public void reset()
+    public synchronized void reset()
     {
-        exceptions = new ArrayList();
+        exceptions = new ArrayList<Exception>();
     }
 
     /**
@@ -126,11 +173,11 @@
      *
      * @return A string containing a dump of the stack traces of all exceptions.
      */
-    public String toString()
+    public synchronized String toString()
     {
         String result = "ExceptionMonitor: holds " + exceptions.size() + " exceptions.\n\n";
 
-        for (JMSException ex : exceptions)
+        for (Exception ex : exceptions)
         {
             result += getStackTrace(ex) + "\n";
         }

Modified: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java?rev=619823&r1=619822&r2=619823&view=diff
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java (original)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java Fri Feb  8 02:09:37 2008
@@ -20,23 +20,20 @@
  */
 package org.apache.qpid.test.framework;
 
-import junit.framework.TestCase;
-
 import org.apache.log4j.Logger;
 import org.apache.log4j.NDC;
 
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
+import org.apache.qpid.test.framework.BrokerLifecycleAware;
 import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-import org.apache.qpid.util.ConversationFactory;
 
 import uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
+import uk.co.thebadgerset.junit.extensions.SetupTaskAware;
+import uk.co.thebadgerset.junit.extensions.SetupTaskHandler;
 import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+import uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Properties;
 
 /**
  * FrameworkBaseCase provides a starting point for writing test cases against the test framework. Its main purpose is
@@ -50,13 +47,26 @@
  * <tr><td> Convert failed assertions to error messages.
  * </table>
  */
-public class FrameworkBaseCase extends AsymptoticTestCase
+public class FrameworkBaseCase extends AsymptoticTestCase implements FrameworkTestContext, SetupTaskAware,
+    BrokerLifecycleAware
 {
     /** Used for debugging purposes. */
     private static final Logger log = Logger.getLogger(FrameworkBaseCase.class);
 
     /** Holds the test sequencer to create and run test circuits with. */
-    protected CircuitFactory circuitFactory = new DefaultCircuitFactory();
+    protected CircuitFactory circuitFactory = new LocalCircuitFactory();
+
+    /** Used to read the tests configurable properties through. */
+    protected ParsedProperties testProps;
+
+    /** A default setup task processor to delegate setup tasks to. */
+    protected SetupTaskHandler taskHandler = new SetupTaskHandler();
+
+    /** Flag used to track whether the test is in-vm or not. */
+    protected boolean isUsingInVM;
+
+    /** Holds the failure mechanism. */
+    protected CauseFailure failureMechanism = new CauseFailureUserPrompt();
 
     /**
      * Creates a new test case with the specified name.
@@ -92,6 +102,26 @@
     }
 
     /**
+     * Reports the current test case name.
+     *
+     * @return The current test case name.
+     */
+    public TestCaseVector getTestCaseVector()
+    {
+        return new TestCaseVector(this.getName(), 0);
+    }
+
+    /**
+     * Reports the current test case parameters.
+     *
+     * @return The current test case parameters.
+     */
+    public MessagingTestConfigProperties getTestParameters()
+    {
+        return new MessagingTestConfigProperties(testProps);
+    }
+
+    /**
      * Creates a list of assertions.
      *
      * @param asserts The assertions to compile in a list.
@@ -116,7 +146,7 @@
      *
      * @param asserts The list of failed assertions.
      */
-    protected void assertNoFailures(List<Assertion> asserts)
+    protected static void assertNoFailures(List<Assertion> asserts)
     {
         log.debug("protected void assertNoFailures(List<Assertion> asserts = " + asserts + "): called");
 
@@ -140,7 +170,7 @@
      *
      * @return The error message.
      */
-    protected String assertionsToString(List<Assertion> asserts)
+    protected static String assertionsToString(List<Assertion> asserts)
     {
         String errorMessage = "";
 
@@ -161,8 +191,10 @@
     {
         NDC.push(getName());
 
-        // Ensure that the in-vm broker is created.
-        TransportConnection.createVMBroker(1);
+        testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+        // Process all optional setup tasks. This may include in-vm broker creation, if a decorator has added it.
+        taskHandler.runSetupTasks();
     }
 
     /**
@@ -170,16 +202,30 @@
      */
     protected void tearDown()
     {
-        try
-        {
-            // Ensure that the in-vm broker is cleaned up so that the next test starts afresh.
-            TransportConnection.killVMBroker(1);
-            ApplicationRegistry.remove(1);
-        }
-        finally
-        {
-            NDC.pop();
-        }
+        NDC.pop();
+
+        // Process all optional tear down tasks. This may include in-vm broker clean up, if a decorator has added it.
+        taskHandler.runTearDownTasks();
+    }
+
+    /**
+     * Adds the specified task to the tests setup.
+     *
+     * @param task The task to add to the tests setup.
+     */
+    public void chainSetupTask(Runnable task)
+    {
+        taskHandler.chainSetupTask(task);
+    }
+
+    /**
+     * Adds the specified task to the tests tear down.
+     *
+     * @param task The task to add to the tests tear down.
+     */
+    public void chainTearDownTask(Runnable task)
+    {
+        taskHandler.chainTearDownTask(task);
     }
 
     /**
@@ -197,84 +243,46 @@
         return methodName;
     }
 
+    public void setInVmBrokers()
+    {
+        isUsingInVM = true;
+    }
+
     /**
-     * DefaultCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted
-     * on the same JVM.
+     * Indicates whether or not a test case is using in-vm brokers.
+     *
+     * @return <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise.
      */
-    public class DefaultCircuitFactory implements CircuitFactory
+    public boolean usingInVmBroker()
     {
-        /**
-         * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
-         * begining the test and gathering the test reports from the participants.
-         *
-         * @param testCircuit    The test circuit.
-         * @param assertions     The list of assertions to apply to the test circuit.
-         * @param testProperties The test case definition.
-         */
-        public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
-        {
-            assertNoFailures(testCircuit.test(1, assertions));
-        }
-
-        /**
-         * Creates a test circuit for the test, configered by the test parameters specified.
-         *
-         * @param testProperties The test parameters.
-         * @return A test circuit.
-         */
-        public Circuit createCircuit(ParsedProperties testProperties)
-        {
-            return LocalCircuitImpl.createCircuit(testProperties);
-        }
-
-        /**
-         * Sets the sender test client to coordinate the test with.
-         *
-         * @param sender The contact details of the sending client in the test.
-         */
-        public void setSender(TestClientDetails sender)
-        {
-            throw new RuntimeException("Not implemented.");
-        }
-
-        /**
-         * Sets the receiving test client to coordinate the test with.
-         *
-         * @param receiver The contact details of the sending client in the test.
-         */
-        public void setReceiver(TestClientDetails receiver)
-        {
-            throw new RuntimeException("Not implemented.");
-        }
+        return isUsingInVM;
+    }
 
-        /**
-         * Supplies the sending test client.
-         *
-         * @return The sending test client.
-         */
-        public TestClientDetails getSender()
-        {
-            throw new RuntimeException("Not implemented.");
-        }
+    /**
+     * Sets the currently live in-vm broker.
+     *
+     * @param i The currently live in-vm broker.
+     */
+    public void setLiveBroker(int i)
+    { }
 
-        /**
-         * Supplies the receiving test client.
-         *
-         * @return The receiving test client.
-         */
-        public List<TestClientDetails> getReceivers()
-        {
-            throw new RuntimeException("Not implemented.");
-        }
+    /**
+     * Reports the currently live in-vm broker.
+     *
+     * @return The currently live in-vm broker.
+     */
+    public int getLiveBroker()
+    {
+        return 0;
+    }
 
-        /**
-         * Accepts the conversation factory over which to hold the test coordinating conversation.
-         *
-         * @param conversationFactory The conversation factory to coordinate the test over.
-         */
-        public void setConversationFactory(ConversationFactory conversationFactory)
-        {
-            throw new RuntimeException("Not implemented.");
-        }
+    /**
+     * Accepts a failure mechanism.
+     *
+     * @param failureMechanism The failure mechanism.
+     */
+    public void setFailureMechanism(CauseFailure failureMechanism)
+    {
+        this.failureMechanism = failureMechanism;
     }
 }

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java Fri Feb  8 02:09:37 2008
@@ -0,0 +1,48 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * A FrameworkTestContext provides context information to test code about the current test case being run; its name, its
+ * parameters.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide the name of the current test case.
+ * <tr><td> Provide the test parameters.
+ * </table>
+ */
+public interface FrameworkTestContext
+{
+    /**
+     * Reports the current test case name.
+     *
+     * @return The current test case name.
+     */
+    TestCaseVector getTestCaseVector();
+
+    /**
+     * Reports the current test case parameters.
+     *
+     * @return The current test case parameters.
+     */
+    MessagingTestConfigProperties getTestParameters();
+}

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java Fri Feb  8 02:09:37 2008
@@ -0,0 +1,168 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.test.framework.localcircuit.LocalAMQPPublisherImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+/**
+ * LocalAMQPCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted
+ * on the same JVM, allowing AMQP/Qpid specific options to be applied to the circuit.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * <tr><td> Construct test circuits the support AMQP specific options.
+ * </table>
+ */
+public class LocalAMQPCircuitFactory extends LocalCircuitFactory
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(LocalAMQPCircuitFactory.class);
+
+    /**
+     * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+     *
+     * @param connection The connection to build the circuit end on.
+     * @param testProps  The test parameters to configure the circuit end construction.
+     * @param uniqueId   A unique number to being numbering destinations from, to make this circuit unique.
+     *
+     * @return A circuit end suitable for the publishing side of a test circuit.
+     *
+     * @throws javax.jms.JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+     */
+    public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+        throws JMSException
+    {
+        log.debug(
+            "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+            + uniqueId + "): called");
+
+        // Cast the test properties into a typed interface for convenience.
+        MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+        Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+        Destination destination =
+            props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+                              : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+        MessageProducer producer =
+            props.getPublisherProducerBind()
+            ? ((props.getImmediate() | props.getMandatory())
+                ? ((AMQSession) session).createProducer(destination, props.getMandatory(), props.getImmediate())
+                : session.createProducer(destination)) : null;
+
+        MessageConsumer consumer =
+            props.getPublisherConsumerBind()
+            ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+        MessageMonitor messageMonitor = new MessageMonitor();
+
+        if (consumer != null)
+        {
+            consumer.setMessageListener(messageMonitor);
+        }
+
+        ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+        connection.setExceptionListener(exceptionMonitor);
+
+        if (!props.getPublisherConsumerActive() && (consumer != null))
+        {
+            consumer.close();
+        }
+
+        return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+    }
+
+    /**
+     * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+     *
+     * @param connection The connection to build the circuit end on.
+     * @param testProps  The test parameters to configure the circuit end construction.
+     * @param uniqueId   A unique number to being numbering destinations from, to make this circuit unique.
+     *
+     * @return A circuit end suitable for the receiving side of a test circuit.
+     *
+     * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+     */
+    public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+        throws JMSException
+    {
+        log.debug(
+            "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+            + uniqueId + "): called");
+
+        // Cast the test properties into a typed interface for convenience.
+        MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+        Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+        MessageProducer producer =
+            props.getReceiverProducerBind()
+            ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+        Destination destination =
+            props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+                              : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+        MessageConsumer consumer =
+            props.getReceiverConsumerBind()
+            ? ((props.getDurableSubscription() && props.getPubsub())
+                ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+            : null;
+
+        MessageMonitor messageMonitor = new MessageMonitor();
+
+        if (consumer != null)
+        {
+            consumer.setMessageListener(messageMonitor);
+        }
+
+        if (!props.getReceiverConsumerActive() && (consumer != null))
+        {
+            consumer.close();
+        }
+
+        return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+    }
+
+    /**
+     * Creates a local {@link Publisher} from a {@link CircuitEnd}. The publisher implementation provides AMQP
+     * specific assertion methods, for testing beyond JMS.
+     *
+     * @param publisherEnd The publishing circuit end.
+     *
+     * @return A {@link Receiver}.
+     */
+    protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+    {
+        return new LocalAMQPPublisherImpl(publisherEnd);
+    }
+}

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java Fri Feb  8 02:09:37 2008
@@ -0,0 +1,316 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalReceiverImpl;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+import org.apache.qpid.util.ConversationFactory;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * LocalCircuitFactory is a circuit factory that creates test circuits with publishing and receiving ends rooted
+ * on the same JVM. The ends of the circuit are presented as {@link Publisher} and {@link Receiver} interfaces, which
+ * in turn provide methods to apply assertions to the circuit. The creation of the circuit ends, and the presentation
+ * of the ends as publisher/receiver interfaces, are designed to be overriden, so that circuits and assertions that
+ * use messaging features not available in JMS can be written. This provides an extension point for writing tests
+ * against proprietary features of JMS implementations.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * </table>
+ */
+public class LocalCircuitFactory implements CircuitFactory
+{
+    /** Used for debugging. */
+    private static final Logger log = Logger.getLogger(LocalCircuitFactory.class);
+
+    /** Used to create unique destination names for each test. */
+    protected static AtomicLong uniqueDestsId = new AtomicLong();
+
+    /**
+     * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+     * begining the test and gathering the test reports from the participants.
+     *
+     * @param testCircuit    The test circuit.
+     * @param assertions     The list of assertions to apply to the test circuit.
+     * @param testProperties The test case definition.
+     */
+    public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
+    {
+        FrameworkBaseCase.assertNoFailures(testCircuit.test(1, assertions));
+    }
+
+    /**
+     * Creates a test circuit for the test, configered by the test parameters specified.
+     *
+     * @param testProperties The test parameters.
+     *
+     * @return A test circuit.
+     */
+    public Circuit createCircuit(ParsedProperties testProperties)
+    {
+        Circuit result;
+
+        // Cast the test properties into a typed interface for convenience.
+        MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+        // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
+        try
+        {
+            // Get a unique offset to append to destination names to make them unique to the connection.
+            long uniqueId = uniqueDestsId.incrementAndGet();
+
+            // Set up the connection.
+            Connection connection = TestUtils.createConnection(testProperties);
+
+            // Add the connection exception listener to assert on exception conditions with.
+            // ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+            // connection.setExceptionListener(exceptionMonitor);
+
+            // Set up the publisher.
+            CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, props, uniqueId);
+
+            // Set up the receiver.
+            CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, props, uniqueId);
+
+            // Start listening for incoming messages.
+            connection.start();
+
+            // Package everything up.
+            LocalPublisherImpl publisher = createPublisherFromCircuitEnd(publisherEnd);
+            LocalReceiverImpl receiver = createReceiverFromCircuitEnd(receiverEnd);
+
+            result = new LocalCircuitImpl(testProperties, publisher, receiver, connection, publisher.getExceptionMonitor());
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
+        }
+
+        return result;
+    }
+
+    /**
+     * Creates a local {@link Receiver} from a {@link CircuitEnd}. Sub-classes may override this to provide more
+     * specialized receivers if necessary.
+     *
+     * @param receiverEnd The receiving circuit end.
+     *
+     * @return A {@link Receiver}.
+     */
+    protected LocalReceiverImpl createReceiverFromCircuitEnd(CircuitEndBase receiverEnd)
+    {
+        return new LocalReceiverImpl(receiverEnd);
+    }
+
+    /**
+     * Creates a local {@link Publisher} from a {@link CircuitEnd}. Sub-classes may override this to provide more
+     * specialized receivers if necessary.
+     *
+     * @param publisherEnd The publishing circuit end.
+     *
+     * @return A {@link Receiver}.
+     */
+    protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+    {
+        return new LocalPublisherImpl(publisherEnd);
+    }
+
+    /**
+     * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+     *
+     * @param connection The connection to build the circuit end on.
+     * @param testProps  The test parameters to configure the circuit end construction.
+     * @param uniqueId   A unique number to being numbering destinations from, to make this circuit unique.
+     *
+     * @return A circuit end suitable for the publishing side of a test circuit.
+     *
+     * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+     */
+    public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+        throws JMSException
+    {
+        log.debug(
+            "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+            + uniqueId + "): called");
+
+        // Cast the test properties into a typed interface for convenience.
+        MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+        // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+        if (props.getImmediate() || props.getMandatory())
+        {
+            throw new RuntimeException(
+                "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+        }
+
+        Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+        Destination destination =
+            props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+                              : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+        MessageProducer producer = props.getPublisherProducerBind() ? session.createProducer(destination) : null;
+
+        MessageConsumer consumer =
+            props.getPublisherConsumerBind()
+            ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+        MessageMonitor messageMonitor = new MessageMonitor();
+
+        if (consumer != null)
+        {
+            consumer.setMessageListener(messageMonitor);
+        }
+
+        ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+        connection.setExceptionListener(exceptionMonitor);
+
+        if (!props.getPublisherConsumerActive() && (consumer != null))
+        {
+            consumer.close();
+        }
+
+        return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+    }
+
+    /**
+     * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+     *
+     * @param connection The connection to build the circuit end on.
+     * @param testProps  The test parameters to configure the circuit end construction.
+     * @param uniqueId   A unique number to being numbering destinations from, to make this circuit unique.
+     *
+     * @return A circuit end suitable for the receiving side of a test circuit.
+     *
+     * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+     */
+    public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+        throws JMSException
+    {
+        log.debug(
+            "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+            + uniqueId + "): called");
+
+        // Cast the test properties into a typed interface for convenience.
+        MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+        // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+        if (props.getImmediate() || props.getMandatory())
+        {
+            throw new RuntimeException(
+                "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+        }
+
+        Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+        MessageProducer producer =
+            props.getReceiverProducerBind()
+            ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+        Destination destination =
+            props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+                              : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+        MessageConsumer consumer =
+            props.getReceiverConsumerBind()
+            ? ((props.getDurableSubscription() && props.getPubsub())
+                ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+            : null;
+
+        MessageMonitor messageMonitor = new MessageMonitor();
+
+        if (consumer != null)
+        {
+            consumer.setMessageListener(messageMonitor);
+        }
+
+        if (!props.getReceiverConsumerActive() && (consumer != null))
+        {
+            consumer.close();
+        }
+
+        return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+    }
+
+    /**
+     * Sets the sender test client to coordinate the test with.
+     *
+     * @param sender The contact details of the sending client in the test.
+     */
+    public void setSender(TestClientDetails sender)
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Sets the receiving test client to coordinate the test with.
+     *
+     * @param receiver The contact details of the sending client in the test.
+     */
+    public void setReceiver(TestClientDetails receiver)
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Supplies the sending test client.
+     *
+     * @return The sending test client.
+     */
+    public TestClientDetails getSender()
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Supplies the receiving test client.
+     *
+     * @return The receiving test client.
+     */
+    public List<TestClientDetails> getReceivers()
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Accepts the conversation factory over which to hold the test coordinating conversation.
+     *
+     * @param conversationFactory The conversation factory to coordinate the test over.
+     */
+    public void setConversationFactory(ConversationFactory conversationFactory)
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+}

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java Fri Feb  8 02:09:37 2008
@@ -0,0 +1,167 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * MessageIdentityVector provides a message identification scheme, that matches individual messages with test cases.
+ * Test messages are being sent by a number of test clients, sending messages over a set of routes, and being received
+ * by another set of test clients. Each test is itself, being run within a test cycle, of which there could be many. It
+ * is the job of the test coordinator to request and receive reports from the available test clients, on what has been
+ * sent, what has been received, and what errors may have occurred, and to reconcile this information against the
+ * assertions being applied by the test case. In order to be able to figure out which messages belong to which test,
+ * there needs to be an identification scheme, that the coordinator can use to correlate messages in senders and
+ * receiver reports. Every message sent in a test can be associated with this information.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Identify a test case, a handling client id, a circuit end within the client, and a test cycle number.
+ * </table>
+ */
+public class MessageIdentityVector
+{
+    /** Holds the test case vector component of the message identity vector. */
+    private TestCaseVector testCaseVector;
+
+    /** The unique client id. */
+    private String clientId;
+
+    /** The unique circuit end number within the client id. */
+    private int circuitEndId;
+
+    /**
+     * Creates a new identity vector for test messages.
+     *
+     * @param testCase        The name of the test case generating the messages.
+     * @param clientId        The unique id of the client implementing a circuit end that is handling the messages.
+     * @param circuitEndId    The unique id number of the circuit end within the client.
+     * @param testCycleNumber The cycle iteration number of the test case.
+     */
+    public MessageIdentityVector(String testCase, String clientId, int circuitEndId, int testCycleNumber)
+    {
+        this.testCaseVector = new TestCaseVector(testCase, testCycleNumber);
+        this.clientId = clientId;
+        this.circuitEndId = circuitEndId;
+    }
+
+    /**
+     * Reports the test case vector component of the message identity vector.
+     *
+     * @return The test case vector component of the message identity vector.
+     */
+    public TestCaseVector getTestCaseVector()
+    {
+        return testCaseVector;
+    }
+
+    /**
+     * Reports the name of the test case.
+     *
+     * @return The name of the test case.
+     */
+    public String getTestCase()
+    {
+        return testCaseVector.getTestCase();
+    }
+
+    /**
+     * Reports the test iteration cycle number within the test case.
+     *
+     * @return The test iteration cycle number within the test case.
+     */
+    public int getTestCycleNumber()
+    {
+        return testCaseVector.getTestCycleNumber();
+    }
+
+    /**
+     * Resports the client id.
+     *
+     * @return The client id.
+     */
+    public String getClientId()
+    {
+        return clientId;
+    }
+
+    /**
+     * Reports the circuit end number within the test client.
+     *
+     * @return The circuit end number within the test client.
+     */
+    public int getCircuitEndId()
+    {
+        return circuitEndId;
+    }
+
+    /**
+     * Compares this identity vector with another for equality. All fields must match.
+     *
+     * @param o The identity vector to compare with.
+     *
+     * @return <tt>true</tt> if the identity vector is identical to this one by all fields, <tt>false</tt> otherwise.
+     */
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+
+        if ((o == null) || (getClass() != o.getClass()))
+        {
+            return false;
+        }
+
+        MessageIdentityVector that = (MessageIdentityVector) o;
+
+        if (circuitEndId != that.circuitEndId)
+        {
+            return false;
+        }
+
+        if ((clientId != null) ? (!clientId.equals(that.clientId)) : (that.clientId != null))
+        {
+            return false;
+        }
+
+        if ((testCaseVector != null) ? (!testCaseVector.equals(that.testCaseVector)) : (that.testCaseVector != null))
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+    * Computes a hash code for this identity vector based on all fields.
+    *
+    * @return A hash code for this identity vector based on all fields.
+    */
+    public int hashCode()
+    {
+        int result;
+        result = ((testCaseVector != null) ? testCaseVector.hashCode() : 0);
+        result = (31 * result) + ((clientId != null) ? clientId.hashCode() : 0);
+        result = (31 * result) + circuitEndId;
+
+        return result;
+    }
+}

Modified: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java?rev=619823&r1=619822&r2=619823&view=diff
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java (original)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java Fri Feb  8 02:09:37 2008
@@ -20,10 +20,10 @@
  */
 package org.apache.qpid.test.framework;
 
-import org.apache.qpid.jms.Session;
-
 import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
 
+import javax.jms.Session;
+
 import java.util.Properties;
 
 /**
@@ -181,10 +181,16 @@
     public static final boolean PERSISTENT_MODE_DEFAULT = false;
 
     /** Holds the name of the property to get the test transactional mode from. */
-    public static final String TRANSACTED_PROPNAME = "transacted";
+    public static final String TRANSACTED_PUBLISHER_PROPNAME = "transactedPublisher";
+
+    /** Holds the transactional mode to use for the test. */
+    public static final boolean TRANSACTED_PUBLISHER_DEFAULT = false;
+
+    /** Holds the name of the property to get the test transactional mode from. */
+    public static final String TRANSACTED_RECEIVER_PROPNAME = "transactedReceiver";
 
     /** Holds the transactional mode to use for the test. */
-    public static final boolean TRANSACTED_DEFAULT = false;
+    public static final boolean TRANSACTED_RECEIVER_DEFAULT = false;
 
     /** Holds the name of the property to set the no local flag from. */
     public static final String NO_LOCAL_PROPNAME = "noLocal";
@@ -204,7 +210,7 @@
     /** Defines the default value of the durable subscriptions flag. */
     public static final boolean DURABLE_SUBSCRIPTION_DEFAULT = false;
 
-    // ======================  Qpid Options and Flags ================================
+    // ======================  Qpid/AMQP Options and Flags ================================
 
     /** Holds the name of the property to set the exclusive flag from. */
     public static final String EXCLUSIVE_PROPNAME = "exclusive";
@@ -230,7 +236,7 @@
     /** Default value for the durable destinations flag. */
     public static final boolean DURABLE_DESTS_DEFAULT = false;
 
-    /** Holds the name of the proeprty to set the prefetch size from. */
+    /** Holds the name of the property to set the prefetch size from. */
     public static final String PREFETCH_PROPNAME = "prefetch";
 
     /** Defines the default prefetch size to use when consuming messages. */
@@ -274,6 +280,26 @@
     /** Defines the default maximum quantity of pending message data to allow producers to hold. */
     public static final int MAX_PENDING_DEFAULT = 0;
 
+    /** Holds the name of the property to get the publisher rollback flag from. */
+    public static final String ROLLBACK_PUBLISHER_PROPNAME = "rollbackPublisher";
+
+    /** Holds the default publisher roll back setting. */
+    public static final boolean ROLLBACK_PUBLISHER_DEFAULT = false;
+
+    /** Holds the name of the property to get the publisher rollback flag from. */
+    public static final String ROLLBACK_RECEIVER_PROPNAME = "rollbackReceiver";
+
+    /** Holds the default publisher roll back setting. */
+    public static final boolean ROLLBACK_RECEIVER_DEFAULT = false;
+
+    // ====================== Options that control the bahviour of the test framework. =========================
+
+    /** Holds the name of the property to get the behavioural mode of not applicable assertions. */
+    public static final String NOT_APPLICABLE_ASSERTION_PROPNAME = "notApplicableAssertion";
+
+    /** Holds the default behavioral mode of not applicable assertions, which is logging them as a warning. */
+    public static final String NOT_APPLICABLE_ASSERTION_DEFAULT = "warn";
+
     /** Holds the name of the property to get the verbose mode proeprty from. */
     public static final String VERBOSE_PROPNAME = "verbose";
 
@@ -286,8 +312,11 @@
     static
     {
         defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
-        // defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_DEFAULT);
-        defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+        defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
+        defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+        defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
+        defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+
         defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
         defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
         defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT);
@@ -296,28 +325,33 @@
         defaults.setPropertyIfNull(RECEIVER_CONSUMER_ACTIVE_PROPNAME, RECEIVER_CONSUMER_ACTIVE_DEFAULT);
         defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT);
         defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
-        defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
-        defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT);
-        defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
-        defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
-        defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
-        defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
-        defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
-        defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
-        defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
-        defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
         defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
-        defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
-        defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
-        defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+        defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
+
+        defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
+        defaults.setPropertyIfNull(TRANSACTED_PUBLISHER_PROPNAME, TRANSACTED_PUBLISHER_DEFAULT);
+        defaults.setPropertyIfNull(TRANSACTED_RECEIVER_PROPNAME, TRANSACTED_RECEIVER_DEFAULT);
+        defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
         defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
         defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
-        defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
-        defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT);
-        defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
+
         defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
         defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
         defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
+        defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+        defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT);
+
+        defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+        defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
+        defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
+        defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
+        defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
+        defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+        defaults.setPropertyIfNull(ROLLBACK_PUBLISHER_PROPNAME, ROLLBACK_PUBLISHER_DEFAULT);
+        defaults.setPropertyIfNull(ROLLBACK_RECEIVER_PROPNAME, ROLLBACK_RECEIVER_DEFAULT);
+
+        defaults.setPropertyIfNull(NOT_APPLICABLE_ASSERTION_PROPNAME, NOT_APPLICABLE_ASSERTION_DEFAULT);
+        defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
     }
 
     /**
@@ -338,148 +372,314 @@
         super(properties);
     }
 
+    /**
+     * The size of test messages to send.
+     *
+     * @return The size of test messages to send.
+     */
     public int getMessageSize()
     {
         return getPropertyAsInteger(MESSAGE_SIZE_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that the publishing producer should be set up to publish to a destination.
+     *
+     * @return Flag to indicate that the publishing producer should be set up to publish to a destination.
+     */
     public boolean getPublisherProducerBind()
     {
         return getPropertyAsBoolean(PUBLISHER_PRODUCER_BIND_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that the publishing consumer should be set up to receive from a destination.
+     *
+     * @return Flag to indicate that the publishing consumer should be set up to receive from a destination.
+     */
     public boolean getPublisherConsumerBind()
     {
         return getPropertyAsBoolean(PUBLISHER_CONSUMER_BIND_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that the receiving producer should be set up to publish to a destination.
+     *
+     * @return Flag to indicate that the receiving producer should be set up to publish to a destination.
+     */
     public boolean getReceiverProducerBind()
     {
         return getPropertyAsBoolean(RECEIVER_PRODUCER_BIND_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that the receiving consumer should be set up to receive from a destination.
+     *
+     * @return Flag to indicate that the receiving consumer should be set up to receive from a destination.
+     */
     public boolean getReceiverConsumerBind()
     {
         return getPropertyAsBoolean(RECEIVER_CONSUMER_BIND_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that the publishing consumer should be created and actively listening.
+     *
+     * @return Flag to indicate that the publishing consumer should be created.
+     */
     public boolean getPublisherConsumerActive()
     {
         return getPropertyAsBoolean(PUBLISHER_CONSUMER_ACTIVE_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that the receiving consumers should be created and actively listening.
+     *
+     * @return Flag to indicate that the receiving consumers should be created and actively listening.
+     */
     public boolean getReceiverConsumerActive()
     {
         return getPropertyAsBoolean(RECEIVER_CONSUMER_ACTIVE_PROPNAME);
     }
 
+    /**
+     * A root to create all test destination names from.
+     *
+     * @return A root to create all test destination names from.
+     */
     public String getSendDestinationNameRoot()
     {
         return getProperty(SEND_DESTINATION_NAME_ROOT_PROPNAME);
     }
 
+    /**
+     * A root to create all receiving destination names from.
+     *
+     * @return A root to create all receiving destination names from.
+     */
     public String getReceiveDestinationNameRoot()
     {
         return getProperty(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that persistent messages should be used.
+     *
+     * @return Flag to indicate that persistent messages should be used.
+     */
     public boolean getPersistentMode()
     {
         return getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME);
     }
 
-    public boolean getTransacted()
+    /**
+     * Flag to indicate that transactional messages should be sent by the publisher.
+     *
+     * @return Flag to indicate that transactional messages should be sent by the publisher.
+     */
+    public boolean getPublisherTransacted()
     {
-        return getPropertyAsBoolean(TRANSACTED_PROPNAME);
+        return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
     }
 
-    public String getBroker()
+    /**
+     * Flag to indicate that transactional receives should be used by the receiver.
+     *
+     * @return Flag to indicate that transactional receives should be used by the receiver.
+     */
+    public boolean getReceiverTransacted()
     {
-        return getProperty(BROKER_PROPNAME);
+        return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
     }
 
+    /**
+     * The name of the virtual host to run all tests over.
+     *
+     * @return The name of the virtual host to run all tests over.
+     */
     public String getVirtualHost()
     {
         return getProperty(VIRTUAL_HOST_PROPNAME);
     }
 
+    /**
+     * Limiting rate for each sender in messages per second, or zero for unlimited.
+     *
+     * @return Limiting rate for each sender in messages per second, or zero for unlimited.
+     */
     public String getRate()
     {
         return getProperty(RATE_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that test messages should be received publish/subscribe style by all receivers.
+     *
+     * @return Flag to indicate that test messages should be received publish/subscribe style by all receivers.
+     */
     public boolean getPubsub()
     {
         return getPropertyAsBoolean(PUBSUB_PROPNAME);
     }
 
+    /**
+     * The username credentials to run tests with.
+     *
+     * @return The username credentials to run tests with.
+     */
     public String getUsername()
     {
         return getProperty(USERNAME_PROPNAME);
     }
 
+    /**
+     * The password credentials to run tests with.
+     *
+     * @return The password credentials to run tests with.
+     */
     public String getPassword()
     {
         return getProperty(PASSWORD_PROPNAME);
     }
 
-    public int getDestinationCount()
-    {
-        return getPropertyAsInteger(DESTINATION_COUNT_PROPNAME);
-    }
-
+    /**
+     * The timeout duration to fail tests on, should they receive no messages within it.
+     *
+     * @return The timeout duration to fail tests on, should they receive no messages within it.
+     */
     public long getTimeout()
     {
         return getPropertyAsLong(TIMEOUT_PROPNAME);
     }
 
+    /**
+     * The number of messages to batch into each transaction in transational tests.
+     *
+     * @return The number of messages to batch into each transaction in transational tests.
+     */
     public int getTxBatchSize()
     {
         return getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that tests should use durable destinations.
+     *
+     * @return Flag to indicate that tests should use durable destinations.
+     */
     public boolean getDurableDests()
     {
         return getPropertyAsBoolean(DURABLE_DESTS_PROPNAME);
     }
 
+    /**
+     * The ack mode for message receivers to use.
+     *
+     * @return The ack mode for message receivers to use.
+     */
     public int getAckMode()
     {
         return getPropertyAsInteger(ACK_MODE_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that tests should use durable subscriptions.
+     *
+     * @return Flag to indicate that tests should use durable subscriptions.
+     */
     public boolean getDurableSubscription()
     {
         return getPropertyAsBoolean(DURABLE_SUBSCRIPTION_PROPNAME);
     }
 
+    /**
+     * The maximum amount of in-flight data, in bytes, that tests should send at any time.
+     *
+     * @return The maximum amount of in-flight data, in bytes, that tests should send at any time.
+     */
     public int getMaxPending()
     {
         return getPropertyAsInteger(MAX_PENDING_PROPNAME);
     }
 
-    public int getPrefecth()
+    /**
+     * The size of the prefetch queue to use.
+     *
+     * @return The size of the prefetch queue to use.
+     */
+    public int getPrefetch()
     {
         return getPropertyAsInteger(PREFETCH_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that subscriptions should be no-local.
+     *
+     * @return Flag to indicate that subscriptions should be no-local.
+     */
     public boolean getNoLocal()
     {
         return getPropertyAsBoolean(NO_LOCAL_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that subscriptions should be exclusive.
+     *
+     * @return Flag to indicate that subscriptions should be exclusive.
+     */
     public boolean getExclusive()
     {
         return getPropertyAsBoolean(EXCLUSIVE_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that messages must be delivered immediately.
+     *
+     * @return Flag to indicate that messages must be delivered immediately.
+     */
     public boolean getImmediate()
     {
         return getPropertyAsBoolean(IMMEDIATE_PROPNAME);
     }
 
+    /**
+     * Flag to indicate that messages must be routable.
+     *
+     * @return Flag to indicate that messages must be routable.
+     */
     public boolean getMandatory()
     {
         return getPropertyAsBoolean(MANDATORY_PROPNAME);
+    }
+
+    /**
+     * Gets the value of a flag to indicate that the publisher should rollback all messages sent.
+     *
+     * @return A flag to indicate that the publisher should rollback all messages sent.
+     */
+    public boolean getRollbackPublisher()
+    {
+        return getPropertyAsBoolean(ROLLBACK_PUBLISHER_PROPNAME);
+    }
+
+    /**
+     * Gets the value of a flag to indicate that the receiver should rollback all messages received, then receive them
+     * again.
+     *
+     * @return A flag to indicate that the publisher should rollback all messages received.
+     */
+    public boolean getRollbackReceiver()
+    {
+        return getPropertyAsBoolean(ROLLBACK_RECEIVER_PROPNAME);
+    }
+
+    /**
+     * Gets the behavioural mode of not applicable assertions. Should be one of 'quiet', 'warn' or 'fail'.
+     *
+     * @return The behavioural mode of not applicable assertions.
+     */
+    public String getNotApplicableAssertionMode()
+    {
+        return getProperty(NOT_APPLICABLE_ASSERTION_PROPNAME);
     }
 }

Added: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java?rev=619823&view=auto
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java (added)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java Fri Feb  8 02:09:37 2008
@@ -0,0 +1,112 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+/**
+ * NotApplicableAssertion is a messaging assertion that can be used when an assertion requested by a test-case is not
+ * applicable to the testing scenario. For example an assertion may relate to AMQP functionality, but a test case may be
+ * being run over a non-AMQP JMS implementation, in which case the request to create the assertion may return this
+ * instead of the proper assertion. The test framework is configurable to quietly drop these assertions, log them
+ * as warnings to the console, or raise them as test failures.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Quitely pass.
+ * <tr><td> Log a warning.
+ * <tr><td> Raise a test failure.
+ * </table>
+ */
+public class NotApplicableAssertion implements Assertion
+{
+    /** Used for logging to the console. */
+    private static final Logger console = Logger.getLogger("CONSOLE." + NotApplicableAssertion.class.getName());
+
+    /** The possible behavioural modes of this assertion. */
+    private enum Mode
+    {
+        /** Quietly ignore the assertion by passing. */
+        Quiet,
+
+        /** Ignore the assertion by passing but log a warning about it. */
+        Warn,
+
+        /** Fail the assertion. */
+        Fail;
+    }
+
+    /** The behavioural mode of the assertion. */
+    private Mode mode;
+
+    /**
+     * Creates an assertion that is driven by the value of the 'notApplicableAssertion' property of the test
+     * configuration. Its value should match one of 'quiet', 'warn' or 'fail' and if it does not it is automatically
+     * read as 'fail'.
+     *
+     * @param testProperties The test configuration properties.
+     */
+    public NotApplicableAssertion(ParsedProperties testProperties)
+    {
+        // Cast the test properties into a typed interface for convenience.
+        MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+        String modeName = props.getNotApplicableAssertionMode();
+
+        if ("quiet".equals(modeName))
+        {
+            mode = Mode.Quiet;
+        }
+        else if ("warn".equals(modeName))
+        {
+            mode = Mode.Warn;
+        }
+        else
+        {
+            mode = Mode.Fail;
+        }
+    }
+
+    /**
+     * Applies the assertion.
+     *
+     * @return <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails.
+     */
+    public boolean apply()
+    {
+        switch (mode)
+        {
+        case Quiet:
+            return true;
+
+        case Warn:
+            console.warn("Warning: Not applicable assertion being ignored.");
+
+            return true;
+
+        case Fail:
+        default:
+            return false;
+        }
+    }
+}

Modified: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java?rev=619823&r1=619822&r2=619823&view=diff
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java (original)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java Fri Feb  8 02:09:37 2008
@@ -20,37 +20,56 @@
  */
 package org.apache.qpid.test.framework;
 
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
 /**
- * A Publisher is a {@link CircuitEnd} that represents the status of the publishing side of a test circuit. Its main
- * purpose is to provide assertions that can be applied to test the behaviour of the publishers.
+ * A Publisher represents the status of the publishing side of a test circuit. Its main purpose is to provide assertions
+ * that can be applied to test the behaviour of the publishers.
  *
  * <p/><table id="crc"><caption>CRC Card</caption>
  * <tr><th> Responsibilities
  * <tr><td> Provide assertion that the publishers received no exceptions.
- * <tr><td> Provide assertion that the publishers received a no consumers error code on every message.
- * <tr><td> Provide assertion that the publishers received a no route error code on every message.
  * </table>
+ *
+ * @todo There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ *       warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ *       I am tempted to go with the dropping/warning/error approach, that would imply that it makes sense to pull
+ *       the assertions back from AMQPPublisher to here.
  */
 public interface Publisher
 {
+    // Assertions that are meaningfull to AMQP and to JMS.
+
     /**
      * Provides an assertion that the publisher encountered no exceptions.
      *
+     * @param testProps The test configuration properties.
+     *
      * @return An assertion that the publisher encountered no exceptions.
      */
-    public Assertion noExceptionsAssertion();
+    public Assertion noExceptionsAssertion(ParsedProperties testProps);
+
+    // Assertions that are meaningfull only to AMQP.
 
     /**
-     * Provides an assertion that the publisher got a no consumers exception on every message.
+     * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
      *
-     * @return An assertion that the publisher got a no consumers exception on every message.
+     * @param testProps The test configuration properties.
+     *
+     * @return An assertion that the AMQP channel was forcibly closed by an error condition.
      */
-    public Assertion noConsumersAssertion();
+    public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+    // Assertions that are meaningfull only to Java/JMS.
 
     /**
-     * Provides an assertion that the publisher got a no rout exception on every message.
+     * Provides an assertion that the publisher got a given exception during the test.
      *
-     * @return An assertion that the publisher got a no rout exception on every message.
+     * @param testProps      The test configuration properties.
+     * @param exceptionClass The exception class to check for.
+     *
+     * @return An assertion that the publisher got a given exception during the test.
      */
-    public Assertion noRouteAssertion();
+    public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
 }
+

Modified: incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java?rev=619823&r1=619822&r2=619823&view=diff
==============================================================================
--- incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java (original)
+++ incubator/qpid/branches/thegreatmerge/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java Fri Feb  8 02:09:37 2008
@@ -20,6 +20,8 @@
  */
 package org.apache.qpid.test.framework;
 
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
 /**
  * A Receiver is a {@link CircuitEnd} that represents the status of the receiving side of a test circuit. Its main
  * purpose is to provide assertions that can be applied to check the behaviour of the receivers.
@@ -29,20 +31,62 @@
  * <tr><td> Provide assertion that the receivers received no exceptions.
  * <tr><td> Provide assertion that the receivers received all test messages sent to it.
  * </table>
+ *
+ * @todo There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ *       warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ *       I am tempted to go with the dropping/warning/error approach.
  */
 public interface Receiver
 {
+    // Assertions that are meaningfull to AMQP and to JMS.
+
     /**
      * Provides an assertion that the receivers encountered no exceptions.
      *
+     * @param testProps The test configuration properties.
+     *
      * @return An assertion that the receivers encountered no exceptions.
      */
-    public Assertion noExceptionsAssertion();
+    public Assertion noExceptionsAssertion(ParsedProperties testProps);
 
     /**
      * Provides an assertion that the receivers got all messages that were sent to it.
      *
+     * @param testProps The test configuration properties.
+     *
      * @return An assertion that the receivers got all messages that were sent to it.
      */
-    public Assertion allMessagesAssertion();
+    public Assertion allMessagesReceivedAssertion(ParsedProperties testProps);
+
+    /**
+     * Provides an assertion that the receivers got none of the messages that were sent to it.
+     *
+     * @param testProps The test configuration properties.
+     *
+     * @return An assertion that the receivers got none of the messages that were sent to it.
+     */
+    public Assertion noMessagesReceivedAssertion(ParsedProperties testProps);
+
+    // Assertions that are meaningfull only to AMQP.
+
+    /**
+     * Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+     *
+     * @param testProps The test configuration properties.
+     *
+     * @return An assertion that the AMQP channel was forcibly closed by an error condition.
+     */
+    public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+    // Assertions that are meaningfull only to Java/JMS.
+
+    /**
+     * Provides an assertion that the receiver got a given exception during the test.
+     *
+     * @param testProps The test configuration properties.
+     * @param exceptionClass The exception class to check for.
+     *
+     * @return An assertion that the receiver got a given exception during the test.
+     */
+    public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
 }