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);
+        }
+    }
+}


Reply via email to