summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs')
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs
new file mode 100644
index 0000000..4127b5a
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs
@@ -0,0 +1,290 @@
+//-----------------------------------------------------------------------
+// <copyright file="ChannelTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Net;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Messaging.Bindings;
+ using DotNetOpenAuth.Test.Mocks;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class ChannelTests : MessagingTestBase {
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void CtorNull() {
+ // This bad channel is deliberately constructed to pass null to
+ // its protected base class' constructor.
+ new TestBadChannel(true);
+ }
+
+ [TestMethod]
+ public void ReadFromRequestQueryString() {
+ this.ParameterizedReceiveTest("GET");
+ }
+
+ [TestMethod]
+ public void ReadFromRequestForm() {
+ this.ParameterizedReceiveTest("POST");
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void SendNull() {
+ this.Channel.Send(null);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void SendIndirectedUndirectedMessage() {
+ IProtocolMessage message = new TestMessage(MessageTransport.Indirect);
+ this.Channel.Send(message);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void SendDirectedNoRecipientMessage() {
+ IProtocolMessage message = new TestDirectedMessage(MessageTransport.Indirect);
+ this.Channel.Send(message);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void SendInvalidMessageTransport() {
+ IProtocolMessage message = new TestDirectedMessage((MessageTransport)100);
+ this.Channel.Send(message);
+ }
+
+ [TestMethod]
+ public void SendIndirectMessage301Get() {
+ TestDirectedMessage message = new TestDirectedMessage(MessageTransport.Indirect);
+ GetStandardTestMessage(FieldFill.CompleteBeforeBindings, message);
+ message.Recipient = new Uri("http://provider/path");
+ var expected = GetStandardTestFields(FieldFill.CompleteBeforeBindings);
+
+ Response response = this.Channel.Send(message);
+ Assert.AreEqual(HttpStatusCode.Redirect, response.Status);
+ StringAssert.StartsWith(response.Headers[HttpResponseHeader.Location], "http://provider/path");
+ foreach (var pair in expected) {
+ string key = HttpUtility.UrlEncode(pair.Key);
+ string value = HttpUtility.UrlEncode(pair.Value);
+ string substring = string.Format("{0}={1}", key, value);
+ StringAssert.Contains(response.Headers[HttpResponseHeader.Location], substring);
+ }
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void SendIndirectMessage301GetNullMessage() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ badChannel.Create301RedirectResponse(null, new Dictionary<string, string>());
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void SendIndirectMessage301GetEmptyRecipient() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ var message = new TestDirectedMessage(MessageTransport.Indirect);
+ badChannel.Create301RedirectResponse(message, new Dictionary<string, string>());
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void SendIndirectMessage301GetNullFields() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ var message = new TestDirectedMessage(MessageTransport.Indirect);
+ message.Recipient = new Uri("http://someserver");
+ badChannel.Create301RedirectResponse(message, null);
+ }
+
+ [TestMethod]
+ public void SendIndirectMessageFormPost() {
+ // We craft a very large message to force fallback to form POST.
+ // We'll also stick some HTML reserved characters in the string value
+ // to test proper character escaping.
+ var message = new TestDirectedMessage(MessageTransport.Indirect) {
+ Age = 15,
+ Name = "c<b" + new string('a', 10 * 1024),
+ Location = new Uri("http://host/path"),
+ Recipient = new Uri("http://provider/path"),
+ };
+ Response response = this.Channel.Send(message);
+ Assert.AreEqual(HttpStatusCode.OK, response.Status, "A form redirect should be an HTTP successful response.");
+ Assert.IsNull(response.Headers[HttpResponseHeader.Location], "There should not be a redirection header in the response.");
+ string body = response.Body;
+ StringAssert.Contains(body, "<form ");
+ StringAssert.Contains(body, "action=\"http://provider/path\"");
+ StringAssert.Contains(body, "method=\"post\"");
+ StringAssert.Contains(body, "<input type=\"hidden\" name=\"age\" value=\"15\" />");
+ StringAssert.Contains(body, "<input type=\"hidden\" name=\"Location\" value=\"http://host/path\" />");
+ StringAssert.Contains(body, "<input type=\"hidden\" name=\"Name\" value=\"" + HttpUtility.HtmlEncode(message.Name) + "\" />");
+ StringAssert.Contains(body, ".submit()", "There should be some javascript to automate form submission.");
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void SendIndirectMessageFormPostNullMessage() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ badChannel.CreateFormPostResponse(null, new Dictionary<string, string>());
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void SendIndirectMessageFormPostEmptyRecipient() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ var message = new TestDirectedMessage(MessageTransport.Indirect);
+ badChannel.CreateFormPostResponse(message, new Dictionary<string, string>());
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void SendIndirectMessageFormPostNullFields() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ var message = new TestDirectedMessage(MessageTransport.Indirect);
+ message.Recipient = new Uri("http://someserver");
+ badChannel.CreateFormPostResponse(message, null);
+ }
+
+ /// <summary>
+ /// Tests that a direct message is sent when the appropriate message type is provided.
+ /// </summary>
+ /// <remarks>
+ /// Since this is a mock channel that doesn't actually formulate a direct message response,
+ /// we just check that the right method was called.
+ /// </remarks>
+ [TestMethod, ExpectedException(typeof(NotImplementedException), "SendDirectMessageResponse")]
+ public void SendDirectMessageResponse() {
+ IProtocolMessage message = new TestMessage {
+ Age = 15,
+ Name = "Andrew",
+ Location = new Uri("http://host/path"),
+ };
+ this.Channel.Send(message);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void SendIndirectMessageNull() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ badChannel.SendIndirectMessage(null);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void ReceiveNull() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ badChannel.Receive(null, null);
+ }
+
+ [TestMethod]
+ public void ReceiveUnrecognizedMessage() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ Assert.IsNull(badChannel.Receive(new Dictionary<string, string>(), null));
+ }
+
+ [TestMethod]
+ public void ReadFromRequestWithContext() {
+ var fields = GetStandardTestFields(FieldFill.AllRequired);
+ TestMessage expectedMessage = GetStandardTestMessage(FieldFill.AllRequired);
+ HttpRequest request = new HttpRequest("somefile", "http://someurl", MessagingUtilities.CreateQueryString(fields));
+ HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
+ IProtocolMessage message = this.Channel.ReadFromRequest();
+ Assert.IsNotNull(message);
+ Assert.IsInstanceOfType(message, typeof(TestMessage));
+ Assert.AreEqual(expectedMessage.Age, ((TestMessage)message).Age);
+ }
+
+ [TestMethod, ExpectedException(typeof(InvalidOperationException))]
+ public void ReadFromRequestNoContext() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ badChannel.ReadFromRequest();
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void ReadFromRequestNull() {
+ TestBadChannel badChannel = new TestBadChannel(false);
+ badChannel.ReadFromRequest(null);
+ }
+
+ [TestMethod]
+ public void SendReplayProtectedMessageSetsNonce() {
+ TestReplayProtectedMessage message = new TestReplayProtectedMessage(MessageTransport.Indirect);
+ message.Recipient = new Uri("http://localtest");
+
+ this.Channel = CreateChannel(MessageProtections.ReplayProtection);
+ this.Channel.Send(message);
+ Assert.IsNotNull(((IReplayProtectedProtocolMessage)message).Nonce);
+ }
+
+ [TestMethod, ExpectedException(typeof(InvalidSignatureException))]
+ public void ReceivedInvalidSignature() {
+ this.Channel = CreateChannel(MessageProtections.TamperProtection);
+ this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, true);
+ }
+
+ [TestMethod]
+ public void ReceivedReplayProtectedMessageJustOnce() {
+ this.Channel = CreateChannel(MessageProtections.ReplayProtection);
+ this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
+ }
+
+ [TestMethod, ExpectedException(typeof(ReplayedMessageException))]
+ public void ReceivedReplayProtectedMessageTwice() {
+ this.Channel = CreateChannel(MessageProtections.ReplayProtection);
+ this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
+ this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
+ }
+
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void MessageExpirationWithoutTamperResistance() {
+ new TestChannel(
+ new TestMessageTypeProvider(),
+ new StandardExpirationBindingElement());
+ }
+
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void TooManyBindingElementsProvidingSameProtection() {
+ new TestChannel(
+ new TestMessageTypeProvider(),
+ new MockSigningBindingElement(),
+ new MockSigningBindingElement());
+ }
+
+ [TestMethod]
+ public void BindingElementsOrdering() {
+ IChannelBindingElement transformA = new MockTransformationBindingElement("a");
+ IChannelBindingElement transformB = new MockTransformationBindingElement("b");
+ IChannelBindingElement sign = new MockSigningBindingElement();
+ IChannelBindingElement replay = new MockReplayProtectionBindingElement();
+ IChannelBindingElement expire = new StandardExpirationBindingElement();
+
+ Channel channel = new TestChannel(
+ new TestMessageTypeProvider(),
+ sign,
+ replay,
+ expire,
+ transformB,
+ transformA);
+
+ Assert.AreEqual(5, channel.BindingElements.Count);
+ Assert.AreSame(transformB, channel.BindingElements[0]);
+ Assert.AreSame(transformA, channel.BindingElements[1]);
+ Assert.AreSame(replay, channel.BindingElements[2]);
+ Assert.AreSame(expire, channel.BindingElements[3]);
+ Assert.AreSame(sign, channel.BindingElements[4]);
+ }
+
+ [TestMethod, ExpectedException(typeof(UnprotectedMessageException))]
+ public void InsufficientlyProtectedMessageSent() {
+ var message = new TestSignedDirectedMessage(MessageTransport.Direct);
+ message.Recipient = new Uri("http://localtest");
+ this.Channel.Send(message);
+ }
+
+ [TestMethod, ExpectedException(typeof(UnprotectedMessageException))]
+ public void InsufficientlyProtectedMessageReceived() {
+ this.Channel = CreateChannel(MessageProtections.None, MessageProtections.TamperProtection);
+ this.ParameterizedReceiveProtectedTest(DateTime.Now, false);
+ }
+
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void IncomingMessageMissingRequiredParameters() {
+ var fields = GetStandardTestFields(FieldFill.IdentifiableButNotAllRequired);
+ this.Channel.ReadFromRequest(CreateHttpRequestInfo("GET", fields));
+ }
+ }
+}