Author: rupertlssmith
Date: Tue Jun 5 08:02:09 2007
New Revision: 544508
URL: http://svn.apache.org/viewvc?view=rev&rev=544508
Log:
Interop tests ported to .Net
Added:
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/InteropClientTestCase.cs
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase1DummyRun.cs
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase2BasicP2P.cs
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase3BasicPubSub.cs
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestClient.cs
Modified:
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
Modified:
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
URL:
http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj?view=diff&rev=544508&r1=544507&r2=544508
==============================================================================
---
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
(original)
+++
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
Tue Jun 5 08:02:09 2007
@@ -47,6 +47,11 @@
<Compile Include="BrokerDetails\BrokerDetailsTest.cs" />
<Compile Include="Channel\ChannelMessageCreationTests.cs" />
<Compile Include="Channel\ChannelQueueTest.cs" />
+ <Compile Include="interop\InteropClientTestCase.cs" />
+ <Compile Include="interop\TestCases\TestCase1DummyRun.cs" />
+ <Compile Include="interop\TestCases\TestCase2BasicP2P.cs" />
+ <Compile Include="interop\TestCases\TestCase3BasicPubSub.cs" />
+ <Compile Include="interop\TestClient.cs" />
<Compile Include="Messages\MessageFactoryRegistryTests.cs" />
<Compile Include="connection\ConnectionTest.cs" />
<Compile Include="connection\SslConnectionTest.cs" />
Added:
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/InteropClientTestCase.cs
URL:
http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/InteropClientTestCase.cs?view=auto&rev=544508
==============================================================================
---
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/InteropClientTestCase.cs
(added)
+++
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/InteropClientTestCase.cs
Tue Jun 5 08:02:09 2007
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Qpid.Messaging;
+
+namespace Qpid.Client.Tests.interop
+{
+ /// <summary> Defines the possible test case roles that an interop test
case can take on. </summary>
+ public enum Roles { SENDER, RECEIVER };
+
+ /// <summary>
+ /// InteropClientTestCase provides an interface that classes implementing
test cases from the interop testing spec
+ ///
(http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification)
should implement.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Perform test case actions.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ interface InteropClientTestCase
+ {
+ /// <summary>
+ /// Should provide the name of the test case that this class
implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ ///
+ /// <returns> The name of the test case that this implements.
</returns>
+ string GetName();
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is
acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject.
</param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt>
to reject it. </returns>
+ ///
+ /// @throws JMSException Any JMSException resulting from reading the
message are allowed to fall through.
+ bool AcceptInvite(IMessage inviteMessage);
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test
parameters are fully specified in the
+ /// assignment message. When this method return the test case will be
ready to execute.
+ /// </summary>
+ ///
+ /// <param name="role"> The role to be played; sender or
receiver. </param>
+ /// <param name="assignRoleMessage"> The role assingment message,
contains the full test parameters. </param>
+ void AssignRole(Roles role, IMessage assignRoleMessage);
+
+ /// <summary>
+ /// Performs the test case actions.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its
assigned role.
+ /// </summary>
+ ///
+ /// <param name="session"> The session to create the report message
in. </param>
+ ///
+ /// <returns> The report message. </returns>
+ IMessage GetReport(IChannel channel);
+ }
+}
Added:
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase1DummyRun.cs
URL:
http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase1DummyRun.cs?view=auto&rev=544508
==============================================================================
---
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase1DummyRun.cs
(added)
+++
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase1DummyRun.cs
Tue Jun 5 08:02:09 2007
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using log4net;
+using Qpid.Messaging;
+
+namespace Qpid.Client.Tests.interop.TestCases
+{
+ /// <summary>
+ /// Implements tet case 1, dummy run. This test case sends no test
messages, it exists to confirm that the test harness
+ /// is interacting with the coordinator correctly.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Perform test case actions.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public class TestCase1DummyRun : InteropClientTestCase
+ {
+ private static ILog log =
LogManager.GetLogger(typeof(TestCase1DummyRun));
+
+ public String GetName()
+ {
+ log.Debug("public String getName(): called");
+
+ return "TC1_DummyRun";
+ }
+
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Debug("public boolean acceptInvite(Message inviteMessage):
called");
+
+ // Test parameters don't matter, accept all invites.
+ return true;
+ }
+
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ log.Debug("public void assignRole(Roles role, Message
assignRoleMessage): called");
+
+ // Do nothing, both roles are the same.
+ }
+
+ public void Start()
+ {
+ log.Debug("public void start(): called");
+
+ // Do nothing.
+ }
+
+ public IMessage GetReport(IChannel channel)
+ {
+ log.Debug("public Message getReport(Session session): called");
+
+ // Generate a dummy report, the coordinator expects a report but
doesn't care what it is.
+ return channel.CreateTextMessage("Dummy Run, Ok.");
+ }
+
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void onMessage(Message message = " + message +
"): called");
+
+ // Ignore any messages.
+ }
+ }
+}
Added:
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase2BasicP2P.cs
URL:
http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase2BasicP2P.cs?view=auto&rev=544508
==============================================================================
---
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase2BasicP2P.cs
(added)
+++
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase2BasicP2P.cs
Tue Jun 5 08:02:09 2007
@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using log4net;
+using Qpid.Messaging;
+
+namespace Qpid.Client.Tests.interop.TestCases
+{
+ /// <summary>
+ /// Implements test case 2, basic P2P. Sends/receives a specified number
of messages to a specified route on the
+ /// default direct exchange. Produces reports on the actual number of
messages sent/received.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Send required number of test messages.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public class TestCase2BasicP2P : InteropClientTestCase
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log =
LogManager.GetLogger(typeof(TestCase2BasicP2P));
+
+ /// <summary> Holds the count of test messages received. </summary>
+ private int messageCount;
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The routing key to send them to on the default direct
exchange. </summary>
+ private string sendDestination;
+
+ /// <summary> The connection to send the test messages on. </summary>
+ private IConnection connection;
+
+ /// <summary> The session to send the test messages on. </summary>
+ private IChannel channel;
+
+ /// <summary> The producer to send the test messages with. </summary>
+ private IMessagePublisher publisher;
+
+ /// <summary>
+ /// Should provide the name of the test case that this class
implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ ///
+ /// <returns> The name of the test case that this implements.
</returns>
+ public String GetName()
+ {
+ log.Debug("public String GetName(): called");
+
+ return "TC2_BasicP2P";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is
acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject.
</param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt>
to reject it. </returns>
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Debug("public boolean AcceptInvite(Message inviteMessage = " +
inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test
parameters are fully specified in the
+ /// assignment message. When this method return the test case will be
ready to execute.
+ /// </summary>
+ ///
+ /// <param name="role"> The role to be played; sender or
receiver. </param>
+ /// <param name="assignRoleMessage"> The role assingment message,
contains the full test parameters. </param>
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ 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.brokerUrl,
TestClient.virtualHost);
+ channel = connection.CreateChannel(false,
AcknowledgeMode.AutoAcknowledge);
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.Headers.GetInt("P2P_NUM_MESSAGES");
+ string queueAndKeyName =
assignRoleMessage.Headers.GetString("P2P_QUEUE_AND_KEY_NAME");
+ channel.DeclareQueue(queueAndKeyName, false, true, true);
+ channel.Bind(queueAndKeyName, ExchangeNameDefaults.DIRECT,
queueAndKeyName);
+ sendDestination = queueAndKeyName;
+
+ log.Debug("numMessages = " + numMessages);
+ log.Debug("sendDestination = " + sendDestination);
+ log.Debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a
message producer if so.
+ case Roles.SENDER:
+ publisher = channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.DIRECT)
+ .WithRoutingKey(sendDestination)
+ .Create();
+ break;
+
+ // Otherwise the receiver role is being assigned, so set this up
to listen for messages.
+ case Roles.RECEIVER:
+ IMessageConsumer consumer =
channel.CreateConsumerBuilder(sendDestination).Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+
+ break;
+ }
+
+ connection.Start();
+ }
+
+ /// <summary> Performs the test case actions. </summary>
+ public void Start()
+ {
+ log.Debug("public void start(): called");
+
+ // Check that the sender role is being performed.
+ if (role == Roles.SENDER)
+ {
+ IMessage testMessage = channel.CreateTextMessage("test");
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ publisher.Send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its
assigned role.
+ /// </summary>
+ ///
+ /// <param name="session"> The session to create the report message
in. </param>
+ ///
+ /// <returns> The report message. </returns>
+ public IMessage GetReport(IChannel channel)
+ {
+ log.Debug("public Message GetReport(IChannel channel): called");
+
+ // Close the test connection.
+ connection.Stop();
+
+ // Generate a report message containing the count of the number of
messages passed.
+ IMessage report = channel.CreateMessage();
+ report.Headers.SetString("CONTROL_TYPE", "REPORT");
+ report.Headers.SetInt("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /// <summary>
+ /// Counts incoming test messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming test message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void OnMessage(IMessage message = " + message +
"): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+}
Added:
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase3BasicPubSub.cs
URL:
http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase3BasicPubSub.cs?view=auto&rev=544508
==============================================================================
---
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase3BasicPubSub.cs
(added)
+++
incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestCases/TestCase3BasicPubSub.cs
Tue Jun 5 08:02:09 2007
@@ -0,0 +1,215 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using log4net;
+using Qpid.Messaging;
+
+namespace Qpid.Client.Tests.interop.TestCases
+{
+ /// <summary>
+ /// Implements test case 3, basic pub/sub. Sends/received a specified
number of messages to a specified route on the
+ /// default topic exchange, using the specified number of receiver
connections. Produces reports on the actual number of
+ /// messages sent/received.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Send required number of test messages using pub/sub.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public class TestCase3BasicPubSub : InteropClientTestCase
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log =
LogManager.GetLogger(typeof(TestCase3BasicPubSub));
+
+ /// <summary> Holds the count of test messages received. </summary>
+ private int messageCount;
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The number of receiver connection to use. </summary>
+ private int numReceivers;
+
+ /// <summary> The routing key to send them to on the default direct
exchange. </summary>
+ private string sendDestination;
+
+ /// <summary> The connections to send/receive the test messages on.
</summary>
+ private IConnection[] connection;
+
+ /// <summary> The sessions to send/receive the test messages on.
</summary>
+ private IChannel[] channel;
+
+ /// <summary> The producer to send the test messages with. </summary>
+ IMessagePublisher publisher;
+
+ /// <summary>
+ /// Should provide the name of the test case that this class
implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ ///
+ /// <returns> The name of the test case that this implements.
</returns>
+ public String GetName()
+ {
+ log.Debug("public String GetName(): called");
+
+ return "TC3_BasicPubSub";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is
acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject.
</param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt>
to reject it. </returns>
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Debug("public boolean AcceptInvite(IMessage inviteMessage = "
+ inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test
parameters are fully specified in the
+ /// assignment message. When this method return the test case will be
ready to execute.
+ /// </summary>
+ ///
+ /// <param name="role"> The role to be played; sender or
receiver. </param>
+ /// <param name="assignRoleMessage"> The role assingment message,
contains the full test parameters. </param>
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ log.Debug("public void assignRole(Roles role = " + role + ",
IMessage assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages =
assignRoleMessage.Headers.GetInt("PUBSUB_NUM_MESSAGES");
+ numReceivers =
assignRoleMessage.Headers.GetInt("PUBSUB_NUM_RECEIVERS");
+ string sendKey = assignRoleMessage.Headers.GetString("PUBSUB_KEY");
+ sendDestination = sendKey;
+
+ log.Debug("numMessages = " + numMessages);
+ log.Debug("numReceivers = " + numReceivers);
+ log.Debug("sendKey = " + sendKey);
+ log.Debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single
message producer if so.
+ case Roles.SENDER:
+ // Create a new connection to pass the test messages on.
+ connection = new IConnection[1];
+ channel = new IChannel[1];
+
+ connection[0] =
+ TestClient.CreateConnection(TestClient.brokerUrl,
TestClient.virtualHost);
+ channel[0] = connection[0].CreateChannel(false,
AcknowledgeMode.AutoAcknowledge);
+
+ // Extract and retain the test parameters.
+ publisher = channel[0].CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(sendDestination)
+ .Create();
+ break;
+
+ // Otherwise the receiver role is being assigned, so set this up
to listen for messages on the required number
+ // of receiver connections.
+ case Roles.RECEIVER:
+ // Create the required number of receiver connections.
+ connection = new IConnection[numReceivers];
+ channel = new IChannel[numReceivers];
+
+ for (int i = 0; i < numReceivers; i++)
+ {
+ connection[i] =
+ TestClient.CreateConnection(TestClient.brokerUrl,
TestClient.virtualHost);
+ channel[i] = connection[i].CreateChannel(false,
AcknowledgeMode.AutoAcknowledge);
+
+ IMessageConsumer consumer =
channel[i].CreateConsumerBuilder(sendDestination).Create();
+ consumer.OnMessage += new
MessageReceivedDelegate(OnMessage);
+ }
+
+ break;
+ }
+
+ // Start all the connection dispatcher threads running.
+ foreach (IConnection con in connection)
+ {
+ con.Start();
+ }
+ }
+
+ /// <summary>
+ /// Performs the test case actions.
+ /// </summary>
+ public void Start()
+ {
+ log.Debug("public void Start(): called");
+
+ // Check that the sender role is being performed.
+ if (role == Roles.SENDER)
+ {
+ IMessage testMessage = channel[0].CreateTextMessage("test");
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ publisher.Send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its
assigned role.
+ /// </summary>
+ ///
+ /// <param name="session"> The session to create the report message
in. </param>
+ ///
+ /// <returns> The report message. </returns>
+ public IMessage GetReport(IChannel channel)
+ {
+ log.Debug("public IMessage getReport(IChannel channel): called");
+
+ // Close the test connections.
+ foreach (IConnection con in connection)
+ {
+ con.Stop();
+ }
+
+ // Generate a report message containing the count of the number of
messages passed.
+ IMessage report = channel.CreateMessage();
+ report.Headers.SetString("CONTROL_TYPE", "REPORT");
+ report.Headers.SetInt("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /// <summary>
+ /// Counts incoming test messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming test message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void onMessage(IMessage message = " + message +
"): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+}
Added: incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestClient.cs
URL:
http://svn.apache.org/viewvc/incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestClient.cs?view=auto&rev=544508
==============================================================================
--- incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestClient.cs
(added)
+++ incubator/qpid/branches/M2/dotnet/Qpid.Client.Tests/interop/TestClient.cs
Tue Jun 5 08:02:09 2007
@@ -0,0 +1,341 @@
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Text;
+using Qpid.Messaging;
+using Qpid.Client.Qms;
+using log4net;
+using Qpid.Client.Tests.interop.TestCases;
+
+namespace Qpid.Client.Tests.interop
+{
+ /// <summary>
+ /// Implements a test client as described in the interop testing spec
+ ///
(http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification).
A test client is an agent that
+ /// reacts to control message sequences send by the test coordinator.
+ ///
+ /// <p/><table><caption>Messages Handled by TestClient</caption>
+ /// <tr><th> Message <th> Action
+ /// <tr><td> Invite(compulsory) <td> Reply with Enlist.
+ /// <tr><td> Invite(test case) <td> Reply with Enlist if test case
available.
+ /// <tr><td> AssignRole(test case) <td> Reply with Accept Role if matches
an enlisted test. Keep test parameters.
+ /// <tr><td> Start <td> Send test messages defined by test
parameters. Send report on messages sent.
+ /// <tr><td> Status Request <td> Send report on messages received.
+ /// </table>
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Handle all incoming control messages. <td> [EMAIL PROTECTED]
InteropClientTestCase}
+ /// <tr><td> Configure and look up test cases by name. <td> [EMAIL
PROTECTED] InteropClientTestCase}
+ /// </table>
+ /// </summary>
+ class TestClient
+ {
+ private static ILog log = LogManager.GetLogger(typeof(TestClient));
+
+ /// <summary> Defines the default broker for the tests, localhost,
default port. </summary>
+ public static string DEFAULT_BROKER_URL = "amqp://guest:[EMAIL
PROTECTED]/?brokerlist='tcp://localhost:5672'";
+
+ /// <summary> Defines the default virtual host to use for the tests,
none. </summary>
+ public static string DEFAULT_VIRTUAL_HOST = "";
+
+ /// <summary> Defines the default identifying name of this test
client. </summary>
+ public static string DEFAULT_CLIENT_NAME = ".net";
+
+ /// <summary> Holds the URL of the broker to run the tests on.
</summary>
+ public static string brokerUrl;
+
+ /// <summary> Holds the virtual host to run the tests on. If
<tt>null</tt>, then the default virtual host is used. </summary>
+ public static string virtualHost;
+
+ /// <summary> The clients identifying name to print in test results
and to distinguish from other clients. </summary>
+ private string clientName;
+
+ /// <summary> Holds all the test cases. </summary>
+ private IDictionary testCases = new Hashtable();
+
+ InteropClientTestCase currentTestCase;
+
+ private MessagePublisherBuilder publisherBuilder;
+
+ private IChannel channel;
+
+
+ /// <summary>
+ /// Creates a new interop test client, listenting to the specified
broker and virtual host, with the specified
+ /// client identifying name.
+ /// </summary>
+ ///
+ /// <param name="brokerUrl"> The url of the broker to connect to.
</param>
+ /// <param name="virtualHost"> The virtual host to conect to. </param>
+ /// <param name="clientName"> The client name to use. </param>
+ public TestClient(string brokerUrl, string virtualHost, string
clientName)
+ {
+ log.Debug("public TestClient(string brokerUrl = " + brokerUrl + ",
string virtualHost = " + virtualHost
+ + ", string clientName = " + clientName + "): called");
+
+ // Retain the connection parameters.
+ TestClient.brokerUrl = brokerUrl;
+ TestClient.virtualHost = virtualHost;
+ this.clientName = clientName;
+ }
+
+
+ /// <summary>
+ /// The entry point for the interop test coordinator. This client
accepts the following command line arguments:
+ /// </summary>
+ ///
+ /// <p/><table>
+ /// <tr><td> -b <td> The broker URL. <td> Optional.
+ /// <tr><td> -h <td> The virtual host. <td> Optional.
+ /// <tr><td> -n <td> The test client name. <td> Optional.
+ /// <tr><td> name=value <td> Trailing argument define name/value
pairs. Added to system properties. <td> Optional.
+ /// </table>
+ ///
+ /// <param name="args"> The command line arguments. </param>
+ public static void Main(string[] args)
+ {
+ // Extract the command line options (Not exactly Posix but it will
do for now...).
+ string brokerUrl = DEFAULT_BROKER_URL;
+ string virtualHost = DEFAULT_VIRTUAL_HOST;
+ string clientName = DEFAULT_CLIENT_NAME;
+
+ foreach (string nextArg in args)
+ {
+ if (nextArg.StartsWith("-b"))
+ {
+ brokerUrl = nextArg.Substring(2);
+ }
+ else if (nextArg.StartsWith("-h"))
+ {
+ virtualHost = nextArg.Substring(2);
+ }
+ else if (nextArg.StartsWith("-n"))
+ {
+ clientName = nextArg.Substring(2);
+ }
+ }
+
+ // Create a test client and start it running.
+ TestClient client = new TestClient(brokerUrl, virtualHost,
clientName);
+
+ try
+ {
+ client.Start();
+ }
+ catch (Exception e)
+ {
+ log.Error("The test client was unable to start.", e);
+ System.Environment.Exit(1);
+ }
+ }
+
+ /// <summary>
+ /// Starts the interop test client running. This causes it to start
listening for incoming test invites.
+ /// </summary>
+ private void Start()
+ {
+ log.Debug("private void Start(): called");
+
+ // Use a class path scanner to find all the interop test case
implementations.
+ ArrayList testCaseClasses = new ArrayList();
+
+ // ClasspathScanner.getMatches(InteropClientTestCase.class,
"^TestCase.*", true);
+ // Hard code the test classes till the classpath scanner is fixed.
+ testCaseClasses.Add(typeof(TestCase1DummyRun));
+ testCaseClasses.Add(typeof(TestCase2BasicP2P));
+ testCaseClasses.Add(typeof(TestCase3BasicPubSub));
+
+ // Create all the test case implementations and index them by the
test names.
+ foreach (Type testClass in testCaseClasses)
+ {
+ InteropClientTestCase testCase =
(InteropClientTestCase)Activator.CreateInstance(testClass);
+ testCases.Add(testCase.GetName(), testCase);
+ }
+
+ // Open a connection to communicate with the coordinator on.
+ IConnection connection = CreateConnection(brokerUrl, virtualHost);
+
+ channel = connection.CreateChannel(false,
AcknowledgeMode.AutoAcknowledge);
+
+ // Set this up to listen for control messages.
+ string responseQueueName = channel.GenerateUniqueName();
+ channel.DeclareQueue(responseQueueName, false, true, true);
+
+ channel.Bind(responseQueueName, ExchangeNameDefaults.DIRECT,
"iop.control." + clientName);
+ channel.Bind(responseQueueName, ExchangeNameDefaults.DIRECT,
"iop.control");
+
+ IMessageConsumer consumer =
channel.CreateConsumerBuilder(responseQueueName)
+ .Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+
+ // Create a publisher to send replies with.
+ publisherBuilder = channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.DIRECT);
+
+
+ // Start listening for incoming control messages.
+ connection.Start();
+ Console.WriteLine("Test client " + clientName + " ready to receive
test control messages...");
+ }
+
+ /// <summary>
+ /// Establishes an AMQ connection. This is a simple convenience method
for code that does not anticipate handling connection failures.
+ /// All exceptions that indicate that the connection has failed, are
allowed to fall through.
+ /// </summary>
+ ///
+ /// <param name="brokerUrl"> The broker url to connect to,
<tt>null</tt> to use the default from the properties. </param>
+ /// <param name="virtualHost"> The virtual host to connectio to,
<tt>null</tt> to use the default. </param>
+ ///
+ /// <returns> A JMS conneciton. </returns>
+ public static IConnection CreateConnection(string brokerUrl, string
virtualHost)
+ {
+ log.Debug("public static Connection createConnection(string
brokerUrl = " + brokerUrl + ", string virtualHost = "
+ + virtualHost + "): called");
+
+ // Create a connection to the broker.
+ IConnectionInfo connectionInfo =
QpidConnectionInfo.FromUrl(brokerUrl);
+ connectionInfo.VirtualHost = virtualHost;
+ IConnection connection = new AMQConnection(connectionInfo);
+
+ return connection;
+ }
+
+ /// <summary>
+ /// Handles all incoming control messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void OnMessage(IMessage message = " + message +
"): called");
+
+ try
+ {
+ string controlType = message.Headers.GetString("CONTROL_TYPE");
+ string testName = message.Headers.GetString("TEST_NAME");
+
+ // Check if the message is a test invite.
+ if ("INVITE" == controlType)
+ {
+ string testCaseName =
message.Headers.GetString("TEST_NAME");
+
+ // Flag used to indicate that an enlist should be sent.
Only enlist to compulsory invites or invites
+ // for which test cases exist.
+ bool enlist = false;
+
+ if (testCaseName != null)
+ {
+ log.Debug("Got an invite to test: " + testCaseName);
+
+ // Check if the requested test case is available.
+ InteropClientTestCase testCase =
(InteropClientTestCase)testCases[testCaseName];
+
+ if (testCase != null)
+ {
+ // Make the requested test case the current test
case.
+ currentTestCase = testCase;
+ enlist = true;
+ }
+ }
+ else
+ {
+ log.Debug("Got a compulsory invite.");
+
+ enlist = true;
+ }
+
+ if (enlist)
+ {
+ // Reply with the client name in an Enlist message.
+ IMessage enlistMessage = channel.CreateMessage();
+ enlistMessage.Headers.SetString("CONTROL_TYPE",
"ENLIST");
+ enlistMessage.Headers.SetString("CLIENT_NAME",
clientName);
+
enlistMessage.Headers.SetString("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." +
clientName);
+ enlistMessage.CorrelationId = message.CorrelationId;
+
+ Send(enlistMessage, message.ReplyToRoutingKey);
+ }
+ }
+ else if ("ASSIGN_ROLE" == controlType)
+ {
+ // Assign the role to the current test case.
+ string roleName = message.Headers.GetString("ROLE");
+
+ log.Debug("Got a role assignment to role: " + roleName);
+
+ Roles role;
+
+ if (roleName == "SENDER")
+ {
+ role = Roles.SENDER;
+ }
+ else
+ {
+ role = Roles.RECEIVER;
+ }
+
+ currentTestCase.AssignRole(role, message);
+
+ // Reply by accepting the role in an Accept Role message.
+ IMessage acceptRoleMessage = channel.CreateMessage();
+ acceptRoleMessage.Headers.SetString("CONTROL_TYPE",
"ACCEPT_ROLE");
+ acceptRoleMessage.CorrelationId = message.CorrelationId;
+
+ Send(acceptRoleMessage, message.ReplyToRoutingKey);
+ }
+ else if ("START" == controlType || "STATUS_REQUEST" ==
controlType)
+ {
+ if ("START" == 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.
+ IMessage reportMessage =
currentTestCase.GetReport(channel);
+ reportMessage.Headers.SetString("CONTROL_TYPE", "REPORT");
+ reportMessage.CorrelationId = message.CorrelationId;
+
+ Send(reportMessage, message.ReplyToRoutingKey);
+ }
+ else if ("TERMINATE" == controlType)
+ {
+ Console.WriteLine("Received termination instruction from
coordinator.");
+
+ // Is a cleaner shutdown needed?
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ // Log a warning about this but otherwise ignore it.
+ log.Warn("Got an unknown control message, controlType = "
+ controlType + ", message = " + message);
+ }
+ }
+ catch (QpidException e)
+ {
+ // Log a warning about this, but otherwise ignore it.
+ log.Warn("A QpidException occurred whilst handling a
message.");
+ log.Debug("Got QpidException whilst handling message: " +
message, e);
+ }
+ }
+
+ /// <summary>
+ /// Send the specified message using the specified routing key on the
direct exchange.
+ /// </summary>
+ ///
+ /// <param name="message"> The message to send.</param>
+ /// <param name="routingKey"> The routing key to send the message
with.</param>
+ public void Send(IMessage message, string routingKey)
+ {
+ IMessagePublisher publisher =
publisherBuilder.WithRoutingKey(routingKey).Create();
+ publisher.Send(message);
+ }
+ }
+}