From 67dd56aa9421204983c92e664b0e86fbf0b2e3e2 Mon Sep 17 00:00:00 2001 From: Robert Greig Date: Fri, 4 May 2007 14:27:53 +0000 Subject: First two test cases completed. Still to do pub/sub. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2@535254 13f79535-47bb-0310-9956-ffa450edef68 --- .../interop/coordinator/CoordinatingTestCase.java | 53 ++++++++++- .../qpid/interop/coordinator/Coordinator.java | 12 +-- .../interop/coordinator/InvitingTestDecorator.java | 4 +- .../qpid/interop/coordinator/OptOutTestCase.java | 13 +++ .../interop/coordinator/TestClientDetails.java | 2 +- .../testcases/CoordinatingTestCase1DummyRun.java | 66 +++++++++++++ .../testcases/CoordinatingTestCase2BasicP2P.java | 30 +++++- .../interop/testclient/InteropClientTestCase.java | 4 +- .../apache/qpid/interop/testclient/TestClient.java | 103 +++++++++++++++------ .../testclient/testcases/TestCase1DummyRun.java | 2 + .../testclient/testcases/TestCase2BasicP2P.java | 94 +++++++++++++++++-- .../org/apache/qpid/util/ConversationFactory.java | 95 ++++++++++++++++++- 12 files changed, 422 insertions(+), 56 deletions(-) create mode 100644 java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase1DummyRun.java (limited to 'java/integrationtests/src') diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/CoordinatingTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/CoordinatingTestCase.java index 01d4874c4e..fd0cccf147 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/CoordinatingTestCase.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/CoordinatingTestCase.java @@ -22,6 +22,7 @@ package org.apache.qpid.interop.coordinator; import java.util.Collection; +import java.util.Map; import java.util.Properties; import java.util.concurrent.LinkedBlockingQueue; @@ -29,6 +30,8 @@ import javax.jms.*; import junit.framework.TestCase; +import org.apache.log4j.Logger; + import org.apache.qpid.util.ConversationFactory; /** @@ -67,6 +70,9 @@ import org.apache.qpid.util.ConversationFactory; */ public abstract class CoordinatingTestCase extends TestCase { + /** Used for debugging. */ + private static final Logger log = Logger.getLogger(CoordinatingTestCase.class); + /** Holds the contact details for the sending test client. */ TestClientDetails sender; @@ -93,6 +99,8 @@ public abstract class CoordinatingTestCase extends TestCase */ public void setSender(TestClientDetails sender) { + log.debug("public void setSender(TestClientDetails sender = " + sender + "): called"); + this.sender = sender; } @@ -103,6 +111,8 @@ public abstract class CoordinatingTestCase extends TestCase */ public void setReceiver(TestClientDetails receiver) { + log.debug("public void setReceiver(TestClientDetails receiver = " + receiver + "): called"); + this.receiver = receiver; } @@ -126,6 +136,17 @@ public abstract class CoordinatingTestCase extends TestCase return receiver; } + /** + * Should provide a translation from the junit method name of a test to its test case name as defined in the + * interop testing specification. For example the method "testP2P" might map onto the interop test case name + * "TC2_BasicP2P". + * + * @param methodName The name of the JUnit test method. + * + * @return The name of the corresponding interop test case. + */ + public abstract String getTestCaseNameForTestMethod(String methodName); + /** * Accepts the conversation factory over which to hold the test coordinating conversation. * @@ -147,8 +168,10 @@ public abstract class CoordinatingTestCase extends TestCase * * @throws JMSException All underlying JMSExceptions are allowed to fall through. */ - protected Message[] sequenceTest(Properties testProperties) throws JMSException + protected Message[] sequenceTest(Map testProperties) throws JMSException { + log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called"); + Session session = conversationFactory.getSession(); Destination senderControlTopic = session.createTopic(sender.privateControlKey); Destination receiverControlTopic = session.createTopic(receiver.privateControlKey); @@ -158,6 +181,7 @@ public abstract class CoordinatingTestCase extends TestCase // Assign the sender role to the sending test client. Message assignSender = conversationFactory.getSession().createMessage(); + setPropertiesOnMessage(assignSender, testProperties); assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); assignSender.setStringProperty("ROLE", "SENDER"); @@ -165,6 +189,7 @@ public abstract class CoordinatingTestCase extends TestCase // Assign the receiver role the receiving client. Message assignReceiver = session.createMessage(); + setPropertiesOnMessage(assignReceiver, testProperties); assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE"); assignReceiver.setStringProperty("ROLE", "RECEIVER"); @@ -183,6 +208,13 @@ public abstract class CoordinatingTestCase extends TestCase // Wait for the test sender to return its report. Message senderReport = senderConversation.receive(); + try + { + Thread.sleep(500); + } + catch (InterruptedException e) + { } + // Ask the receiver for its report. Message statusRequest = session.createMessage(); statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST"); @@ -194,4 +226,23 @@ public abstract class CoordinatingTestCase extends TestCase return new Message[] { senderReport, receiverReport }; } + + /** + * Sets properties of different types on a JMS Message. + * + * @param message The message to set properties on. + * @param properties The property name/value pairs to set. + * + * @throws JMSException All underlying JMSExceptions are allowed to fall through. + */ + public void setPropertiesOnMessage(Message message, Map properties) throws JMSException + { + for (Map.Entry entry : properties.entrySet()) + { + String name = entry.getKey(); + Object value = entry.getValue(); + + message.setObjectProperty(name, value); + } + } } diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java index 3469090369..71ea85f8ed 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/Coordinator.java @@ -31,12 +31,9 @@ import junit.framework.TestSuite; import org.apache.log4j.Logger; +import org.apache.qpid.interop.coordinator.testcases.CoordinatingTestCase1DummyRun; import org.apache.qpid.interop.coordinator.testcases.CoordinatingTestCase2BasicP2P; -import org.apache.qpid.interop.testclient.InteropClientTestCase; import org.apache.qpid.interop.testclient.TestClient; -import org.apache.qpid.interop.testclient.testcases.TestCase1DummyRun; -import org.apache.qpid.interop.testclient.testcases.TestCase2BasicP2P; -import org.apache.qpid.util.ClasspathScanner; import org.apache.qpid.util.CommandLineParser; import org.apache.qpid.util.ConversationFactory; import org.apache.qpid.util.PrettyPrintingUtils; @@ -128,7 +125,8 @@ public class Coordinator extends TestRunnerImprovedErrorHandling new ArrayList>(); // ClasspathScanner.getMatches(CoordinatingTestCase.class, "^Test.*", true); // Hard code the test classes till the classpath scanner is fixed. - Collections.addAll(testCaseClasses, new Class[] { CoordinatingTestCase2BasicP2P.class }); + Collections.addAll(testCaseClasses, + new Class[] { CoordinatingTestCase1DummyRun.class, CoordinatingTestCase2BasicP2P.class }); // Check that some test classes were actually found. if ((testCaseClasses == null) || testCaseClasses.isEmpty()) @@ -190,6 +188,8 @@ public class Coordinator extends TestRunnerImprovedErrorHandling conversationFactory = new ConversationFactory(connection, responseQueue, LinkedBlockingQueue.class); ConversationFactory.Conversation conversation = conversationFactory.startConversation(); + connection.start(); + // Broadcast the compulsory invitation to find out what clients are available to test. Message invite = session.createMessage(); invite.setStringProperty("CONTROL_TYPE", "INVITE"); @@ -198,7 +198,7 @@ public class Coordinator extends TestRunnerImprovedErrorHandling conversation.send(controlTopic, invite); // Wait for a short time, to give test clients an opportunity to reply to the invitation. - Collection enlists = conversation.receiveAll(0, 10000); + Collection enlists = conversation.receiveAll(0, 3000); enlistedClients = extractEnlists(enlists); diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java index f6991ef0ef..afdad70001 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/InvitingTestDecorator.java @@ -115,12 +115,12 @@ public class InvitingTestDecorator extends WrappedSuiteTestDecorator ConversationFactory.Conversation conversation = conversationFactory.startConversation(); invite.setStringProperty("CONTROL_TYPE", "INVITE"); - invite.setStringProperty("TEST_NAME", coordTest.getName()); + invite.setStringProperty("TEST_NAME", coordTest.getTestCaseNameForTestMethod(coordTest.getName())); conversation.send(controlTopic, invite); // Wait for a short time, to give test clients an opportunity to reply to the invitation. - Collection replies = conversation.receiveAll(allClients.size(), 10000); + Collection replies = conversation.receiveAll(allClients.size(), 3000); enlists = Coordinator.extractEnlists(replies); } catch (JMSException e) diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java index 27e2c42a9a..42a382a898 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/OptOutTestCase.java @@ -49,4 +49,17 @@ public class OptOutTestCase extends CoordinatingTestCase { Assert.fail("One of " + getSender() + " and " + getReceiver() + " opted out of the test."); } + + /** + * Should provide a translation from the junit method name of a test to its test case name as defined in the + * interop testing specification. For example the method "testP2P" might map onto the interop test case name + * "TC2_BasicP2P". + * + * @param methodName The name of the JUnit test method. + * @return The name of the corresponding interop test case. + */ + public String getTestCaseNameForTestMethod(String methodName) + { + return "OptOutTest"; + } } diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java index 80abd4d4c9..c4a9d39cd8 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/TestClientDetails.java @@ -82,6 +82,6 @@ public class TestClientDetails */ public String toString() { - return "clientName = " + clientName + ", privateControlKey = " + privateControlKey; + return "TestClientDetails: [ clientName = " + clientName + ", privateControlKey = " + privateControlKey + " ]"; } } diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase1DummyRun.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase1DummyRun.java new file mode 100644 index 0000000000..654c46be8a --- /dev/null +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase1DummyRun.java @@ -0,0 +1,66 @@ +package org.apache.qpid.interop.coordinator.testcases; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.jms.Message; + +import junit.framework.Assert; + +import org.apache.log4j.Logger; + +import org.apache.qpid.interop.coordinator.CoordinatingTestCase; + +/** + *

