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/13 16:24:06 UTC

svn commit: r556011 [2/2] - in /incubator/qpid/branches/M2/java: perftests/src/main/java/org/apache/qpid/requestreply/ systests/src/main/java/org/apache/qpid/server/exchange/ systests/src/main/java/org/apache/qpid/test/framework/

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitImpl.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,384 @@
+/*
+ *
+ * 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 junit.framework.Assert;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.test.framework.MessageMonitor;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * <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 CircuitImpl implements Circuit
+{
+    /** Used to create unique destination names for each test. */
+    private static AtomicLong uniqueDestsId = new AtomicLong();
+
+    /** Holds the test configuration for the circuit. */
+    private ParsedProperties testProps;
+
+    /** Holds the publishing end of the circuit. */
+    private PublisherImpl publisher;
+
+    /** Holds the receiving end of the circuit. */
+    private ReceiverImpl receiver;
+
+    /** Holds the connection for the publishing end of the circuit. */
+    private Connection connection;
+
+    /** Holds the exception listener for the connection on the publishing end of the circuit. */
+    private ExceptionMonitor connectionExceptionMonitor;
+
+    /** Holds the exception listener for the session on the publishing end of the circuit. */
+    private ExceptionMonitor exceptionMonitor;
+
+    /**
+     * Creates a test circuit using the specified test parameters. The publisher, receiver, connection and
+     * connection monitor must already have been created, to assemble the circuit.
+     *
+     * @param testProps                  The test parameters.
+     * @param publisher                  The test publisher.
+     * @param receiver                   The test receiver.
+     * @param connection                 The connection.
+     * @param connectionExceptionMonitor The connection exception monitor.
+     */
+    protected CircuitImpl(ParsedProperties testProps, PublisherImpl publisher, ReceiverImpl receiver, Connection connection,
+        ExceptionMonitor connectionExceptionMonitor)
+    {
+        this.testProps = testProps;
+        this.publisher = publisher;
+        this.receiver = receiver;
+        this.connection = connection;
+        this.connectionExceptionMonitor = connectionExceptionMonitor;
+        this.exceptionMonitor = new ExceptionMonitor();
+
+        // Set this as the parent circuit on the publisher and receiver.
+        publisher.setCircuit(this);
+        receiver.setCircuit(this);
+    }
+
+    /**
+     * Creates a test circuit from the specified test parameters.
+     *
+     * @param testProps The test parameters.
+     *
+     * @return A connected and ready to start, test circuit.
+     */
+    public static Circuit createCircuit(ParsedProperties testProps)
+    {
+        // Create a standard publisher/receiver 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();
+
+            // Extract the standard test configuration parameters relevant to the connection.
+            String destinationSendRoot =
+                testProps.getProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME) + "_" + uniqueId;
+            String destinationReceiveRoot =
+                testProps.getProperty(MessagingTestConfigProperties.RECEIVE_DESTINATION_NAME_ROOT_PROPNAME) + "_" + uniqueId;
+            boolean createPublisherProducer =
+                testProps.getPropertyAsBoolean(MessagingTestConfigProperties.PUBLISHER_PRODUCER_BIND_PROPNAME);
+            boolean createPublisherConsumer =
+                testProps.getPropertyAsBoolean(MessagingTestConfigProperties.PUBLISHER_CONSUMER_BIND_PROPNAME);
+            boolean createReceiverProducer =
+                testProps.getPropertyAsBoolean(MessagingTestConfigProperties.RECEIVER_PRODUCER_BIND_PROPNAME);
+            boolean createReceiverConsumer =
+                testProps.getPropertyAsBoolean(MessagingTestConfigProperties.RECEIVER_CONSUMER_BIND_PROPNAME);
+
+            // Check which JMS flags and options are to be set.
+            int ackMode = testProps.getPropertyAsInteger(MessagingTestConfigProperties.ACK_MODE_PROPNAME);
+            boolean useTopics = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.PUBSUB_PROPNAME);
+            boolean transactional = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.TRANSACTED_PROPNAME);
+            boolean durableSubscription =
+                testProps.getPropertyAsBoolean(MessagingTestConfigProperties.DURABLE_SUBSCRIPTION_PROPNAME);
+
+            // Check if any Qpid/AMQP specific flags or options need to be set.
+            boolean immediate = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.IMMEDIATE_PROPNAME);
+            boolean mandatory = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.MANDATORY_PROPNAME);
+            boolean needsQpidOptions = immediate | mandatory;
+
+            /*log.debug("ackMode = " + ackMode);
+            log.debug("useTopics = " + useTopics);
+            log.debug("destinationSendRoot = " + destinationSendRoot);
+            log.debug("destinationReceiveRoot = " + destinationReceiveRoot);
+            log.debug("createPublisherProducer = " + createPublisherProducer);
+            log.debug("createPublisherConsumer = " + createPublisherConsumer);
+            log.debug("createReceiverProducer = " + createReceiverProducer);
+            log.debug("createReceiverConsumer = " + createReceiverConsumer);
+            log.debug("transactional = " + transactional);
+            log.debug("immediate = " + immediate);
+            log.debug("mandatory = " + mandatory);
+            log.debug("needsQpidOptions = " + needsQpidOptions);*/
+
+            // Create connection, sessions and producer/consumer pairs on each session.
+            Connection connection = TestUtils.createConnection(testProps);
+
+            // Add the connection exception listener to assert on exception conditions with.
+            ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+            connection.setExceptionListener(exceptionMonitor);
+
+            Session publisherSession = connection.createSession(transactional, ackMode);
+            Session receiverSession = connection.createSession(transactional, ackMode);
+
+            Destination publisherProducerDestination =
+                useTopics ? publisherSession.createTopic(destinationSendRoot)
+                          : publisherSession.createQueue(destinationSendRoot);
+
+            MessageProducer publisherProducer =
+                createPublisherProducer
+                ? (needsQpidOptions
+                    ? ((AMQSession) publisherSession).createProducer(publisherProducerDestination, mandatory, immediate)
+                    : publisherSession.createProducer(publisherProducerDestination)) : null;
+
+            MessageConsumer publisherConsumer =
+                createPublisherConsumer
+                ? publisherSession.createConsumer(publisherSession.createQueue(destinationReceiveRoot)) : null;
+
+            if (publisherConsumer != null)
+            {
+                publisherConsumer.setMessageListener(new MessageMonitor());
+            }
+
+            MessageProducer receiverProducer =
+                createReceiverProducer ? receiverSession.createProducer(receiverSession.createQueue(destinationReceiveRoot))
+                                       : null;
+
+            Destination receiverConsumerDestination =
+                useTopics ? receiverSession.createTopic(destinationSendRoot)
+                          : receiverSession.createQueue(destinationSendRoot);
+
+            MessageConsumer receiverConsumer =
+                createReceiverConsumer
+                ? ((durableSubscription && useTopics)
+                    ? receiverSession.createDurableSubscriber((Topic) receiverConsumerDestination, "testsub")
+                    : receiverSession.createConsumer(receiverConsumerDestination)) : null;
+
+            if (receiverConsumer != null)
+            {
+                receiverConsumer.setMessageListener(new MessageMonitor());
+            }
+
+            // Start listening for incoming messages.
+            connection.start();
+
+            // Package everything up.
+            PublisherImpl publisher = new PublisherImpl(publisherProducer, publisherConsumer, publisherSession);
+            ReceiverImpl receiver = new ReceiverImpl(receiverProducer, receiverConsumer, receiverSession);
+
+            return new CircuitImpl(testProps, publisher, receiver, connection, exceptionMonitor);
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("Could not create publisher/receiver pair due to a JMSException.", e);
+        }
+    }
+
+    /**
+     * Gets the interface on the publishing end of the circuit.
+     *
+     * @return The publishing end of the circuit.
+     */
+    public Publisher getPublisher()
+    {
+        return publisher;
+    }
+
+    /**
+     * Gets the interface on the receiving end of the circuit.
+     *
+     * @return The receiving end of the circuit.
+     */
+    public Receiver getReceiver()
+    {
+        return receiver;
+    }
+
+    /**
+     * Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+     * into a report, against which assertions may be checked.
+     */
+    public void check()
+    { }
+
+    /**
+     * Applied a list of assertions against the test circuit. The {@link #check()} method should be called before doing
+     * this, to ensure that the circuit has gathered its state into a report to assert against.
+     *
+     * @param assertions The list of assertions to apply.
+     * @return Any assertions that failed.
+     */
+    public List<Assertion> applyAssertions(List<Assertion> assertions)
+    {
+        return null;
+    }
+
+    /**
+     * Connects and starts the circuit. After this method is called the circuit is ready to send messages.
+     */
+    public void start()
+    { }
+
+    /**
+     * Closes the circuit. All associated resources are closed.
+     */
+    public void close()
+    {
+        try
+        {
+            publisher.close();
+            receiver.close();
+            connection.close();
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("Got JMSException during close.", e);
+        }
+    }
+
+    /**
+     * Sends a message on the test circuit. The exact nature of the message sent is controlled by the test parameters.
+     */
+    public void send()
+    {
+        boolean transactional = testProps.getPropertyAsBoolean(MessagingTestConfigProperties.TRANSACTED_PROPNAME);
+
+        // Send an immediate message through the publisher and ensure that it results in a JMSException.
+        try
+        {
+            getPublisher().send(createTestMessage(getPublisher()));
+
+            if (transactional)
+            {
+                getPublisher().getSession().commit();
+            }
+        }
+        catch (JMSException e)
+        {
+            exceptionMonitor.onException(e);
+        }
+    }
+
+    /**
+     * Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. The
+     * outline of the default test procedure is:
+     *
+     * <p/><pre>
+     * Start the circuit.
+     * Send test messages.
+     * Request a status report.
+     * Assert conditions on the publishing end of the circuit.
+     * Assert conditions on the receiving end of the circuit.
+     * Close the circuit.
+     * Pass with no failed assertions or fail with a list of failed assertions.
+     * </pre>
+     *
+     * @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)
+    {
+        // Start the test circuit.
+        start();
+
+        // Send the requested number of test messages.
+        for (int i = 0; i < numMessages; i++)
+        {
+            send();
+        }
+
+        // Inject a short pause to allow time for exceptions to come back asynchronously.
+        TestUtils.pause(100L);
+
+        // Request a status report.
+        check();
+
+        // Apply all of the requested assertions, keeping record of any that fail.
+        List<Assertion> failures = new LinkedList<Assertion>();
+
+        for (Assertion assertion : assertions)
+        {
+            if (!assertion.apply())
+            {
+                failures.add(assertion);
+            }
+        }
+
+        // Clean up the publisher/receiver/session/connections.
+        close();
+
+        // Return any failed assertions to the caller.
+        return failures;
+    }
+
+    /**
+     * Creates a message with the properties defined as per the test parameters.
+     *
+     * @param client The circuit end to create the message on.
+     *
+     * @return The test message.
+     *
+     * @throws JMSException Any JMSException occurring during creation of the message is allowed to fall through.
+     */
+    private Message createTestMessage(CircuitEnd client) throws JMSException
+    {
+        return client.getSession().createTextMessage("Hello");
+    }
+
+    /**
+     * Gets the exception monitor for the publishing ends connection.
+     *
+     * @return The exception monitor for the publishing ends connection.
+     */
+    public ExceptionMonitor getConnectionExceptionMonitor()
+    {
+        return connectionExceptionMonitor;
+    }
+
+    /**
+     * Gets the exception monitor for the publishing ends session.
+     *
+     * @return The exception monitor for the publishing ends session.
+     */
+    public ExceptionMonitor getExceptionMonitor()
+    {
+        return exceptionMonitor;
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ExceptionMonitor.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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 javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+* <tr><th> Responsibilities <th> Collaborations
+* <tr><td>
+* </table>
+*/
+public class ExceptionMonitor implements ExceptionListener
+{
+    List<JMSException> exceptions = new ArrayList<JMSException>();
+
+    public void onException(JMSException e)
+    {
+        exceptions.add(e);
+    }
+
+    public boolean assertNoExceptions()
+    {
+        return exceptions.isEmpty();
+    }
+
+    public boolean assertOneJMSException()
+    {
+        return exceptions.size() == 1;
+    }
+
+    public boolean assertOneJMSExceptionWithLinkedCause(Class aClass)
+    {
+        if (exceptions.size() == 1)
+        {
+            JMSException e = exceptions.get(0);
+
+            Exception linkedCause = e.getLinkedException();
+
+            if ((linkedCause != null) && aClass.isInstance(linkedCause))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Reports the number of exceptions held by this monitor.
+     *
+     * @return The number of exceptions held by this monitor.
+     */
+    public int size()
+    {
+        return exceptions.size();
+    }
+
+    public void reset()
+    {
+        exceptions = new ArrayList();
+    }
+
+    /**
+     * Provides a dump of the stack traces of all exceptions that this exception monitor was notified of. Mainly
+     * use for debugging/test failure reporting purposes.
+     *
+     * @return A string containing a dump of the stack traces of all exceptions.
+     */
+    public String toString()
+    {
+        String result = "ExceptionMonitor: holds " + exceptions.size() + " exceptions.\n\n";
+
+        for (JMSException ex : exceptions)
+        {
+            result += getStackTrace(ex) + "\n";
+        }
+
+        return result;
+    }
+
+    /**
+     * Prints an exception stack trace into a string.
+     *
+     * @param t The throwable to get the stack trace from.
+     *
+     * @return A string containing the throwables stack trace.
+     */
+    public static String getStackTrace(Throwable t)
+    {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw, true);
+        t.printStackTrace(pw);
+        pw.flush();
+        sw.flush();
+
+        return sw.toString();
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,136 @@
+/*
+ *
+ * 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 junit.framework.TestCase;
+
+import org.apache.log4j.NDC;
+
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * FrameworkBaseCase provides a starting point for writing test cases against the test framework. Its main purpose is
+ * to provide some convenience methods for testing.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create and clean up in-vm brokers on every test case.
+ * <tr><td> Produce lists of assertions from assertion creation calls.
+ * <tr><td> Produce JUnit failures from assertion failures.
+ * <tr><td> Convert failed assertions to error messages.
+ * </table>
+ */
+public class FrameworkBaseCase extends TestCase
+{
+    /**
+     * Creates a list of assertions.
+     *
+     * @param asserts The assertions to compile in a list.
+     *
+     * @return A list of assertions.
+     */
+    protected List<Assertion> assertionList(Assertion... asserts)
+    {
+        List<Assertion> result = new ArrayList<Assertion>();
+
+        for (Assertion assertion : asserts)
+        {
+            result.add(assertion);
+        }
+
+        return result;
+    }
+
+    /**
+     * Generates a JUnit assertion exception (failure) if any assertions are passed into this method, also concatenating
+     * all of the error messages in the assertions together to form an error message to diagnose the test failure with.
+     *
+     * @param asserts The list of failed assertions.
+     */
+    protected void assertNoFailures(List<Assertion> asserts)
+    {
+        // Check if there are no assertion failures, and return without doing anything if so.
+        if ((asserts == null) || asserts.isEmpty())
+        {
+            return;
+        }
+
+        // Compile all of the assertion failure messages together.
+        String errorMessage = assertionsToString(asserts);
+
+        // Fail with the error message from all of the assertions.
+        fail(errorMessage);
+    }
+
+    /**
+     * Converts a list of failed assertions into an error message.
+     *
+     * @param asserts The failed assertions.
+     *
+     * @return The error message.
+     */
+    protected String assertionsToString(List<Assertion> asserts)
+    {
+        String errorMessage = "";
+
+        for (Assertion assertion : asserts)
+        {
+            errorMessage += assertion.toString() + "\n";
+        }
+
+        return errorMessage;
+    }
+
+    /**
+     * Ensures that the in-vm broker is created and initialized.
+     *
+     * @throws Exception Any exceptions allowed to fall through and fail the test.
+     */
+    protected void setUp() throws Exception
+    {
+        NDC.push(getName());
+
+        // Ensure that the in-vm broker is created.
+        TransportConnection.createVMBroker(1);
+    }
+
+    /**
+     * Ensures that the in-vm broker is cleaned up after each test run.
+     */
+    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();
+        }
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessageMonitor.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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 javax.jms.Message;
+import javax.jms.MessageListener;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class MessageMonitor implements MessageListener
+{
+    public void onMessage(Message message)
+    { }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MessagingTestConfigProperties.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,309 @@
+/*
+ *
+ * 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.jms.Session;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+/**
+ * MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology,
+ * and test parameters for running a messaging test over that topology. A Properties object holding some of these
+ * properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour.
+ *
+ * <p/>A complete list of the parameters, default values and comments on their usage is provided here:
+ *
+ * <p/><table><caption>Parameters</caption>
+ * <tr><th> Parameter        <th> Default  <th> Comments
+ * <tr><td> messageSize      <td> 0        <td> Message size in bytes. Not including any headers.
+ * <tr><td> destinationName  <td> ping     <td> The root name to use to generate destination names to ping.
+ * <tr><td> persistent       <td> false    <td> Determines whether peristent delivery is used.
+ * <tr><td> transacted       <td> false    <td> Determines whether messages are sent/received in transactions.
+ * <tr><td> broker           <td> tcp://localhost:5672 <td> Determines the broker to connect to.
+ * <tr><td> virtualHost      <td> test     <td> Determines the virtual host to send all ping over.
+ * <tr><td> rate             <td> 0        <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
+ * <tr><td> verbose          <td> false    <td> The verbose flag for debugging. Prints to console on every message.
+ * <tr><td> pubsub           <td> false    <td> Whether to ping topics or queues. Uses p2p by default.
+ * <tr><td> username         <td> guest    <td> The username to access the broker with.
+ * <tr><td> password         <td> guest    <td> The password to access the broker with.
+ * <tr><td> selector         <td> null     <td> Not used. Defines a message selector to filter pings with.
+ * <tr><td> destinationCount <td> 1        <td> The number of receivers listening to the pings.
+ * <tr><td> timeout          <td> 30000    <td> In milliseconds. The timeout to stop waiting for replies.
+ * <tr><td> commitBatchSize  <td> 1        <td> The number of messages per transaction in transactional mode.
+ * <tr><td> uniqueDests      <td> true     <td> Whether each receiver only listens to one ping destination or all.
+ * <tr><td> durableDests     <td> false    <td> Whether or not durable destinations are used.
+ * <tr><td> ackMode          <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
+ *                                               0 - SESSION_TRANSACTED
+ *                                               1 - AUTO_ACKNOWLEDGE
+ *                                               2 - CLIENT_ACKNOWLEDGE
+ *                                               3 - DUPS_OK_ACKNOWLEDGE
+ *                                               257 - NO_ACKNOWLEDGE
+ *                                               258 - PRE_ACKNOWLEDGE
+ * <tr><td> maxPending       <td> 0        <td> The maximum size in bytes, of messages sent but not yet received.
+ *                                              Limits the volume of messages currently buffered on the client
+ *                                              or broker. Can help scale test clients by limiting amount of buffered
+ *                                              data to avoid out of memory errors.
+ * </table>
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide the names and defaults of all test parameters.
+ * </table>
+ */
+public class MessagingTestConfigProperties
+{
+    // ====================== Connection Properties ==================================
+
+    /** Holds the name of the default connection configuration. */
+    public static final String CONNECTION_NAME = "broker";
+
+    /** Holds the name of the property to get the initial context factory name from. */
+    public static final String INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial";
+
+    /** Defines the class to use as the initial context factory by default. */
+    public static final String INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
+
+    /** Holds the name of the default connection factory configuration property. */
+    public static final String CONNECTION_PROPNAME = "connectionfactory.broker";
+
+    /** Defeins the default connection configuration. */
+    public static final String CONNECTION_DEFAULT = "amqp://guest:guest@clientid/?brokerlist='vm://:1'";
+
+    /** Holds the name of the property to get the test broker url from. */
+    public static final String BROKER_PROPNAME = "qpid.test.broker";
+
+    /** Holds the default broker url for the test. */
+    public static final String BROKER_DEFAULT = "vm://:1";
+
+    /** Holds the name of the property to get the test broker virtual path. */
+    public static final String VIRTUAL_HOST_PROPNAME = "virtualHost";
+
+    /** Holds the default virtual path for the test. */
+    public static final String VIRTUAL_HOST_DEFAULT = "";
+
+    /** Holds the name of the property to get the broker access username from. */
+    public static final String USERNAME_PROPNAME = "username";
+
+    /** Holds the default broker log on username. */
+    public static final String USERNAME_DEFAULT = "guest";
+
+    /** Holds the name of the property to get the broker access password from. */
+    public static final String PASSWORD_PROPNAME = "password";
+
+    /** Holds the default broker log on password. */
+    public static final String PASSWORD_DEFAULT = "guest";
+
+    // ====================== Messaging Topology Properties ==========================
+
+    /** Holds the name of the property to get the bind publisher procuder flag from. */
+    public static final String PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind";
+
+    /** Holds the default value of the publisher producer flag. */
+    public static final boolean PUBLISHER_PRODUCER_BIND_DEFAULT = true;
+
+    /** Holds the name of the property to get the bind publisher procuder flag from. */
+    public static final String PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind";
+
+    /** Holds the default value of the publisher consumer flag. */
+    public static final boolean PUBLISHER_CONSUMER_BIND_DEFAULT = false;
+
+    /** Holds the name of the property to get the bind receiver procuder flag from. */
+    public static final String RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind";
+
+    /** Holds the default value of the receiver producer flag. */
+    public static final boolean RECEIVER_PRODUCER_BIND_DEFAULT = false;
+
+    /** Holds the name of the property to get the bind receiver procuder flag from. */
+    public static final String RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind";
+
+    /** Holds the default value of the receiver consumer flag. */
+    public static final boolean RECEIVER_CONSUMER_BIND_DEFAULT = true;
+
+    /** Holds the name of the property to get the destination name root from. */
+    public static final String SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot";
+
+    /** Holds the root of the name of the default destination to send to. */
+    public static final String SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo";
+
+    /** Holds the name of the property to get the destination name root from. */
+    public static final String RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot";
+
+    /** Holds the root of the name of the default destination to send to. */
+    public static final String RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom";
+
+    /** Holds the name of the proeprty to get the destination count from. */
+    public static final String DESTINATION_COUNT_PROPNAME = "destinationCount";
+
+    /** Defines the default number of destinations to ping. */
+    public static final int DESTINATION_COUNT_DEFAULT = 1;
+
+    /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */
+    public static final String PUBSUB_PROPNAME = "pubsub";
+
+    /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */
+    public static final boolean PUBSUB_DEFAULT = false;
+
+    // ======================  JMS Options and Flags =================================
+
+    /** Holds the name of the property to get the test delivery mode from. */
+    public static final String PERSISTENT_MODE_PROPNAME = "persistent";
+
+    /** Holds the message delivery mode to use for the test. */
+    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";
+
+    /** Holds the transactional mode to use for the test. */
+    public static final boolean TRANSACTED_DEFAULT = false;
+
+    /** Holds the name of the property to set the no local flag from. */
+    public static final String NO_LOCAL_PROPNAME = "noLocal";
+
+    /** Defines the default value of the no local flag to use when consuming messages. */
+    public static final boolean NO_LOCAL_DEFAULT = false;
+
+    /** Holds the name of the property to get the message acknowledgement mode from. */
+    public static final String ACK_MODE_PROPNAME = "ackMode";
+
+    /** Defines the default message acknowledgement mode. */
+    public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
+
+    /** Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. */
+    public static final String DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription";
+
+    /** Defines the default value of the durable subscriptions flag. */
+    public static final boolean DURABLE_SUBSCRIPTION_DEFAULT = false;
+
+    // ======================  Qpid Options and Flags ================================
+
+    /** Holds the name of the property to set the exclusive flag from. */
+    public static final String EXCLUSIVE_PROPNAME = "exclusive";
+
+    /** Defines the default value of the exclusive flag to use when consuming messages. */
+    public static final boolean EXCLUSIVE_DEFAULT = false;
+
+    /** Holds the name of the property to set the immediate flag from. */
+    public static final String IMMEDIATE_PROPNAME = "immediate";
+
+    /** Defines the default value of the immediate flag to use when sending messages. */
+    public static final boolean IMMEDIATE_DEFAULT = false;
+
+    /** Holds the name of the property to set the mandatory flag from. */
+    public static final String MANDATORY_PROPNAME = "mandatory";
+
+    /** Defines the default value of the mandatory flag to use when sending messages. */
+    public static final boolean MANDATORY_DEFAULT = false;
+
+    /** Holds the name of the property to get the durable destinations flag from. */
+    public static final String DURABLE_DESTS_PROPNAME = "durableDests";
+
+    /** 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. */
+    public static final String PREFECTH_PROPNAME = "prefetch";
+
+    /** Defines the default prefetch size to use when consuming messages. */
+    public static final int PREFETCH_DEFAULT = 100;
+
+    // ======================  Common Test Parameters ================================
+
+    /** Holds the name of the property to get the test message size from. */
+    public static final String MESSAGE_SIZE_PROPNAME = "messageSize";
+
+    /** Used to set up a default message size. */
+    public static final int MESSAGE_SIZE_DEAFULT = 0;
+
+    /** Holds the name of the property to get the message rate from. */
+    public static final String RATE_PROPNAME = "rate";
+
+    /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */
+    public static final int RATE_DEFAULT = 0;
+
+    /** Holds the name of the proeprty to get the. */
+    public static final String SELECTOR_PROPNAME = "selector";
+
+    /** Holds the default message selector. */
+    public static final String SELECTOR_DEFAULT = "";
+
+    /** Holds the name of the property to get the waiting timeout for response messages. */
+    public static final String TIMEOUT_PROPNAME = "timeout";
+
+    /** Default time to wait before assuming that a ping has timed out. */
+    public static final long TIMEOUT_DEFAULT = 30000;
+
+    /** Holds the name of the property to get the commit batch size from. */
+    public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
+
+    /** Defines the default number of pings to send in each transaction when running transactionally. */
+    public static final int TX_BATCH_SIZE_DEFAULT = 1;
+
+    /** Holds the name of the property to set the maximum amount of pending message data for a producer to hold. */
+    public static final String MAX_PENDING_PROPNAME = "maxPending";
+
+    /** 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 verbose mode proeprty from. */
+    public static final String VERBOSE_PROPNAME = "verbose";
+
+    /** Holds the default verbose mode. */
+    public static final boolean VERBOSE_DEFAULT = false;
+
+    /** Holds the default configuration properties. */
+    public static ParsedProperties defaults = new ParsedProperties();
+
+    static
+    {
+        defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
+        defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_DEFAULT);
+        defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+        defaults.setPropertyIfNull(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);
+        defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_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(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
+        defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
+        defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+        defaults.setPropertyIfNull(PREFECTH_PROPNAME, PREFETCH_DEFAULT);
+        defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
+        defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
+        defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
+        defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MultiProducerConsumerPairImpl.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MultiProducerConsumerPairImpl.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MultiProducerConsumerPairImpl.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/MultiProducerConsumerPairImpl.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,82 @@
+/*
+ *
+ * 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 javax.jms.*;
+
+/**
+ * Multiple producers and consumers made to look like a single producer and consumer. All methods repeated accross
+ * all producers and consumers.
+ */
+public class MultiProducerConsumerPairImpl implements CircuitEnd
+{
+
+    /**
+     * Gets the message producer at this circuit end point.
+     *
+     * @return The message producer at with this circuit end point.
+     */
+    public MessageProducer getProducer()
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Gets the message consumer at this circuit end point.
+     *
+     * @return The message consumer at this circuit end point.
+     */
+    public MessageConsumer getConsumer()
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Send the specified message over the producer at this end point.
+     *
+     * @param message The message to send.
+     * @throws javax.jms.JMSException Any JMS exception occuring during the send is allowed to fall through.
+     */
+    public void send(Message message) throws JMSException
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Gets the JMS Session associated with this circuit end point.
+     *
+     * @return The JMS Session associated with this circuit end point.
+     */
+    public Session getSession()
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+
+    /**
+     * Closes the message producers and consumers and the sessions, associated with this circuit end point.
+     *
+     * @throws javax.jms.JMSException Any JMSExceptions occurring during the close are allowed to fall through.
+     */
+    public void close() throws JMSException
+    {
+        throw new RuntimeException("Not implemented.");
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Publisher.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 Publisher is a {@link CircuitEnd} that represents one end of a test circuit. Its main purpose is to
+ * provide assertions that can be applied to test the behaviour of the publisher.
+ */
+public interface Publisher extends CircuitEnd
+{
+    /**
+     * Provides an assertion that the publisher encountered no exceptions.
+     *
+     * @return An assertion that the publisher encountered no exceptions.
+     */
+    public Assertion noExceptionsAssertion();
+
+    /**
+     * Provides an assertion that the publisher got a no consumers exception on every message.
+     *
+     * @return An assertion that the publisher got a no consumers exception on every message.
+     */
+    public Assertion noConsumersAssertion();
+
+    /**
+     * Provides an assertion that the publisher got a no rout exception on every message.
+     *
+     * @return An assertion that the publisher got a no rout exception on every message.
+     */
+    public Assertion noRouteAssertion();
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/PublisherImpl.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/PublisherImpl.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/PublisherImpl.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/PublisherImpl.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,153 @@
+/*
+ *
+ * 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.client.AMQNoConsumersException;
+import org.apache.qpid.client.AMQNoRouteException;
+
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class PublisherImpl extends CircuitEndBase implements Publisher
+{
+    /** Holds a reference to the containing circuit. */
+    private CircuitImpl circuit;
+
+    /**
+     * Creates a circuit end point on the specified producer, consumer and session.
+     *
+     * @param producer The message producer for the circuit end point.
+     * @param consumer The message consumer for the circuit end point.
+     * @param session  The session for the circuit end point.
+     */
+    public PublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session)
+    {
+        super(producer, consumer, session);
+    }
+
+    /**
+     * Provides an assertion that the publisher encountered no exceptions.
+     *
+     * @return An assertion that the publisher encountered no exceptions.
+     */
+    public Assertion noExceptionsAssertion()
+    {
+        return new AssertionBase()
+            {
+                public boolean apply()
+                {
+                    boolean passed = true;
+                    ExceptionMonitor sessionExceptionMonitor = circuit.getExceptionMonitor();
+                    ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+                    if (!connectionExceptionMonitor.assertNoExceptions())
+                    {
+                        passed = false;
+                        addError("Was expecting no exceptions.\n");
+                        addError("Got the following exceptions on the connection, "
+                            + circuit.getConnectionExceptionMonitor());
+                    }
+
+                    if (!sessionExceptionMonitor.assertNoExceptions())
+                    {
+                        passed = false;
+                        addError("Was expecting no exceptions.\n");
+                        addError("Got the following exceptions on the producer, " + circuit.getExceptionMonitor());
+                    }
+
+                    return passed;
+                }
+            };
+    }
+
+    /**
+     * Provides an assertion that the publisher got a no consumers exception on every message.
+     *
+     * @return An assertion that the publisher got a no consumers exception on every message.
+     */
+    public Assertion noConsumersAssertion()
+    {
+        return new AssertionBase()
+            {
+                public boolean apply()
+                {
+                    boolean passed = true;
+                    ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+                    if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoConsumersException.class))
+                    {
+                        addError("Was expecting linked exception type " + AMQNoConsumersException.class.getName()
+                            + " on the connection.\n");
+                        addError((connectionExceptionMonitor.size() > 0)
+                            ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+                            : "Got no exceptions on the connection.");
+                    }
+
+                    return passed;
+                }
+            };
+    }
+
+    /**
+     * Provides an assertion that the publisher got a no rout exception on every message.
+     *
+     * @return An assertion that the publisher got a no rout exception on every message.
+     */
+    public Assertion noRouteAssertion()
+    {
+        return new AssertionBase()
+            {
+                public boolean apply()
+                {
+                    boolean passed = true;
+                    ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+                    if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoRouteException.class))
+                    {
+                        addError("Was expecting linked exception type " + AMQNoRouteException.class.getName()
+                            + " on the connection.\n");
+                        addError((connectionExceptionMonitor.size() > 0)
+                            ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+                            : "Got no exceptions on the connection.");
+                    }
+
+                    return passed;
+                }
+            };
+    }
+
+    /**
+     * Sets the contianing circuit.
+     *
+     * @param circuit The containing circuit.
+     */
+    public void setCircuit(CircuitImpl circuit)
+    {
+        this.circuit = circuit;
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/Receiver.java Fri Jul 13 07:24:03 2007
@@ -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;
+
+/**
+ * A Receiver is a {@link CircuitEnd} that represents one end of a test circuit. Its main purpose is to
+ * provide assertions that can be applied to test the behaviour of the receiver.
+ */
+public interface Receiver extends CircuitEnd
+{
+    /**
+     * Provides an assertion that the receiver encountered no exceptions.
+     *
+     * @return An assertion that the receiver encountered no exceptions.
+     */
+    public Assertion noExceptionsAssertion();
+
+    /**
+     * Provides an assertion that the receiver got all messages that were sent to it.
+     *
+     * @return An assertion that the receiver got all messages that were sent to it.
+     */
+    public Assertion allMessagesAssertion();
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/ReceiverImpl.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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 javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class ReceiverImpl extends CircuitEndBase implements Receiver
+{
+    /** Holds a reference to the containing circuit. */
+    private CircuitImpl circuit;
+
+    /**
+     * Creates a circuit end point on the specified producer, consumer and session.
+     *
+     * @param producer The message producer for the circuit end point.
+     * @param consumer The message consumer for the circuit end point.
+     * @param session  The session for the circuit end point.
+     */
+    public ReceiverImpl(MessageProducer producer, MessageConsumer consumer, Session session)
+    {
+        super(producer, consumer, session);
+    }
+
+    /**
+     * Provides an assertion that the receiver encountered no exceptions.
+     *
+     * @return An assertion that the receiver encountered no exceptions.
+     */
+    public Assertion noExceptionsAssertion()
+    {
+        return null;
+    }
+
+    /**
+     * Provides an assertion that the receiver got all messages that were sent to it.
+     *
+     * @return An assertion that the receiver got all messages that were sent to it.
+     */
+    public Assertion allMessagesAssertion()
+    {
+        return null;
+    }
+
+    /**
+     * Sets the contianing circuit.
+     *
+     * @param circuit The containing circuit.
+     */
+    public void setCircuit(CircuitImpl circuit)
+    {
+        this.circuit = circuit;
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/TestUtils.java Fri Jul 13 07:24:03 2007
@@ -0,0 +1,108 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
+
+import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class TestUtils
+{
+    /**
+     * Establishes a JMS connection using a properties file and qpids built in JNDI implementation. This is a simple
+     * convenience method for code that does anticipate handling connection failures. All exceptions that indicate
+     * that the connection has failed, are wrapped as rutime exceptions, preumably handled by a top level failure
+     * handler.
+     *
+     * @param messagingProps Connection properties as defined in {@link MessagingTestConfigProperties}.
+     *
+     * @return A JMS conneciton.
+     */
+    public static Connection createConnection(ParsedProperties messagingProps)
+    {
+        try
+        {
+            // Extract the configured connection properties from the test configuration.
+            String conUsername = messagingProps.getProperty(USERNAME_PROPNAME);
+            String conPassword = messagingProps.getProperty(PASSWORD_PROPNAME);
+            String virtualHost = messagingProps.getProperty(VIRTUAL_HOST_PROPNAME);
+            String brokerUrl = messagingProps.getProperty(BROKER_PROPNAME);
+
+            // Set up the broker connection url.
+            String connectionString =
+                "amqp://" + conUsername + ":" + conPassword + "/" + ((virtualHost != null) ? virtualHost : "")
+                + "?brokerlist='" + brokerUrl + "'";
+
+            // messagingProps.setProperty(CONNECTION_PROPNAME, connectionString);
+
+            Context ctx = new InitialContext(messagingProps);
+
+            ConnectionFactory cf = (ConnectionFactory) ctx.lookup(CONNECTION_NAME);
+            Connection connection = cf.createConnection();
+
+            return connection;
+        }
+        catch (NamingException e)
+        {
+            throw new RuntimeException("Got JNDI NamingException whilst looking up the connection factory.", e);
+        }
+        catch (JMSException e)
+        {
+            throw new RuntimeException("Could not establish connection due to JMSException.", e);
+        }
+    }
+
+    /**
+     * Pauses for the specified length of time. In the event of failing to pause for at least that length of time
+     * due to interuption of the thread, a RutimeException is raised to indicate the failure. The interupted status
+     * of the thread is restores in that case. This method should only be used when it is expected that the pause
+     * will be succesfull, for example in test code that relies on inejecting a pause.
+     *
+     * @param t The minimum time to pause for in milliseconds.
+     */
+    public static void pause(long t)
+    {
+        try
+        {
+            Thread.sleep(t);
+        }
+        catch (InterruptedException e)
+        {
+            // Restore the interrupted status
+            Thread.currentThread().interrupt();
+
+            throw new RuntimeException("Failed to generate the requested pause length.", e);
+        }
+    }
+}

Added: incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/package.html
URL: http://svn.apache.org/viewvc/incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/package.html?view=auto&rev=556011
==============================================================================
--- incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/package.html (added)
+++ incubator/qpid/branches/M2/java/systests/src/main/java/org/apache/qpid/test/framework/package.html Fri Jul 13 07:24:03 2007
@@ -0,0 +1,22 @@
+<html>
+<body>
+<p/>A framework for testing Qpid, built around a standard 'test circuit' design. The idea behind this framework is the
+use of a test circuit which is configured by a set of test parameters, that may be projected onto a topology of
+test nodes, with tests scripted to run over test circuits, making as few assumptions as possible about the underlying
+topology. The standardization of the design, whilst limiting in some respectes, allows a large variety of test 
+scenarios to be written with minimal amounts of coding.
+
+<p/>The standard consruction block for a test, is a test circuit. This consists of a publisher, and a receiver. The
+publisher and receiver may reside on the same machine, or may be distributed. Will use a standard set of properties to
+define the desired circuit topology.
+
+<p/>Tests are always to be controlled from the publishing side only. The receiving end of the circuit is to be exposed
+to the test code through an interface, that abstracts as much as possible the receiving end of the test. The interface
+exposes a set of 'assertions' that may be applied to the receiving end of the test circuit.
+
+<p/>In the case where the receiving end of the circuit resides on the same JVM, the assertions will call the receivers
+code locally. Where the receiving end is distributed accross one or more machines, the assertions will be applied to a
+test report gethered from all of the receivers. Test code will be written to the assertions making as few assumptions
+as possible about the exact test topology.
+</body>
+</html>
\ No newline at end of file