diff options
Diffstat (limited to 'src/DotNetOpenAuth.Test')
11 files changed, 102 insertions, 54 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index 2bcec94..43beea0 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -52,6 +52,9 @@ <Reference Include="System.Runtime.Serialization"> <RequiredTargetFramework>3.0</RequiredTargetFramework> </Reference> + <Reference Include="System.ServiceModel"> + <RequiredTargetFramework>3.0</RequiredTargetFramework> + </Reference> <Reference Include="System.Web" /> <Reference Include="System.Xml" /> <Reference Include="System.Xml.Linq"> diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs index ed0cb10..4598a9f 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs @@ -11,7 +11,9 @@ namespace DotNetOpenAuth.Test.Mocks { using System.Text; using System.Threading; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.Messaging.Reflection; using DotNetOpenAuth.Test.OpenId; + using Microsoft.VisualStudio.TestTools.UnitTesting; internal class CoordinatingChannel : Channel { /// <summary> @@ -52,7 +54,9 @@ namespace DotNetOpenAuth.Test.Mocks { /// An incoming message that has been posted by a remote channel and /// is waiting for receipt by this channel. /// </summary> - private IProtocolMessage incomingMessage; + private IDictionary<string, string> incomingMessage; + + private MessageReceivingEndpoint incomingMessageRecipient; /// <summary> /// A delegate that gets a chance to peak at and fiddle with all @@ -104,6 +108,8 @@ namespace DotNetOpenAuth.Test.Mocks { TestUtilities.TestLogger.Debug("CoordinatingChannel is closing while remote channel is waiting for an incoming message. Signaling channel to unblock it to receive a null message."); this.RemoteChannel.incomingMessageSignal.Set(); } + + this.Dispose(); } } @@ -115,32 +121,60 @@ namespace DotNetOpenAuth.Test.Mocks { this.VerifyMessageAfterReceiving(CloneSerializedParts(message)); } + /// <summary> + /// Called from a remote party's thread to post a message to this channel for processing. + /// </summary> + /// <param name="message">The message that this channel should receive. This message will be cloned.</param> internal void PostMessage(IProtocolMessage message) { ErrorUtilities.VerifyInternal(this.incomingMessage == null, "Oops, a message is already waiting for the remote party!"); - this.incomingMessage = CloneSerializedParts(message); + this.incomingMessage = new Dictionary<string, string>(new MessageDictionary(message)); + var directedMessage = message as IDirectedProtocolMessage; + this.incomingMessageRecipient = directedMessage != null ? new MessageReceivingEndpoint(directedMessage.Recipient, directedMessage.HttpMethods) : null; this.incomingMessageSignal.Set(); } protected internal override HttpRequestInfo GetRequestFromContext() { - return new HttpRequestInfo((IDirectedProtocolMessage)this.AwaitIncomingMessage()); + MessageReceivingEndpoint recipient; + var messageData = this.AwaitIncomingMessage(out recipient); + IDirectedProtocolMessage message = null; + if (messageData != null) { + message = this.MessageFactory.GetNewRequestMessage(recipient, messageData); + if (message != null) { + MessageSerializer.Get(message.GetType()).Deserialize(messageData, message); + } + return new HttpRequestInfo(message, recipient.AllowedMethods); + } else { + return new HttpRequestInfo(null, HttpDeliveryMethods.GetRequest); + } } protected override IProtocolMessage RequestInternal(IDirectedProtocolMessage request) { this.ProcessMessageFilter(request, true); - HttpRequestInfo requestInfo = this.SpoofHttpMethod(request); + // Drop the outgoing message in the other channel's in-slot and let them know it's there. - ErrorUtilities.VerifyInternal(this.RemoteChannel.incomingMessage == null, "Oops, a message is already waiting for the remote party!"); - this.RemoteChannel.incomingMessage = requestInfo.Message; - this.RemoteChannel.incomingMessageSignal.Set(); + this.RemoteChannel.PostMessage(request); + // Now wait for a response... - IProtocolMessage response = this.AwaitIncomingMessage(); - this.ProcessMessageFilter(response, false); - return response; + MessageReceivingEndpoint recipient; + IDictionary<string, string> responseData = this.AwaitIncomingMessage(out recipient); + ErrorUtilities.VerifyInternal(recipient == null, "The recipient is expected to be null for direct responses."); + + // And deserialize it. + IDirectResponseProtocolMessage responseMessage = this.MessageFactory.GetNewResponseMessage(request, responseData); + if (responseMessage == null) { + return null; + } + + var responseSerializer = MessageSerializer.Get(responseMessage.GetType()); + responseSerializer.Deserialize(responseData, responseMessage); + + this.ProcessMessageFilter(responseMessage, false); + return responseMessage; } protected override UserAgentResponse SendDirectMessageResponse(IProtocolMessage response) { this.ProcessMessageFilter(response, true); - return new CoordinatingUserAgentResponse(CloneSerializedParts(response), this.RemoteChannel); + return new CoordinatingUserAgentResponse(response, this.RemoteChannel); } protected override UserAgentResponse SendIndirectMessage(IDirectedProtocolMessage message) { @@ -168,18 +202,16 @@ namespace DotNetOpenAuth.Test.Mocks { } /// <summary> - /// Spoof HTTP request information for signing/verification purposes. + /// Clones a message, instantiating the new instance using <i>this</i> channel's + /// message factory. /// </summary> - /// <param name="message">The message to add a pretend HTTP method to.</param> - /// <returns>A spoofed HttpRequestInfo that wraps the new message.</returns> - protected virtual HttpRequestInfo SpoofHttpMethod(IDirectedProtocolMessage message) { - HttpRequestInfo requestInfo = new HttpRequestInfo(message); - - requestInfo.Message = this.CloneSerializedParts(message); - - return requestInfo; - } - + /// <typeparam name="T">The type of message to clone.</typeparam> + /// <param name="message">The message to clone.</param> + /// <returns>The new instance of the message.</returns> + /// <remarks> + /// This Clone method should <i>not</i> be used to send message clones to the remote + /// channel since their message factory is not used. + /// </remarks> protected virtual T CloneSerializedParts<T>(T message) where T : class, IProtocolMessage { ErrorUtilities.VerifyArgumentNotNull(message, "message"); @@ -195,9 +227,9 @@ namespace DotNetOpenAuth.Test.Mocks { recipient = new MessageReceivingEndpoint(directedMessage.Recipient, directedMessage.HttpMethods); } - clonedMessage = this.RemoteChannel.MessageFactory.GetNewRequestMessage(recipient, fields); + clonedMessage = this.MessageFactory.GetNewRequestMessage(recipient, fields); } else if (directResponse != null && directResponse.IsDirectResponse()) { - clonedMessage = this.RemoteChannel.MessageFactory.GetNewResponseMessage(directResponse.OriginatingRequest, fields); + clonedMessage = this.MessageFactory.GetNewResponseMessage(directResponse.OriginatingRequest, fields); } else { throw new InvalidOperationException("Totally expected a message to implement one of the two derived interface types."); } @@ -217,7 +249,7 @@ namespace DotNetOpenAuth.Test.Mocks { return accessor.MessageFactory; } - private IProtocolMessage AwaitIncomingMessage() { + private IDictionary<string, string> AwaitIncomingMessage(out MessageReceivingEndpoint recipient) { // Special care should be taken so that we don't indefinitely // wait for a message that may never come due to a bug in the product // or the test. @@ -241,8 +273,10 @@ namespace DotNetOpenAuth.Test.Mocks { lock (waitingForMessageCoordinationLock) { this.waitingForMessage = false; - IProtocolMessage response = this.incomingMessage; + var response = this.incomingMessage; + recipient = this.incomingMessageRecipient; this.incomingMessage = null; + this.incomingMessageRecipient = null; return response; } } diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs index 05d1fd4..f00c356 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs @@ -58,7 +58,8 @@ namespace DotNetOpenAuth.Test.Mocks { } protected internal override HttpRequestInfo GetRequestFromContext() { - return new HttpRequestInfo((IDirectedProtocolMessage)this.AwaitIncomingMessage()); + var directedMessage = (IDirectedProtocolMessage)this.AwaitIncomingMessage(); + return new HttpRequestInfo(directedMessage, directedMessage.HttpMethods); } protected override IProtocolMessage RequestInternal(IDirectedProtocolMessage request) { @@ -91,7 +92,7 @@ namespace DotNetOpenAuth.Test.Mocks { /// <param name="message">The message to add a pretend HTTP method to.</param> /// <returns>A spoofed HttpRequestInfo that wraps the new message.</returns> private HttpRequestInfo SpoofHttpMethod(IDirectedProtocolMessage message) { - HttpRequestInfo requestInfo = new HttpRequestInfo(message); + HttpRequestInfo requestInfo = new HttpRequestInfo(message, message.HttpMethods); var signedMessage = message as ITamperResistantOAuthMessage; if (signedMessage != null) { diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingUserAgentResponse.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingUserAgentResponse.cs index 4897e98..75c68e0 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingUserAgentResponse.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingUserAgentResponse.cs @@ -14,6 +14,11 @@ namespace DotNetOpenAuth.Test.Mocks { internal class CoordinatingUserAgentResponse : UserAgentResponse { private CoordinatingChannel receivingChannel; + /// <summary> + /// Initializes a new instance of the <see cref="CoordinatingUserAgentResponse"/> class. + /// </summary> + /// <param name="message">The direct response message to send to the remote channel. This message will be cloned.</param> + /// <param name="receivingChannel">The receiving channel.</param> internal CoordinatingUserAgentResponse(IProtocolMessage message, CoordinatingChannel receivingChannel) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); ErrorUtilities.VerifyArgumentNotNull(receivingChannel, "receivingChannel"); diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs index 8739ead..01c2cf5 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs @@ -143,7 +143,7 @@ namespace DotNetOpenAuth.Test.OpenId { var request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send a response that suggests a foreign association type. - AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request); + AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = "HMAC-UNKNOWN"; renegotiateResponse.SessionType = "DH-UNKNOWN"; op.Channel.Send(renegotiateResponse); @@ -167,7 +167,7 @@ namespace DotNetOpenAuth.Test.OpenId { var request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send a response that suggests a no encryption. - AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request); + AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA1; renegotiateResponse.SessionType = protocol.Args.SessionType.NoEncryption; op.Channel.Send(renegotiateResponse); @@ -192,7 +192,7 @@ namespace DotNetOpenAuth.Test.OpenId { var request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send a mismatched response - AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request); + AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA1; renegotiateResponse.SessionType = protocol.Args.SessionType.DH_SHA256; op.Channel.Send(renegotiateResponse); @@ -217,7 +217,7 @@ namespace DotNetOpenAuth.Test.OpenId { var request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send a renegotiate response - AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request); + AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA1; renegotiateResponse.SessionType = protocol.Args.SessionType.DH_SHA1; op.Channel.Send(renegotiateResponse); @@ -226,7 +226,7 @@ namespace DotNetOpenAuth.Test.OpenId { request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send ANOTHER renegotiate response, at which point the DNOI RP should give up. - renegotiateResponse = new AssociateUnsuccessfulResponse(request); + renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA256; renegotiateResponse.SessionType = protocol.Args.SessionType.DH_SHA256; op.Channel.Send(renegotiateResponse); diff --git a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs index b20886b..d0966e7 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs @@ -134,14 +134,14 @@ namespace DotNetOpenAuth.Test.OpenId { if (positive && !sharedAssociation) { var checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>(); - var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest); + var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest); checkauthResponse.IsValid = checkauthRequest.IsValid; op.Channel.Send(checkauthResponse); if (!tamper) { // Respond to the replay attack. checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>(); - checkauthResponse = new CheckAuthenticationResponse(checkauthRequest); + checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest); checkauthResponse.IsValid = checkauthRequest.IsValid; op.Channel.Send(checkauthResponse); } diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs index 16f76cf..89609f6 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs @@ -18,7 +18,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { [TestInitialize] public void Setup() { var request = new AssociateUnencryptedRequest(Protocol.V20.Version, new Uri("http://host")); - this.response = new AssociateUnencryptedResponse(request); + this.response = new AssociateUnencryptedResponse(request.Version, request); } [TestMethod] diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs index b6f6914..e803400 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs @@ -18,7 +18,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { [TestInitialize] public void Setup() { var request = new AssociateUnencryptedRequest(Protocol.V20.Version, new Uri("http://host")); - this.response = new AssociateUnsuccessfulResponse(request); + this.response = new AssociateUnsuccessfulResponse(request.Version, request); } [TestMethod] diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs index afd3e0f..3a5e824 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs @@ -21,7 +21,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { base.SetUp(); var request = new AssociateUnencryptedRequest(Protocol.V20.Version, new Uri("http://host")); - this.response = new DirectErrorResponse(request); + this.response = new DirectErrorResponse(request.Version, request); } [TestMethod] diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs index 6db5d1b..b45dc1b 100644 --- a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs +++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs @@ -126,8 +126,12 @@ namespace DotNetOpenAuth.Test.OpenId { /// This is a very useful method to pass to the OpenIdCoordinator constructor for the Provider argument. /// </remarks> internal void AutoProvider(OpenIdProvider provider) { - IRequest request; - while ((request = provider.GetRequest()) != null) { + while (!((CoordinatingChannel)provider.Channel).RemoteChannel.IsDisposed) { + IRequest request = provider.GetRequest(); + if (request == null) { + continue; + } + if (!request.IsResponseReady) { var authRequest = (DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest)request; switch (this.AutoProviderScenario) { diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs index bb035c3..114a135 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs @@ -101,21 +101,22 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { coordinator.Run(); } - ////[TestMethod] - ////public void BadRequestsGenerateValidErrorResponses() { - //// var coordinator = new OpenIdCoordinator( - //// rp => { - //// var nonOpenIdMessage = new Mocks.TestDirectedMessage(); - //// nonOpenIdMessage.Recipient = OPUri; - //// nonOpenIdMessage.HttpMethods = HttpDeliveryMethods.PostRequest; - //// MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, nonOpenIdMessage); - //// var response = rp.Channel.Request<DirectErrorResponse>(nonOpenIdMessage); - //// Assert.IsNotNull(response.ErrorMessage); - //// }, - //// AutoProvider); + [TestMethod] + public void BadRequestsGenerateValidErrorResponses() { + var coordinator = new OpenIdCoordinator( + rp => { + var nonOpenIdMessage = new Mocks.TestDirectedMessage(); + nonOpenIdMessage.Recipient = OPUri; + nonOpenIdMessage.HttpMethods = HttpDeliveryMethods.PostRequest; + MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, nonOpenIdMessage); + var response = rp.Channel.Request<DirectErrorResponse>(nonOpenIdMessage); + Assert.IsNotNull(response.ErrorMessage); + Assert.AreEqual(Protocol.Default.Version, response.Version); + }, + AutoProvider); - //// coordinator.Run(); - ////} + coordinator.Run(); + } [TestMethod] public void BadRequestsGenerateValidErrorResponsesHosted() { |