//----------------------------------------------------------------------- // // Copyright (c) Andrew Arnott. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOAuth.Test.Messaging { using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Web; using DotNetOAuth.Messaging; using DotNetOAuth.Test.Mocks; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class ChannelTests : TestBase { private Channel channel; [TestInitialize] public override void SetUp() { base.SetUp(); this.channel = new TestChannel(); } [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 DequeueIndirectOrResponseMessageReturnsNull() { Assert.IsNull(this.channel.DequeueIndirectOrResponseMessage()); } [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() { IProtocolMessage message = new TestDirectedMessage(MessageTransport.Indirect) { Age = 15, Name = "Andrew", Location = new Uri("http://host/path"), Recipient = new Uri("http://provider/path"), }; this.channel.Send(message); Response response = this.channel.DequeueIndirectOrResponseMessage(); Assert.AreEqual(HttpStatusCode.Redirect, response.Status); StringAssert.StartsWith(response.Headers[HttpResponseHeader.Location], "http://provider/path"); StringAssert.Contains(response.Headers[HttpResponseHeader.Location], "age=15"); StringAssert.Contains(response.Headers[HttpResponseHeader.Location], "Name=Andrew"); StringAssert.Contains(response.Headers[HttpResponseHeader.Location], "Location=http%3a%2f%2fhost%2fpath"); } [TestMethod, ExpectedException(typeof(ArgumentNullException))] public void SendIndirectMessage301GetNullMessage() { TestBadChannel badChannel = new TestBadChannel(false); badChannel.Create301RedirectResponse(null, new Dictionary()); } [TestMethod, ExpectedException(typeof(ArgumentException))] public void SendIndirectMessage301GetEmptyRecipient() { TestBadChannel badChannel = new TestBadChannel(false); var message = new TestDirectedMessage(MessageTransport.Indirect); badChannel.Create301RedirectResponse(message, new Dictionary()); } [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"); StringAssert.Contains(body, ""); StringAssert.Contains(body, ""); 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()); } [TestMethod, ExpectedException(typeof(ArgumentException))] public void SendIndirectMessageFormPostEmptyRecipient() { TestBadChannel badChannel = new TestBadChannel(false); var message = new TestDirectedMessage(MessageTransport.Indirect); badChannel.CreateFormPostResponse(message, new Dictionary()); } [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); } /// /// Tests that a direct message is sent when the appropriate message type is provided. /// /// /// Since this is a mock channel that doesn't actually formulate a direct message response, /// we just check that the right method was called. /// [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 QueueIndirectOrResponseMessageNull() { TestBadChannel badChannel = new TestBadChannel(false); badChannel.QueueIndirectOrResponseMessage(null); } [TestMethod, ExpectedException(typeof(InvalidOperationException))] public void QueueIndirectOrResponseMessageTwice() { TestBadChannel badChannel = new TestBadChannel(false); Response response = new Response(); badChannel.QueueIndirectOrResponseMessage(new Response()); badChannel.QueueIndirectOrResponseMessage(new Response()); } [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); } [TestMethod] public void ReceiveUnrecognizedMessage() { TestBadChannel badChannel = new TestBadChannel(false); Assert.IsNull(badChannel.Receive(new Dictionary())); } [TestMethod] public void ReadFromRequestWithContext() { // TODO: make this a request with a message in it. HttpRequest request = new HttpRequest("somefile", "http://someurl", "age=15"); HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter())); IProtocolMessage message = this.channel.ReadFromRequest(); Assert.IsNotNull(message); Assert.IsInstanceOfType(message, typeof(TestMessage)); Assert.AreEqual(15, ((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); } private static HttpRequestInfo CreateHttpRequestInfo(string method, IDictionary fields) { string query = MessagingUtilities.CreateQueryString(fields); UriBuilder requestUri = new UriBuilder("http://localhost/path"); WebHeaderCollection headers = new WebHeaderCollection(); MemoryStream ms = new MemoryStream(); if (method == "POST") { headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); StreamWriter sw = new StreamWriter(ms); sw.Write(query); sw.Flush(); ms.Position = 0; } else if (method == "GET") { requestUri.Query = query; } else { throw new ArgumentOutOfRangeException("method", method, "Expected POST or GET"); } HttpRequestInfo request = new HttpRequestInfo { HttpMethod = method, Url = requestUri.Uri, Headers = headers, InputStream = ms, }; return request; } private void ParameterizedReceiveTest(string method) { var fields = new Dictionary { { "age", "15" }, { "Name", "Andrew" }, { "Location", "http://hostb/pathB" }, }; IProtocolMessage requestMessage = this.channel.ReadFromRequest(CreateHttpRequestInfo(method, fields)); Assert.IsNotNull(requestMessage); Assert.IsInstanceOfType(requestMessage, typeof(TestMessage)); TestMessage testMessage = (TestMessage)requestMessage; Assert.AreEqual(15, testMessage.Age); Assert.AreEqual("Andrew", testMessage.Name); Assert.AreEqual("http://hostb/pathB", testMessage.Location.AbsoluteUri); } } }