+ *
CRC Card
Responsibilities Collaborations + *
Exercises the interop testing framework without actually sending any test messages. + * {@link org.apache.qpid.interop.coordinator.CoordinatingTestCase} + *
+ */ +public class CoordinatingTestCase1DummyRun extends CoordinatingTestCase +{ + /** Used for debugging. */ + private static final Logger log = Logger.getLogger(CoordinatingTestCase2BasicP2P.class); + + /** + * Creates a new coordinating test case with the specified name. + * + * @param name The test case name. + */ + public CoordinatingTestCase1DummyRun(String name) + { + super(name); + } + + /** + * Performs the basic P2P test case, "Test Case 2" in the specification. + */ + public void testDummyRun() throws Exception + { + log.debug("public void testDummyRun(): called"); + + Map testConfig = new HashMap(); + testConfig.put("TEST_NAME", "TC1_DummyRun"); + + Message[] reports = sequenceTest(testConfig); + + // Compare sender and receiver reports. + Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length); + } + + /** + * Should provide a translation from the junit method name of a test to its test case name as defined in the + * interop testing specification. For example the method "testP2P" might map onto the interop test case name + * "TC2_BasicP2P". + * + * @param methodName The name of the JUnit test method. + * @return The name of the corresponding interop test case. + */ + public String getTestCaseNameForTestMethod(String methodName) + { + return "TC1_DummyRun"; + } + +} diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase2BasicP2P.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase2BasicP2P.java index 4fb9729c4a..904ac1361a 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase2BasicP2P.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/coordinator/testcases/CoordinatingTestCase2BasicP2P.java @@ -1,11 +1,15 @@ package org.apache.qpid.interop.coordinator.testcases; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import javax.jms.Message; import junit.framework.Assert; +import org.apache.log4j.Logger; + import org.apache.qpid.interop.coordinator.CoordinatingTestCase; /** @@ -16,6 +20,9 @@ import org.apache.qpid.interop.coordinator.CoordinatingTestCase; */ public class CoordinatingTestCase2BasicP2P extends CoordinatingTestCase { + /** Used for debugging. */ + private static final Logger log = Logger.getLogger(CoordinatingTestCase2BasicP2P.class); + /** * Creates a new coordinating test case with the specified name. * @@ -31,10 +38,12 @@ public class CoordinatingTestCase2BasicP2P extends CoordinatingTestCase */ public void testBasicP2P() throws Exception { - Properties testConfig = new Properties(); - testConfig.setProperty("TEST_CASE", "TC2_BasicP2P"); - testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue"); - testConfig.setProperty("P2P_NUM_MESSAGES", "50"); + log.debug("public void testBasicP2P(): called"); + + Map testConfig = new HashMap(); + testConfig.put("TEST_NAME", "TC2_BasicP2P"); + testConfig.put("P2P_QUEUE_AND_KEY_NAME", "tc2queue"); + testConfig.put("P2P_NUM_MESSAGES", 50); Message[] reports = sequenceTest(testConfig); @@ -45,4 +54,17 @@ public class CoordinatingTestCase2BasicP2P extends CoordinatingTestCase Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent); Assert.assertEquals("Sender and receiver messages sent did not match up.", messagesSent, messagesReceived); } + + /** + * Should provide a translation from the junit method name of a test to its test case name as defined in the + * interop testing specification. For example the method "testP2P" might map onto the interop test case name + * "TC2_BasicP2P". + * + * @param methodName The name of the JUnit test method. + * @return The name of the corresponding interop test case. + */ + public String getTestCaseNameForTestMethod(String methodName) + { + return "TC2_BasicP2P"; + } } diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java index 57726285f9..9f769822de 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/InteropClientTestCase.java @@ -79,8 +79,10 @@ public interface InteropClientTestCase extends MessageListener /** * Performs the test case actions. + * + * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through. */ - public void start(); + public void start() throws JMSException; /** * Gets a report on the actions performed by the test case in its assigned role. diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java index 6d7ab9c978..a128b63da5 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/TestClient.java @@ -21,10 +21,7 @@ package org.apache.qpid.interop.testclient; import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; +import java.util.*; import javax.jms.*; import javax.naming.Context; @@ -33,6 +30,8 @@ import javax.naming.NamingException; import org.apache.log4j.Logger; +import org.apache.qpid.interop.testclient.testcases.TestCase1DummyRun; +import org.apache.qpid.interop.testclient.testcases.TestCase2BasicP2P; import org.apache.qpid.util.ClasspathScanner; import org.apache.qpid.util.CommandLineParser; import org.apache.qpid.util.PropertiesUtils; @@ -61,41 +60,53 @@ public class TestClient implements MessageListener { private static Logger log = Logger.getLogger(TestClient.class); + public static final String CONNECTION_PROPERTY = "connectionfactory.broker"; + public static final String CONNECTION_NAME = "broker"; + public static final String CLIENT_NAME = "java"; + public static final String DEFAULT_CONNECTION_PROPS_RESOURCE = "org/apache/qpid/interop/connection.properties"; + /** Holds the URL of the broker to run the tests on. */ - String brokerUrl; + public static String brokerUrl; /** Holds the virtual host to run the tests on. If null, then the default virtual host is used. */ - String virtualHost; + public static String virtualHost; /** Holds all the test cases loaded from the classpath. */ Map testCases = new HashMap(); InteropClientTestCase currentTestCase; - public static final String CONNECTION_PROPERTY = "connectionfactory.broker"; - public static final String CONNECTION_NAME = "broker"; - public static final String CLIENT_NAME = "java"; - public static final String DEFAULT_CONNECTION_PROPS_RESOURCE = "org/apache/qpid/interop/connection.properties"; - private MessageProducer producer; private Session session; - public TestClient(String brokerUrl, String virtualHost) + private String clientName = CLIENT_NAME; + + /** + * Creates a new interop test client, listenting to the specified broker and virtual host, with the specified + * client identifying name. + * + * @param brokerUrl The url of the broker to connect to. + * @param virtualHost The virtual host to conect to. + * @param clientName The client name to use. + */ + public TestClient(String brokerUrl, String virtualHost, String clientName) { log.debug("public TestClient(String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost - + "): called"); + + ", String clientName = " + clientName + "): called"); // Retain the connection parameters. this.brokerUrl = brokerUrl; this.virtualHost = virtualHost; + this.clientName = clientName; } /** * The entry point for the interop test coordinator. This client accepts the following command line arguments: * *

- *
-b The broker URL. Mandatory. - *
-h The virtual host. Optional. + *
-b The broker URL. Optional. + *
-h The virtual host. Optional. + *
-n The test client name. Optional. *
name=value Trailing argument define name/value pairs. Added to system properties. Optional. *
* @@ -105,11 +116,13 @@ public class TestClient implements MessageListener { // Use the command line parser to evaluate the command line. CommandLineParser commandLine = - new CommandLineParser(new String[][] - { - { "b", "The broker URL.", "broker", "false" }, - { "h", "The virtual host to use.", "virtual host", "false" } - }); + new CommandLineParser( + new String[][] + { + { "b", "The broker URL.", "broker", "false" }, + { "h", "The virtual host to use.", "virtual host", "false" }, + { "n", "The test client name.", "name", "false" } + }); // Capture the command line arguments or display errors and correct usage and then exit. Properties options = null; @@ -128,13 +141,14 @@ public class TestClient implements MessageListener // Extract the command line options. String brokerUrl = options.getProperty("b"); String virtualHost = options.getProperty("h"); + String clientName = options.getProperty("n"); // Add all the trailing command line options (name=value pairs) to system properties. Tests may pick up // overridden values from there. commandLine.addCommandLineToSysProperties(); // Create a test client and start it running. - TestClient client = new TestClient(brokerUrl, virtualHost); + TestClient client = new TestClient(brokerUrl, virtualHost, (clientName == null) ? CLIENT_NAME : clientName); try { @@ -147,13 +161,21 @@ public class TestClient implements MessageListener } } + /** + * Starts the interop test client running. This causes it to start listening for incoming test invites. + * + * @throws JMSException Any underlying JMSExceptions are allowed to fall through. + */ private void start() throws JMSException { log.debug("private void start(): called"); // Use a class path scanner to find all the interop test case implementations. Collection> testCaseClasses = - ClasspathScanner.getMatches(InteropClientTestCase.class, "^TestCase.*", true); + new ArrayList>(); + // ClasspathScanner.getMatches(InteropClientTestCase.class, "^TestCase.*", true); + // Hard code the test classes till the classpath scanner is fixed. + Collections.addAll(testCaseClasses, new Class[] { TestCase1DummyRun.class, TestCase2BasicP2P.class }); // Create all the test case implementations and index them by the test names. for (Class nextClass : testCaseClasses) @@ -181,9 +203,12 @@ public class TestClient implements MessageListener session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Set this up to listen for control messages. - MessageConsumer consumer = session.createConsumer(session.createTopic("iop.control." + CLIENT_NAME)); + MessageConsumer consumer = session.createConsumer(session.createTopic("iop.control." + clientName)); consumer.setMessageListener(this); + MessageConsumer consumer2 = session.createConsumer(session.createTopic("iop.control")); + consumer2.setMessageListener(this); + // Create a producer to send replies with. producer = session.createProducer(null); @@ -209,13 +234,13 @@ public class TestClient implements MessageListener public static Connection createConnection(String connectionPropsResource, String brokerUrl, String virtualHost) { log.debug("public static Connection createConnection(String connectionPropsResource = " + connectionPropsResource - + ", String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost + "): called"); + + ", String brokerUrl = " + brokerUrl + ", String virtualHost = " + virtualHost + "): called"); try { Properties connectionProps = PropertiesUtils.getProperties(TestClient.class.getClassLoader().getResourceAsStream( - connectionPropsResource)); + connectionPropsResource)); if (brokerUrl != null) { @@ -270,6 +295,8 @@ public class TestClient implements MessageListener if (testCaseName != null) { + log.debug("Got an invite to test: " + testCaseName); + // Check if the requested test case is available. InteropClientTestCase testCase = testCases.get(testCaseName); @@ -282,6 +309,8 @@ public class TestClient implements MessageListener } else { + log.debug("Got a compulsory invite."); + enlist = true; } @@ -290,8 +319,8 @@ public class TestClient implements MessageListener // Reply with the client name in an Enlist message. Message enlistMessage = session.createMessage(); enlistMessage.setStringProperty("CONTROL_TYPE", "ENLIST"); - enlistMessage.setStringProperty("CLIENT_NAME", CLIENT_NAME); - enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + CLIENT_NAME); + enlistMessage.setStringProperty("CLIENT_NAME", clientName); + enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName); enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID()); producer.send(message.getJMSReplyTo(), enlistMessage); @@ -300,7 +329,10 @@ public class TestClient implements MessageListener else if ("ASSIGN_ROLE".equals(controlType)) { // Assign the role to the current test case. - String roleName = message.getStringProperty(""); + String roleName = message.getStringProperty("ROLE"); + + log.debug("Got a role assignment to role: " + roleName); + InteropClientTestCase.Roles role = Enum.valueOf(InteropClientTestCase.Roles.class, roleName); currentTestCase.assignRole(role, message); @@ -316,9 +348,15 @@ public class TestClient implements MessageListener { if ("START".equals(controlType)) { + log.debug("Got a start notification."); + // Start the current test case. currentTestCase.start(); } + else + { + log.debug("Got a status request."); + } // Generate the report from the test case and reply with it as a Report message. Message reportMessage = currentTestCase.getReport(session); @@ -327,10 +365,17 @@ public class TestClient implements MessageListener producer.send(message.getJMSReplyTo(), reportMessage); } + else if ("TERMINATE".equals(controlType)) + { + System.out.println("Received termination instruction from coordinator."); + + // Is a cleaner shutdown needed? + System.exit(0); + } else { // Log a warning about this but otherwise ignore it. - log.warn("Got an unknown control message: " + message); + log.warn("Got an unknown control message, controlType = " + controlType + ", message = " + message); } } catch (JMSException e) diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java index aa31a59b06..874f86daa9 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase1DummyRun.java @@ -84,6 +84,8 @@ public class TestCase1DummyRun implements InteropClientTestCase public void onMessage(Message message) { + log.debug("public void onMessage(Message message = " + message + "): called"); + // Ignore any messages. } } diff --git a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java index c3c05d8fd9..ea62b46451 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/interop/testclient/testcases/TestCase2BasicP2P.java @@ -20,11 +20,12 @@ */ package org.apache.qpid.interop.testclient.testcases; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Session; +import javax.jms.*; + +import org.apache.log4j.Logger; import org.apache.qpid.interop.testclient.InteropClientTestCase; +import org.apache.qpid.interop.testclient.TestClient; /** * Implements test case 2, basic P2P. Sends/received a specified number of messages to a specified route on the @@ -41,6 +42,30 @@ import org.apache.qpid.interop.testclient.InteropClientTestCase; */ public class TestCase2BasicP2P implements InteropClientTestCase { + /** Used for debugging. */ + private static final Logger log = Logger.getLogger(TestCase2BasicP2P.class); + + /** Holds the count of test messages received. */ + private int messageCount; + + /** The role to be played by the test. */ + private Roles role; + + /** The number of test messages to send. */ + private int numMessages; + + /** The routing key to send them to on the default direct exchange. */ + private Destination sendDestination; + + /** The connection to send the test messages on. */ + private Connection connection; + + /** The session to send the test messages on. */ + private Session session; + + /** The producer to send the test messages with. */ + MessageProducer producer; + /** * Should provide the name of the test case that this class implements. The exact names are defined in the * interop testing spec. @@ -49,6 +74,8 @@ public class TestCase2BasicP2P implements InteropClientTestCase */ public String getName() { + log.debug("public String getName(): called"); + return "TC2_BasicP2P"; } @@ -63,6 +90,8 @@ public class TestCase2BasicP2P implements InteropClientTestCase */ public boolean acceptInvite(Message inviteMessage) throws JMSException { + log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called"); + // All invites are acceptable. return true; } @@ -79,27 +108,65 @@ public class TestCase2BasicP2P implements InteropClientTestCase */ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException { + log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage + + "): called"); + + // Reset the message count for a new test. + messageCount = 0; + // Take note of the role to be played. + this.role = role; + + // Create a new connection to pass the test messages on. + connection = + TestClient.createConnection(TestClient.DEFAULT_CONNECTION_PROPS_RESOURCE, TestClient.brokerUrl, + TestClient.virtualHost); + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Extract and retain the test parameters. + numMessages = assignRoleMessage.getIntProperty("P2P_NUM_MESSAGES"); + sendDestination = session.createQueue(assignRoleMessage.getStringProperty("P2P_QUEUE_AND_KEY_NAME")); - // Create a new connection to pass the test messages on. + log.debug("numMessages = " + numMessages); + log.debug("sendDestination = " + sendDestination); + log.debug("role = " + role); - // Check if the sender role is being assigned, and set up a message producer if so. + switch (role) { - } + // Check if the sender role is being assigned, and set up a message producer if so. + case SENDER: + producer = session.createProducer(sendDestination); + break; + // Otherwise the receiver role is being assigned, so set this up to listen for messages. - { + case RECEIVER: + MessageConsumer consumer = session.createConsumer(sendDestination); + consumer.setMessageListener(this); + break; } + + connection.start(); } /** * Performs the test case actions. */ - public void start() + public void start() throws JMSException { + log.debug("public void start(): called"); + // Check that the sender role is being performed. + if (role.equals(Roles.SENDER)) { + Message testMessage = session.createTextMessage("test"); + + for (int i = 0; i < numMessages; i++) + { + producer.send(testMessage); + + // Increment the message count. + messageCount++; + } } } @@ -114,11 +181,17 @@ public class TestCase2BasicP2P implements InteropClientTestCase */ public Message getReport(Session session) throws JMSException { + log.debug("public Message getReport(Session session): called"); + // Close the test connection. + connection.close(); // Generate a report message containing the count of the number of messages passed. + Message report = session.createMessage(); + report.setStringProperty("CONTROL_TYPE", "REPORT"); + report.setIntProperty("MESSAGE_COUNT", messageCount); - return null; + return report; } /** @@ -128,6 +201,9 @@ public class TestCase2BasicP2P implements InteropClientTestCase */ public void onMessage(Message message) { + log.debug("public void onMessage(Message message = " + message + "): called"); + // Increment the message count. + messageCount++; } } diff --git a/java/integrationtests/src/main/java/org/apache/qpid/util/ConversationFactory.java b/java/integrationtests/src/main/java/org/apache/qpid/util/ConversationFactory.java index 204369b5b9..4ca2fe8ff5 100644 --- a/java/integrationtests/src/main/java/org/apache/qpid/util/ConversationFactory.java +++ b/java/integrationtests/src/main/java/org/apache/qpid/util/ConversationFactory.java @@ -23,10 +23,13 @@ package org.apache.qpid.util; import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.jms.*; +import org.apache.log4j.Logger; + /** * A conversation helper, uses a message correlation id pattern to match up sent and received messages as a conversation * over JMS messaging. Incoming message traffic is divided up by correlation id. Each id has a queue (behaviour dependant @@ -96,6 +99,9 @@ import javax.jms.*; */ public class ConversationFactory { + /** Used for debugging. */ + private static final Logger log = Logger.getLogger(ConversationFactory.class); + /** Holds a map from correlation id's to queues. */ private Map> idsToQueues = new HashMap>(); @@ -152,6 +158,9 @@ public class ConversationFactory public ConversationFactory(Connection connection, Destination receiveDestination, Class queueClass) throws JMSException { + log.debug("public ConversationFactory(Connection connection, Destination receiveDestination = " + receiveDestination + + ", Class queueClass = " + queueClass + "): called"); + this.connection = connection; this.queueClass = queueClass; @@ -173,6 +182,8 @@ public class ConversationFactory */ public Conversation startConversation() { + log.debug("public Conversation startConversation(): called"); + Conversation conversation = new Conversation(); conversation.conversationId = conversationIdGenerator.getAndIncrement(); @@ -199,6 +210,8 @@ public class ConversationFactory */ public Collection emptyDeadLetterBox() { + log.debug("public Collection emptyDeadLetterBox(): called"); + Collection result = new ArrayList(); deadLetterBox.drainTo(result); @@ -246,6 +259,9 @@ public class ConversationFactory */ public void send(Destination sendDestination, Message message) throws JMSException { + log.debug("public void send(Destination sendDestination = " + sendDestination + ", Message message = " + message + + "): called"); + // Conversation settings = threadLocals.get(); // long conversationId = conversationId; message.setJMSCorrelationID(Long.toString(conversationId)); @@ -287,6 +303,8 @@ public class ConversationFactory */ public Message receive() throws JMSException { + log.debug("public Message receive(): called"); + // Conversation settings = threadLocals.get(); // long conversationId = settings.conversationId; @@ -313,7 +331,8 @@ public class ConversationFactory /** * Gets many messages in an ongoing conversation. If a limit is specified, then once that many messages are * received they will be returned. If a timeout is specified, then all messages up to the limit, received within - * that timespan will be returned. + * that timespan will be returned. At least one of the message count or timeout should be set to a value of + * 1 or greater. * * @param num The number of messages to receive, or all if this is less than 1. * @param timeout The timeout in milliseconds to receive the messages in, or forever if this is less than 1. @@ -324,12 +343,78 @@ public class ConversationFactory */ public Collection receiveAll(int num, long timeout) throws JMSException { + log.debug("public Collection receiveAll(int num = " + num + ", long timeout = " + timeout + + "): called"); + + // Check that a timeout or message count was set. + if ((num < 1) && (timeout < 1)) + { + throw new IllegalArgumentException("At least one of message count (num) or timeout must be set."); + } + + // Ensure that the reply queue for this conversation exists. + initQueueForId(conversationId); + BlockingQueue queue = idsToQueues.get(conversationId); + + // Used to collect the received messages in. Collection result = new ArrayList(); - for (int i = 0; i < num; i++) + // Used to indicate when the timeout or message count has expired. + boolean receiveMore = true; + + int messageCount = 0; + + // Receive messages until the timeout or message count expires. + do { - result.add(receive()); + try + { + Message next = null; + + // Try to receive the message with a timeout if one has been set. + if (timeout > 0) + { + next = queue.poll(timeout, TimeUnit.MILLISECONDS); + + // Check if the timeout expired, and stop receiving if so. + if (next == null) + { + receiveMore = false; + } + } + // Receive the message without a timeout. + else + { + next = queue.take(); + } + + // Increment the message count if a message was received. + messageCount += (next != null) ? 1 : 0; + + // Check if all the requested messages were received, and stop receiving if so. + if ((num > 0) && (messageCount >= num)) + { + receiveMore = false; + } + + // Keep the reply-to destination to send replies to. + sendDestination = (next != null) ? next.getJMSReplyTo() : sendDestination; + + if (next != null) + { + result.add(next); + } + } + catch (InterruptedException e) + { + // Restore the threads interrupted status. + Thread.currentThread().interrupt(); + + // Stop receiving but return the messages received so far. + receiveMore = false; + } } + while (receiveMore); return result; } @@ -340,6 +425,8 @@ public class ConversationFactory */ public void end() { + log.debug("public void end(): called"); + // Ensure that the thread local for the current thread is cleaned up. // Conversation settings = threadLocals.get(); // long conversationId = settings.conversationId; @@ -366,6 +453,8 @@ public class ConversationFactory */ public void onMessage(Message message) { + log.debug("public void onMessage(Message message = " + message + "): called"); + try { Long conversationId = Long.parseLong(message.getJMSCorrelationID()); -- cgit v1.2.1